notifications.rs

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