Skip to main content

ui/components/collab/
collab_notification.rs

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("app").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 the app:",
122                        ))
123                        .child(
124                            Label::new("app-cloud, app, edit-prediction-bench, example.com")
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 #app 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}