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 );
62 Task::ready(room.unshare_screen(cx))
63 } else {
64 report_call_event_for_room(
65 "enable screen share",
66 room.id(),
67 room.channel_id(),
68 &client,
69 );
70 room.share_screen(cx)
71 }
72 });
73 toggle_screen_sharing.detach_and_log_err(cx);
74 }
75}
76
77pub fn toggle_mute(_: &ToggleMute, cx: &mut AppContext) {
78 let call = ActiveCall::global(cx).read(cx);
79 if let Some(room) = call.room().cloned() {
80 let client = call.client();
81 room.update(cx, |room, cx| {
82 let operation = if room.is_muted(cx) {
83 "enable microphone"
84 } else {
85 "disable microphone"
86 };
87 report_call_event_for_room(operation, room.id(), room.channel_id(), &client);
88
89 room.toggle_mute(cx)
90 })
91 .map(|task| task.detach_and_log_err(cx))
92 .log_err();
93 }
94}
95
96pub fn toggle_deafen(_: &ToggleDeafen, cx: &mut AppContext) {
97 if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
98 room.update(cx, Room::toggle_deafen)
99 .map(|task| task.detach_and_log_err(cx))
100 .log_err();
101 }
102}
103
104fn notification_window_options(
105 screen: Rc<dyn PlatformDisplay>,
106 window_size: Size<Pixels>,
107) -> WindowOptions {
108 let notification_margin_width = GlobalPixels::from(16.);
109 let notification_margin_height = GlobalPixels::from(-0.) - GlobalPixels::from(48.);
110
111 let screen_bounds = screen.bounds();
112 let size: Size<GlobalPixels> = window_size.into();
113
114 // todo!() use content bounds instead of screen.bounds and get rid of magics in point's 2nd argument.
115 let bounds = gpui::Bounds::<GlobalPixels> {
116 origin: screen_bounds.upper_right()
117 - point(
118 size.width + notification_margin_width,
119 notification_margin_height,
120 ),
121 size: window_size.into(),
122 };
123 WindowOptions {
124 bounds: WindowBounds::Fixed(bounds),
125 titlebar: None,
126 center: false,
127 focus: false,
128 show: true,
129 kind: WindowKind::PopUp,
130 is_movable: false,
131 display_id: Some(screen.id()),
132 }
133}
134
135// fn render_avatar<T: 'static>(
136// avatar: Option<Arc<ImageData>>,
137// avatar_style: &AvatarStyle,
138// container: ContainerStyle,
139// ) -> AnyElement<T> {
140// avatar
141// .map(|avatar| {
142// Image::from_data(avatar)
143// .with_style(avatar_style.image)
144// .aligned()
145// .contained()
146// .with_corner_radius(avatar_style.outer_corner_radius)
147// .constrained()
148// .with_width(avatar_style.outer_width)
149// .with_height(avatar_style.outer_width)
150// .into_any()
151// })
152// .unwrap_or_else(|| {
153// Empty::new()
154// .constrained()
155// .with_width(avatar_style.outer_width)
156// .into_any()
157// })
158// .contained()
159// .with_style(container)
160// .into_any()
161// }
162
163fn is_channels_feature_enabled(cx: &gpui::WindowContext<'_>) -> bool {
164 cx.is_staff() || cx.has_flag::<ChannelsAlpha>()
165}