1use client::User;
2use gpui::{
3 elements::*,
4 platform::{CursorStyle, MouseButton},
5 AnyElement, AppContext, Element, ViewContext,
6};
7use std::sync::Arc;
8use workspace::AppState;
9
10pub mod contact_notification;
11pub mod incoming_call_notification;
12pub mod project_shared_notification;
13
14enum Dismiss {}
15enum Button {}
16
17pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
18 incoming_call_notification::init(app_state, cx);
19 project_shared_notification::init(app_state, cx);
20}
21
22pub fn render_user_notification<F, V: 'static>(
23 user: Arc<User>,
24 title: &'static str,
25 body: Option<&'static str>,
26 on_dismiss: F,
27 buttons: Vec<(&'static str, Box<dyn Fn(&mut V, &mut ViewContext<V>)>)>,
28 cx: &mut ViewContext<V>,
29) -> AnyElement<V>
30where
31 F: 'static + Fn(&mut V, &mut ViewContext<V>),
32{
33 let theme = theme::current(cx).clone();
34 let theme = &theme.contact_notification;
35
36 Flex::column()
37 .with_child(
38 Flex::row()
39 .with_children(user.avatar.clone().map(|avatar| {
40 Image::from_data(avatar)
41 .with_style(theme.header_avatar)
42 .aligned()
43 .constrained()
44 .with_height(
45 cx.font_cache()
46 .line_height(theme.header_message.text.font_size),
47 )
48 .aligned()
49 .top()
50 }))
51 .with_child(
52 Text::new(
53 format!("{} {}", user.github_login, title),
54 theme.header_message.text.clone(),
55 )
56 .contained()
57 .with_style(theme.header_message.container)
58 .aligned()
59 .top()
60 .left()
61 .flex(1., true),
62 )
63 .with_child(
64 MouseEventHandler::new::<Dismiss, _>(user.id as usize, cx, |state, _| {
65 let style = theme.dismiss_button.style_for(state);
66 Svg::new("icons/x.svg")
67 .with_color(style.color)
68 .constrained()
69 .with_width(style.icon_width)
70 .aligned()
71 .contained()
72 .with_style(style.container)
73 .constrained()
74 .with_width(style.button_width)
75 .with_height(style.button_width)
76 })
77 .with_cursor_style(CursorStyle::PointingHand)
78 .with_padding(Padding::uniform(5.))
79 .on_click(MouseButton::Left, move |_, view, cx| on_dismiss(view, cx))
80 .aligned()
81 .constrained()
82 .with_height(
83 cx.font_cache()
84 .line_height(theme.header_message.text.font_size),
85 )
86 .aligned()
87 .top()
88 .flex_float(),
89 )
90 .into_any_named("contact notification header"),
91 )
92 .with_children(body.map(|body| {
93 Label::new(body, theme.body_message.text.clone())
94 .contained()
95 .with_style(theme.body_message.container)
96 }))
97 .with_children(if buttons.is_empty() {
98 None
99 } else {
100 Some(
101 Flex::row()
102 .with_children(buttons.into_iter().enumerate().map(
103 |(ix, (message, handler))| {
104 MouseEventHandler::new::<Button, _>(ix, cx, |state, _| {
105 let button = theme.button.style_for(state);
106 Label::new(message, button.text.clone())
107 .contained()
108 .with_style(button.container)
109 })
110 .with_cursor_style(CursorStyle::PointingHand)
111 .on_click(MouseButton::Left, move |_, view, cx| handler(view, cx))
112 },
113 ))
114 .aligned()
115 .right(),
116 )
117 })
118 .contained()
119 .into_any()
120}