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