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