1use crate::prelude::*;
2use crate::{
3 static_collab_panel_channels, static_collab_panel_current_call, v_stack, Icon, List,
4 ListHeader, ToggleState,
5};
6use gpui2::{img, svg, SharedString};
7use std::marker::PhantomData;
8
9#[derive(Element)]
10pub struct CollabPanel<S: 'static + Send + Sync> {
11 id: ElementId,
12 state_type: PhantomData<S>,
13}
14
15impl<S: 'static + Send + Sync> CollabPanel<S> {
16 pub fn new(id: impl Into<ElementId>) -> Self {
17 Self {
18 id: id.into(),
19 state_type: PhantomData,
20 }
21 }
22
23 fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
24 let color = ThemeColor::new(cx);
25
26 v_stack()
27 .id(self.id.clone())
28 .h_full()
29 .bg(color.surface)
30 .child(
31 v_stack()
32 .id("crdb")
33 .w_full()
34 .overflow_y_scroll()
35 .child(
36 div().pb_1().border_color(color.border).border_b().child(
37 List::new(static_collab_panel_current_call())
38 .header(
39 ListHeader::new("CRDB")
40 .set_left_icon(Icon::Hash.into())
41 .set_toggle(ToggleState::Toggled),
42 )
43 .set_toggle(ToggleState::Toggled),
44 ),
45 )
46 .child(
47 v_stack().id("channels").py_1().child(
48 List::new(static_collab_panel_channels())
49 .header(
50 ListHeader::new("CHANNELS").set_toggle(ToggleState::Toggled),
51 )
52 .empty_message("No channels yet. Add a channel to get started.")
53 .set_toggle(ToggleState::Toggled),
54 ),
55 )
56 .child(
57 v_stack().id("contacts-online").py_1().child(
58 List::new(static_collab_panel_current_call())
59 .header(
60 ListHeader::new("CONTACTS – ONLINE")
61 .set_toggle(ToggleState::Toggled),
62 )
63 .set_toggle(ToggleState::Toggled),
64 ),
65 )
66 .child(
67 v_stack().id("contacts-offline").py_1().child(
68 List::new(static_collab_panel_current_call())
69 .header(
70 ListHeader::new("CONTACTS – OFFLINE")
71 .set_toggle(ToggleState::NotToggled),
72 )
73 .set_toggle(ToggleState::NotToggled),
74 ),
75 ),
76 )
77 .child(
78 div()
79 .h_7()
80 .px_2()
81 .border_t()
82 .border_color(color.border)
83 .flex()
84 .items_center()
85 .child(
86 div()
87 .text_sm()
88 .text_color(color.text_placeholder)
89 .child("Find..."),
90 ),
91 )
92 }
93
94 fn list_section_header(
95 &self,
96 label: impl Into<SharedString>,
97 expanded: bool,
98 cx: &WindowContext,
99 ) -> impl Element<ViewState = S> {
100 let color = ThemeColor::new(cx);
101 div()
102 .h_7()
103 .px_2()
104 .flex()
105 .justify_between()
106 .items_center()
107 .child(div().flex().gap_1().text_sm().child(label.into()))
108 .child(
109 div().flex().h_full().gap_1().items_center().child(
110 svg()
111 .path(if expanded {
112 "icons/caret_down.svg"
113 } else {
114 "icons/caret_up.svg"
115 })
116 .w_3p5()
117 .h_3p5()
118 .text_color(color.icon_muted),
119 ),
120 )
121 }
122
123 fn list_item(
124 &self,
125 avatar_uri: impl Into<SharedString>,
126 label: impl Into<SharedString>,
127 cx: &WindowContext,
128 ) -> impl Element<ViewState = S> {
129 let color = ThemeColor::new(cx);
130
131 div()
132 .id("list_item")
133 .h_7()
134 .px_2()
135 .flex()
136 .items_center()
137 .hover(|style| style.bg(color.ghost_element_hover))
138 .active(|style| style.bg(color.ghost_element_active))
139 .child(
140 div()
141 .flex()
142 .items_center()
143 .gap_1()
144 .text_sm()
145 .child(
146 img()
147 .uri(avatar_uri)
148 .size_3p5()
149 .rounded_full()
150 .bg(color.image_fallback_background),
151 )
152 .child(label.into()),
153 )
154 }
155}
156
157#[cfg(feature = "stories")]
158pub use stories::*;
159
160#[cfg(feature = "stories")]
161mod stories {
162 use crate::Story;
163
164 use super::*;
165
166 #[derive(Element)]
167 pub struct CollabPanelStory<S: 'static + Send + Sync> {
168 state_type: PhantomData<S>,
169 }
170
171 impl<S: 'static + Send + Sync> CollabPanelStory<S> {
172 pub fn new() -> Self {
173 Self {
174 state_type: PhantomData,
175 }
176 }
177
178 fn render(
179 &mut self,
180 _view: &mut S,
181 cx: &mut ViewContext<S>,
182 ) -> impl Element<ViewState = S> {
183 Story::container(cx)
184 .child(Story::title_for::<_, CollabPanel<S>>(cx))
185 .child(Story::label(cx, "Default"))
186 .child(CollabPanel::new("collab-panel"))
187 }
188 }
189}