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(
80 body.to_string(),
81 theme.body_message.text.clone(),
82 )
83 .contained()
84 .with_style(theme.body_message.container)
85 .boxed()
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::new::<Button, _, _>(ix, cx, |state, _| {
95 let button = theme.button.style_for(state, false);
96 Label::new(message.to_string(), button.text.clone())
97 .contained()
98 .with_style(button.container)
99 .boxed()
100 })
101 .with_cursor_style(CursorStyle::PointingHand)
102 .on_click(move |_, cx| cx.dispatch_any_action(action.boxed_clone()))
103 .boxed()
104 },
105 ))
106 .aligned()
107 .right()
108 .boxed(),
109 )
110 })
111 .contained()
112 .boxed()
113}