notifications.rs

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