1pub mod channel_view;
2pub mod chat_panel;
3pub mod collab_panel;
4mod collab_titlebar_item;
5mod face_pile;
6pub mod notification_panel;
7pub mod notifications;
8mod panel_settings;
9
10use std::{rc::Rc, sync::Arc};
11
12use call::{report_call_event_for_room, ActiveCall, Room};
13pub use collab_panel::CollabPanel;
14pub use collab_titlebar_item::CollabTitlebarItem;
15use feature_flags::{ChannelsAlpha, FeatureFlagAppExt};
16use gpui::{
17 actions, point, AppContext, GlobalPixels, Pixels, PlatformDisplay, Size, Task, WindowBounds,
18 WindowKind, WindowOptions,
19};
20pub use panel_settings::{
21 ChatPanelSettings, CollaborationPanelSettings, NotificationPanelSettings,
22};
23use settings::Settings;
24use util::ResultExt;
25use workspace::AppState;
26
27actions!(
28 collab,
29 [ToggleScreenSharing, ToggleMute, ToggleDeafen, LeaveCall]
30);
31
32pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
33 CollaborationPanelSettings::register(cx);
34 ChatPanelSettings::register(cx);
35 NotificationPanelSettings::register(cx);
36
37 // vcs_menu::init(cx);
38 collab_titlebar_item::init(cx);
39 collab_panel::init(cx);
40 channel_view::init(cx);
41 chat_panel::init(cx);
42 notification_panel::init(cx);
43 notifications::init(&app_state, cx);
44
45 // cx.add_global_action(toggle_screen_sharing);
46 // cx.add_global_action(toggle_mute);
47 // cx.add_global_action(toggle_deafen);
48}
49
50pub fn toggle_screen_sharing(_: &ToggleScreenSharing, cx: &mut AppContext) {
51 let call = ActiveCall::global(cx).read(cx);
52 if let Some(room) = call.room().cloned() {
53 let client = call.client();
54 let toggle_screen_sharing = room.update(cx, |room, cx| {
55 if room.is_screen_sharing() {
56 report_call_event_for_room(
57 "disable screen share",
58 room.id(),
59 room.channel_id(),
60 &client,
61 cx,
62 );
63 Task::ready(room.unshare_screen(cx))
64 } else {
65 report_call_event_for_room(
66 "enable screen share",
67 room.id(),
68 room.channel_id(),
69 &client,
70 cx,
71 );
72 room.share_screen(cx)
73 }
74 });
75 toggle_screen_sharing.detach_and_log_err(cx);
76 }
77}
78
79pub fn toggle_mute(_: &ToggleMute, cx: &mut AppContext) {
80 let call = ActiveCall::global(cx).read(cx);
81 if let Some(room) = call.room().cloned() {
82 let client = call.client();
83 room.update(cx, |room, cx| {
84 let operation = if room.is_muted(cx) {
85 "enable microphone"
86 } else {
87 "disable microphone"
88 };
89 report_call_event_for_room(operation, room.id(), room.channel_id(), &client, cx);
90
91 room.toggle_mute(cx)
92 })
93 .map(|task| task.detach_and_log_err(cx))
94 .log_err();
95 }
96}
97
98pub fn toggle_deafen(_: &ToggleDeafen, cx: &mut AppContext) {
99 if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
100 room.update(cx, Room::toggle_deafen)
101 .map(|task| task.detach_and_log_err(cx))
102 .log_err();
103 }
104}
105
106fn notification_window_options(
107 screen: Rc<dyn PlatformDisplay>,
108 window_size: Size<Pixels>,
109) -> WindowOptions {
110 let notification_margin_width = GlobalPixels::from(16.);
111 let notification_margin_height = GlobalPixels::from(-0.) - GlobalPixels::from(48.);
112
113 let screen_bounds = screen.bounds();
114 let size: Size<GlobalPixels> = window_size.into();
115
116 // todo!() use content bounds instead of screen.bounds and get rid of magics in point's 2nd argument.
117 let bounds = gpui::Bounds::<GlobalPixels> {
118 origin: screen_bounds.upper_right()
119 - point(
120 size.width + notification_margin_width,
121 notification_margin_height,
122 ),
123 size: window_size.into(),
124 };
125 WindowOptions {
126 bounds: WindowBounds::Fixed(bounds),
127 titlebar: None,
128 center: false,
129 focus: false,
130 show: true,
131 kind: WindowKind::PopUp,
132 is_movable: false,
133 display_id: Some(screen.id()),
134 }
135}
136
137// fn render_avatar<T: 'static>(
138// avatar: Option<Arc<ImageData>>,
139// avatar_style: &AvatarStyle,
140// container: ContainerStyle,
141// ) -> AnyElement<T> {
142// avatar
143// .map(|avatar| {
144// Image::from_data(avatar)
145// .with_style(avatar_style.image)
146// .aligned()
147// .contained()
148// .with_corner_radius(avatar_style.outer_corner_radius)
149// .constrained()
150// .with_width(avatar_style.outer_width)
151// .with_height(avatar_style.outer_width)
152// .into_any()
153// })
154// .unwrap_or_else(|| {
155// Empty::new()
156// .constrained()
157// .with_width(avatar_style.outer_width)
158// .into_any()
159// })
160// .contained()
161// .with_style(container)
162// .into_any()
163// }
164
165fn is_channels_feature_enabled(cx: &gpui::WindowContext<'_>) -> bool {
166 cx.is_staff() || cx.has_flag::<ChannelsAlpha>()
167}