notifications.rs

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