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