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