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