1use gpui::{AnyElement, SharedUri, prelude::*};
2use smallvec::SmallVec;
3
4use crate::{Avatar, prelude::*};
5
6#[derive(IntoElement, RegisterComponent)]
7pub struct CollabNotification {
8 avatar_uri: SharedUri,
9 accept_button: Button,
10 dismiss_button: Button,
11 children: SmallVec<[AnyElement; 2]>,
12}
13
14impl CollabNotification {
15 pub fn new(
16 avatar_uri: impl Into<SharedUri>,
17 accept_button: Button,
18 dismiss_button: Button,
19 ) -> Self {
20 Self {
21 avatar_uri: avatar_uri.into(),
22 accept_button,
23 dismiss_button,
24 children: SmallVec::new(),
25 }
26 }
27}
28
29impl ParentElement for CollabNotification {
30 fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
31 self.children.extend(elements)
32 }
33}
34
35impl RenderOnce for CollabNotification {
36 fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
37 h_flex()
38 .p_2()
39 .size_full()
40 .text_ui(cx)
41 .justify_between()
42 .overflow_hidden()
43 .elevation_3(cx)
44 .gap_1()
45 .child(
46 h_flex()
47 .min_w_0()
48 .gap_4()
49 .child(Avatar::new(self.avatar_uri).size(px(40.)))
50 .child(v_flex().truncate().children(self.children)),
51 )
52 .child(
53 v_flex()
54 .items_center()
55 .child(self.accept_button)
56 .child(self.dismiss_button),
57 )
58 }
59}
60
61impl Component for CollabNotification {
62 fn scope() -> ComponentScope {
63 ComponentScope::Collaboration
64 }
65
66 fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {
67 let avatar = "https://avatars.githubusercontent.com/u/67129314?v=4";
68 let container = || div().h(px(72.)).w(px(400.)); // Size of the actual notification window
69
70 let call_examples = vec![
71 single_example(
72 "Incoming Call",
73 container()
74 .child(
75 CollabNotification::new(
76 avatar,
77 Button::new("accept", "Accept"),
78 Button::new("decline", "Decline"),
79 )
80 .child(Label::new("the user is inviting you to a call")),
81 )
82 .into_any_element(),
83 ),
84 single_example(
85 "Screen Share Request",
86 container()
87 .child(
88 CollabNotification::new(
89 avatar,
90 Button::new("accept", "View"),
91 Button::new("decline", "Ignore"),
92 )
93 .child(Label::new("the user is sharing their screen")),
94 )
95 .into_any_element(),
96 ),
97 single_example(
98 "Project Shared",
99 container()
100 .child(
101 CollabNotification::new(
102 avatar,
103 Button::new("accept", "Open"),
104 Button::new("decline", "Dismiss"),
105 )
106 .child(Label::new("the user is sharing a project"))
107 .child(Label::new("zed").color(Color::Muted)),
108 )
109 .into_any_element(),
110 ),
111 single_example(
112 "Overflowing Content",
113 container()
114 .child(
115 CollabNotification::new(
116 avatar,
117 Button::new("accept", "Accept"),
118 Button::new("decline", "Decline"),
119 )
120 .child(Label::new(
121 "a_very_long_username_that_might_overflow is sharing a project in Zed:",
122 ))
123 .child(
124 Label::new("zed-cloud, zed, edit-prediction-bench, zed.dev")
125 .color(Color::Muted),
126 ),
127 )
128 .into_any_element(),
129 ),
130 ];
131
132 let toast_examples = vec![
133 single_example(
134 "Contact Request",
135 container()
136 .child(
137 CollabNotification::new(
138 avatar,
139 Button::new("accept", "Accept"),
140 Button::new("decline", "Decline"),
141 )
142 .child(Label::new("maxbrunsfeld wants to add you as a contact")),
143 )
144 .into_any_element(),
145 ),
146 single_example(
147 "Contact Request Accepted",
148 container()
149 .child(
150 CollabNotification::new(
151 avatar,
152 Button::new("dismiss", "Dismiss"),
153 Button::new("close", "Close"),
154 )
155 .child(Label::new("maxbrunsfeld accepted your contact request")),
156 )
157 .into_any_element(),
158 ),
159 single_example(
160 "Channel Invitation",
161 container()
162 .child(
163 CollabNotification::new(
164 avatar,
165 Button::new("accept", "Accept"),
166 Button::new("decline", "Decline"),
167 )
168 .child(Label::new(
169 "maxbrunsfeld invited you to join the #zed channel",
170 )),
171 )
172 .into_any_element(),
173 ),
174 ];
175
176 Some(
177 v_flex()
178 .gap_6()
179 .child(example_group_with_title("Calls & Projects", call_examples).vertical())
180 .child(
181 example_group_with_title("Contact & Channel Toasts", toast_examples).vertical(),
182 )
183 .into_any_element(),
184 )
185 }
186}