1use call::{room, ActiveCall};
2use client::User;
3use gpui::{
4 actions,
5 elements::*,
6 geometry::{rect::RectF, vector::vec2f},
7 Entity, MouseButton, MutableAppContext, RenderContext, View, ViewContext, WindowBounds,
8 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 cx.add_window(
24 WindowOptions {
25 bounds: WindowBounds::Fixed(RectF::new(vec2f(0., 0.), vec2f(300., 400.))),
26 titlebar: None,
27 center: true,
28 kind: WindowKind::PopUp,
29 is_movable: false,
30 },
31 |_| ProjectSharedNotification::new(*project_id, owner.clone()),
32 );
33 }
34 })
35 .detach();
36}
37
38pub struct ProjectSharedNotification {
39 project_id: u64,
40 owner: Arc<User>,
41}
42
43impl ProjectSharedNotification {
44 fn new(project_id: u64, owner: Arc<User>) -> Self {
45 Self { project_id, owner }
46 }
47
48 fn join(&mut self, _: &JoinProject, cx: &mut ViewContext<Self>) {
49 let window_id = cx.window_id();
50 cx.remove_window(window_id);
51 cx.propagate_action();
52 }
53
54 fn dismiss(&mut self, _: &DismissProject, cx: &mut ViewContext<Self>) {
55 let window_id = cx.window_id();
56 cx.remove_window(window_id);
57 }
58
59 fn render_owner(&self, cx: &mut RenderContext<Self>) -> ElementBox {
60 let theme = &cx.global::<Settings>().theme.project_shared_notification;
61 Flex::row()
62 .with_children(
63 self.owner
64 .avatar
65 .clone()
66 .map(|avatar| Image::new(avatar).with_style(theme.owner_avatar).boxed()),
67 )
68 .with_child(
69 Label::new(
70 format!("{} has shared a new project", self.owner.github_login),
71 theme.message.text.clone(),
72 )
73 .boxed(),
74 )
75 .boxed()
76 }
77
78 fn render_buttons(&self, cx: &mut RenderContext<Self>) -> ElementBox {
79 enum Join {}
80 enum Dismiss {}
81
82 let project_id = self.project_id;
83 let owner_user_id = self.owner.id;
84 Flex::row()
85 .with_child(
86 MouseEventHandler::<Join>::new(0, cx, |_, cx| {
87 let theme = &cx.global::<Settings>().theme.project_shared_notification;
88 Label::new("Join".to_string(), theme.join_button.text.clone())
89 .contained()
90 .with_style(theme.join_button.container)
91 .boxed()
92 })
93 .on_click(MouseButton::Left, move |_, cx| {
94 cx.dispatch_action(JoinProject {
95 project_id,
96 follow_user_id: owner_user_id,
97 });
98 })
99 .boxed(),
100 )
101 .with_child(
102 MouseEventHandler::<Dismiss>::new(0, cx, |_, cx| {
103 let theme = &cx.global::<Settings>().theme.project_shared_notification;
104 Label::new("Dismiss".to_string(), theme.dismiss_button.text.clone())
105 .contained()
106 .with_style(theme.dismiss_button.container)
107 .boxed()
108 })
109 .on_click(MouseButton::Left, |_, cx| {
110 cx.dispatch_action(DismissProject);
111 })
112 .boxed(),
113 )
114 .boxed()
115 }
116}
117
118impl Entity for ProjectSharedNotification {
119 type Event = ();
120}
121
122impl View for ProjectSharedNotification {
123 fn ui_name() -> &'static str {
124 "ProjectSharedNotification"
125 }
126
127 fn render(&mut self, cx: &mut RenderContext<Self>) -> gpui::ElementBox {
128 Flex::row()
129 .with_child(self.render_owner(cx))
130 .with_child(self.render_buttons(cx))
131 .boxed()
132 }
133}