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, MouseButton, 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/x_mark_thin_8.svg",
59 )
60 .boxed()
61 })
62 .with_cursor_style(CursorStyle::PointingHand)
63 .with_padding(Padding::uniform(5.))
64 .on_click(MouseButton::Left, move |_, cx| {
65 cx.dispatch_any_action(dismiss_action.boxed_clone())
66 })
67 .aligned()
68 .constrained()
69 .with_height(
70 cx.font_cache()
71 .line_height(theme.header_message.text.font_size),
72 )
73 .aligned()
74 .top()
75 .flex_float()
76 .boxed(),
77 )
78 .named("contact notification header"),
79 )
80 .with_children(body.map(|body| {
81 Label::new(body.to_string(), theme.body_message.text.clone())
82 .contained()
83 .with_style(theme.body_message.container)
84 .boxed()
85 }))
86 .with_children(if buttons.is_empty() {
87 None
88 } else {
89 Some(
90 Flex::row()
91 .with_children(buttons.into_iter().enumerate().map(
92 |(ix, (message, action))| {
93 MouseEventHandler::new::<Button, _, _>(ix, cx, |state, _| {
94 let button = theme.button.style_for(state, false);
95 Label::new(message.to_string(), button.text.clone())
96 .contained()
97 .with_style(button.container)
98 .boxed()
99 })
100 .with_cursor_style(CursorStyle::PointingHand)
101 .on_click(MouseButton::Left, move |_, cx| {
102 cx.dispatch_any_action(action.boxed_clone())
103 })
104 .boxed()
105 },
106 ))
107 .aligned()
108 .right()
109 .boxed(),
110 )
111 })
112 .contained()
113 .boxed()
114}