project_shared_notification.rs

  1use call::{room, ActiveCall};
  2use client::User;
  3use gpui::{
  4    actions,
  5    elements::*,
  6    geometry::{rect::RectF, vector::vec2f},
  7    CursorStyle, Entity, MouseButton, MutableAppContext, RenderContext, View, ViewContext,
  8    WindowBounds, WindowKind, WindowOptions,
  9};
 10use settings::Settings;
 11use std::sync::Arc;
 12use workspace::JoinProject;
 13
 14actions!(project_shared_notification, [DismissProject]);
 15
 16pub fn init(cx: &mut MutableAppContext) {
 17    cx.add_action(ProjectSharedNotification::join);
 18    cx.add_action(ProjectSharedNotification::dismiss);
 19
 20    let active_call = ActiveCall::global(cx);
 21    cx.subscribe(&active_call, move |_, event, cx| match event {
 22        room::Event::RemoteProjectShared { owner, project_id } => {
 23            const PADDING: f32 = 16.;
 24            let screen_size = cx.platform().screen_size();
 25            let window_size = vec2f(366., 64.);
 26            cx.add_window(
 27                WindowOptions {
 28                    bounds: WindowBounds::Fixed(RectF::new(
 29                        vec2f(screen_size.x() - window_size.x() - PADDING, PADDING),
 30                        window_size,
 31                    )),
 32                    titlebar: None,
 33                    center: false,
 34                    kind: WindowKind::PopUp,
 35                    is_movable: false,
 36                },
 37                |_| ProjectSharedNotification::new(*project_id, owner.clone()),
 38            );
 39        }
 40    })
 41    .detach();
 42}
 43
 44pub struct ProjectSharedNotification {
 45    project_id: u64,
 46    owner: Arc<User>,
 47}
 48
 49impl ProjectSharedNotification {
 50    fn new(project_id: u64, owner: Arc<User>) -> Self {
 51        Self { project_id, owner }
 52    }
 53
 54    fn join(&mut self, _: &JoinProject, cx: &mut ViewContext<Self>) {
 55        let window_id = cx.window_id();
 56        cx.remove_window(window_id);
 57        cx.propagate_action();
 58    }
 59
 60    fn dismiss(&mut self, _: &DismissProject, cx: &mut ViewContext<Self>) {
 61        let window_id = cx.window_id();
 62        cx.remove_window(window_id);
 63    }
 64
 65    fn render_owner(&self, cx: &mut RenderContext<Self>) -> ElementBox {
 66        let theme = &cx.global::<Settings>().theme.project_shared_notification;
 67        Flex::row()
 68            .with_children(self.owner.avatar.clone().map(|avatar| {
 69                Image::new(avatar)
 70                    .with_style(theme.owner_avatar)
 71                    .aligned()
 72                    .boxed()
 73            }))
 74            .with_child(
 75                Flex::column()
 76                    .with_child(
 77                        Label::new(
 78                            self.owner.github_login.clone(),
 79                            theme.owner_username.text.clone(),
 80                        )
 81                        .contained()
 82                        .with_style(theme.owner_username.container)
 83                        .boxed(),
 84                    )
 85                    .with_child(
 86                        Label::new(
 87                            "has shared a project with you".into(),
 88                            theme.message.text.clone(),
 89                        )
 90                        .contained()
 91                        .with_style(theme.message.container)
 92                        .boxed(),
 93                    )
 94                    .contained()
 95                    .with_style(theme.owner_metadata)
 96                    .aligned()
 97                    .boxed(),
 98            )
 99            .contained()
100            .with_style(theme.owner_container)
101            .flex(1., true)
102            .boxed()
103    }
104
105    fn render_buttons(&self, cx: &mut RenderContext<Self>) -> ElementBox {
106        enum Join {}
107        enum Dismiss {}
108
109        let project_id = self.project_id;
110        let owner_user_id = self.owner.id;
111
112        Flex::column()
113            .with_child(
114                MouseEventHandler::<Join>::new(0, cx, |_, cx| {
115                    let theme = &cx.global::<Settings>().theme.project_shared_notification;
116                    Label::new("Join".to_string(), theme.join_button.text.clone())
117                        .aligned()
118                        .contained()
119                        .with_style(theme.join_button.container)
120                        .boxed()
121                })
122                .with_cursor_style(CursorStyle::PointingHand)
123                .on_click(MouseButton::Left, move |_, cx| {
124                    cx.dispatch_action(JoinProject {
125                        project_id,
126                        follow_user_id: owner_user_id,
127                    });
128                })
129                .flex(1., true)
130                .boxed(),
131            )
132            .with_child(
133                MouseEventHandler::<Dismiss>::new(0, cx, |_, cx| {
134                    let theme = &cx.global::<Settings>().theme.project_shared_notification;
135                    Label::new("Dismiss".to_string(), theme.dismiss_button.text.clone())
136                        .aligned()
137                        .contained()
138                        .with_style(theme.dismiss_button.container)
139                        .boxed()
140                })
141                .with_cursor_style(CursorStyle::PointingHand)
142                .on_click(MouseButton::Left, |_, cx| {
143                    cx.dispatch_action(DismissProject);
144                })
145                .flex(1., true)
146                .boxed(),
147            )
148            .constrained()
149            .with_width(
150                cx.global::<Settings>()
151                    .theme
152                    .project_shared_notification
153                    .button_width,
154            )
155            .boxed()
156    }
157}
158
159impl Entity for ProjectSharedNotification {
160    type Event = ();
161}
162
163impl View for ProjectSharedNotification {
164    fn ui_name() -> &'static str {
165        "ProjectSharedNotification"
166    }
167
168    fn render(&mut self, cx: &mut RenderContext<Self>) -> gpui::ElementBox {
169        let background = cx
170            .global::<Settings>()
171            .theme
172            .project_shared_notification
173            .background;
174        Flex::row()
175            .with_child(self.render_owner(cx))
176            .with_child(self.render_buttons(cx))
177            .contained()
178            .with_background_color(background)
179            .expanded()
180            .boxed()
181    }
182}