1use client::User;
2use gpui::{
3 elements::*,
4 platform::{CursorStyle, MouseButton},
5 Action, AnyElement, Element, View, ViewContext,
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 ViewContext<V>,
20) -> AnyElement<V> {
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 }))
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 )
51 .with_child(
52 MouseEventHandler::<Dismiss, V>::new(user.id as usize, cx, |state, _| {
53 let style = theme.dismiss_button.style_for(state, false);
54 Svg::new("icons/x_mark_8.svg")
55 .with_color(style.color)
56 .constrained()
57 .with_width(style.icon_width)
58 .aligned()
59 .contained()
60 .with_style(style.container)
61 .constrained()
62 .with_width(style.button_width)
63 .with_height(style.button_width)
64 })
65 .with_cursor_style(CursorStyle::PointingHand)
66 .with_padding(Padding::uniform(5.))
67 .on_click(MouseButton::Left, move |_, _, cx| {
68 cx.dispatch_any_action(dismiss_action.boxed_clone())
69 })
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, action))| {
94 MouseEventHandler::<Button, V>::new(ix, cx, |state, _| {
95 let button = theme.button.style_for(state, false);
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 |_, _, cx| {
102 cx.dispatch_any_action(action.boxed_clone())
103 })
104 },
105 ))
106 .aligned()
107 .right(),
108 )
109 })
110 .contained()
111 .into_any()
112}