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