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