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