Cargo.lock 🔗
@@ -11644,6 +11644,7 @@ dependencies = [
"async-recursion 0.3.2",
"async-tar",
"async-trait",
+ "audio2",
"auto_update2",
"backtrace",
"call2",
Piotr Osiewicz created
Cargo.lock | 1
crates/collab_ui2/src/collab_ui.rs | 58
crates/collab_ui2/src/notifications.rs | 16
crates/collab_ui2/src/notifications/incoming_call_notification.rs | 346
crates/zed2/Cargo.toml | 2
crates/zed2/src/main.rs | 2
6 files changed, 239 insertions(+), 186 deletions(-)
@@ -11644,6 +11644,7 @@ dependencies = [
"async-recursion 0.3.2",
"async-tar",
"async-trait",
+ "audio2",
"auto_update2",
"backtrace",
"call2",
@@ -7,11 +7,14 @@ pub mod notification_panel;
pub mod notifications;
mod panel_settings;
-use std::sync::Arc;
+use std::{rc::Rc, sync::Arc};
pub use collab_panel::CollabPanel;
pub use collab_titlebar_item::CollabTitlebarItem;
-use gpui::AppContext;
+use gpui::{
+ point, px, AppContext, GlobalPixels, Pixels, PlatformDisplay, Point, Size, WindowBounds,
+ WindowKind, WindowOptions,
+};
pub use panel_settings::{
ChatPanelSettings, CollaborationPanelSettings, NotificationPanelSettings,
};
@@ -23,7 +26,7 @@ use workspace::AppState;
// [ToggleScreenSharing, ToggleMute, ToggleDeafen, LeaveCall]
// );
-pub fn init(_app_state: &Arc<AppState>, cx: &mut AppContext) {
+pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
CollaborationPanelSettings::register(cx);
ChatPanelSettings::register(cx);
NotificationPanelSettings::register(cx);
@@ -32,7 +35,7 @@ pub fn init(_app_state: &Arc<AppState>, cx: &mut AppContext) {
collab_titlebar_item::init(cx);
collab_panel::init(cx);
// chat_panel::init(cx);
- // notifications::init(&app_state, cx);
+ notifications::init(&app_state, cx);
// cx.add_global_action(toggle_screen_sharing);
// cx.add_global_action(toggle_mute);
@@ -95,31 +98,30 @@ pub fn init(_app_state: &Arc<AppState>, cx: &mut AppContext) {
// }
// }
-// fn notification_window_options(
-// screen: Rc<dyn Screen>,
-// window_size: Vector2F,
-// ) -> WindowOptions<'static> {
-// const NOTIFICATION_PADDING: f32 = 16.;
+fn notification_window_options(
+ screen: Rc<dyn PlatformDisplay>,
+ window_size: Size<Pixels>,
+) -> WindowOptions {
+ let notification_padding = Pixels::from(16.);
-// let screen_bounds = screen.content_bounds();
-// WindowOptions {
-// bounds: WindowBounds::Fixed(RectF::new(
-// screen_bounds.upper_right()
-// + vec2f(
-// -NOTIFICATION_PADDING - window_size.x(),
-// NOTIFICATION_PADDING,
-// ),
-// window_size,
-// )),
-// titlebar: None,
-// center: false,
-// focus: false,
-// show: true,
-// kind: WindowKind::PopUp,
-// is_movable: false,
-// screen: Some(screen),
-// }
-// }
+ let screen_bounds = screen.bounds();
+ let size: Size<GlobalPixels> = window_size.into();
+
+ let bounds = gpui::Bounds::<GlobalPixels> {
+ origin: screen_bounds.origin,
+ size: window_size.into(),
+ };
+ WindowOptions {
+ bounds: WindowBounds::Fixed(bounds),
+ titlebar: None,
+ center: false,
+ focus: false,
+ show: true,
+ kind: WindowKind::PopUp,
+ is_movable: false,
+ display_id: Some(screen.id()),
+ }
+}
// fn render_avatar<T: 'static>(
// avatar: Option<Arc<ImageData>>,
@@ -1,11 +1,11 @@
-// use gpui::AppContext;
-// use std::sync::Arc;
-// use workspace::AppState;
+use gpui::AppContext;
+use std::sync::Arc;
+use workspace::AppState;
-// pub mod incoming_call_notification;
+pub mod incoming_call_notification;
// pub mod project_shared_notification;
-// pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
-// incoming_call_notification::init(app_state, cx);
-// project_shared_notification::init(app_state, cx);
-// }
+pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
+ incoming_call_notification::init(app_state, cx);
+ //project_shared_notification::init(app_state, cx);
+}
@@ -3,12 +3,12 @@ use call::{ActiveCall, IncomingCall};
use client::proto;
use futures::StreamExt;
use gpui::{
- elements::*,
- geometry::vector::vec2f,
- platform::{CursorStyle, MouseButton},
- AnyElement, AppContext, Entity, View, ViewContext, WindowHandle,
+ blue, div, green, px, red, AnyElement, AppContext, Component, Context, Div, Element, Entity,
+ EventEmitter, GlobalPixels, ParentElement, Render, RenderOnce, StatefulInteractiveElement,
+ Styled, View, ViewContext, VisualContext as _, WindowHandle,
};
use std::sync::{Arc, Weak};
+use ui::{h_stack, v_stack, Avatar, Button, Label};
use util::ResultExt;
use workspace::AppState;
@@ -19,23 +19,44 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
let mut notification_windows: Vec<WindowHandle<IncomingCallNotification>> = Vec::new();
while let Some(incoming_call) = incoming_call.next().await {
for window in notification_windows.drain(..) {
- window.remove(&mut cx);
+ window.update(&mut cx, |this, cx| {
+ //cx.remove_window();
+ });
+ //cx.update_window(window.into(), |this, cx| cx.remove_window());
+ //window.remove(&mut cx);
}
if let Some(incoming_call) = incoming_call {
- let window_size = cx.read(|cx| {
- let theme = &theme::current(cx).incoming_call_notification;
- vec2f(theme.window_width, theme.window_height)
- });
+ let unique_screens = cx.update(|cx| cx.displays()).unwrap();
+ let window_size = gpui::Size {
+ width: px(380.),
+ height: px(64.),
+ };
- for screen in cx.platform().screens() {
+ for window in unique_screens {
+ let options = notification_window_options(window, window_size);
+ dbg!(&options);
let window = cx
- .add_window(notification_window_options(screen, window_size), |_| {
- IncomingCallNotification::new(incoming_call.clone(), app_state.clone())
- });
-
+ .open_window(options, |cx| {
+ cx.build_view(|_| {
+ IncomingCallNotification::new(
+ incoming_call.clone(),
+ app_state.clone(),
+ )
+ })
+ })
+ .unwrap();
notification_windows.push(window);
}
+
+ // for screen in cx.platform().screens() {
+ // let window = cx
+ // .add_window(notification_window_options(screen, window_size), |_| {
+ // IncomingCallNotification::new(incoming_call.clone(), app_state.clone())
+ // });
+
+ // notification_windows.push(window);
+ // }
}
}
})
@@ -47,167 +68,196 @@ struct RespondToCall {
accept: bool,
}
-pub struct IncomingCallNotification {
+struct IncomingCallNotificationState {
call: IncomingCall,
app_state: Weak<AppState>,
}
-impl IncomingCallNotification {
+pub struct IncomingCallNotification {
+ state: Arc<IncomingCallNotificationState>,
+}
+impl IncomingCallNotificationState {
pub fn new(call: IncomingCall, app_state: Weak<AppState>) -> Self {
Self { call, app_state }
}
- fn respond(&mut self, accept: bool, cx: &mut ViewContext<Self>) {
+ fn respond(&self, accept: bool, cx: &mut AppContext) {
let active_call = ActiveCall::global(cx);
if accept {
let join = active_call.update(cx, |active_call, cx| active_call.accept_incoming(cx));
let caller_user_id = self.call.calling_user.id;
let initial_project_id = self.call.initial_project.as_ref().map(|project| project.id);
let app_state = self.app_state.clone();
- cx.app_context()
- .spawn(|mut cx| async move {
- join.await?;
- if let Some(project_id) = initial_project_id {
- cx.update(|cx| {
- if let Some(app_state) = app_state.upgrade() {
- workspace::join_remote_project(
- project_id,
- caller_user_id,
- app_state,
- cx,
- )
- .detach_and_log_err(cx);
- }
- });
- }
- anyhow::Ok(())
- })
- .detach_and_log_err(cx);
+ let cx: &mut AppContext = cx;
+ cx.spawn(|mut cx| async move {
+ join.await?;
+ if let Some(project_id) = initial_project_id {
+ cx.update(|cx| {
+ if let Some(app_state) = app_state.upgrade() {
+ // workspace::join_remote_project(
+ // project_id,
+ // caller_user_id,
+ // app_state,
+ // cx,
+ // )
+ // .detach_and_log_err(cx);
+ }
+ });
+ }
+ anyhow::Ok(())
+ })
+ .detach_and_log_err(cx);
} else {
active_call.update(cx, |active_call, cx| {
active_call.decline_incoming(cx).log_err();
});
}
}
+}
- fn render_caller(&self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
- let theme = &theme::current(cx).incoming_call_notification;
- let default_project = proto::ParticipantProject::default();
- let initial_project = self
- .call
- .initial_project
- .as_ref()
- .unwrap_or(&default_project);
- Flex::row()
- .with_children(self.call.calling_user.avatar.clone().map(|avatar| {
- Image::from_data(avatar)
- .with_style(theme.caller_avatar)
- .aligned()
- }))
- .with_child(
- Flex::column()
- .with_child(
- Label::new(
- self.call.calling_user.github_login.clone(),
- theme.caller_username.text.clone(),
- )
- .contained()
- .with_style(theme.caller_username.container),
- )
- .with_child(
- Label::new(
- format!(
- "is sharing a project in Zed{}",
- if initial_project.worktree_root_names.is_empty() {
- ""
- } else {
- ":"
- }
- ),
- theme.caller_message.text.clone(),
- )
- .contained()
- .with_style(theme.caller_message.container),
- )
- .with_children(if initial_project.worktree_root_names.is_empty() {
- None
- } else {
- Some(
- Label::new(
- initial_project.worktree_root_names.join(", "),
- theme.worktree_roots.text.clone(),
- )
- .contained()
- .with_style(theme.worktree_roots.container),
- )
- })
- .contained()
- .with_style(theme.caller_metadata)
- .aligned(),
- )
- .contained()
- .with_style(theme.caller_container)
- .flex(1., true)
- .into_any()
+impl IncomingCallNotification {
+ pub fn new(call: IncomingCall, app_state: Weak<AppState>) -> Self {
+ Self {
+ state: Arc::new(IncomingCallNotificationState::new(call, app_state)),
+ }
}
-
- fn render_buttons(&self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
- enum Accept {}
- enum Decline {}
-
- let theme = theme::current(cx);
- Flex::column()
- .with_child(
- MouseEventHandler::new::<Accept, _>(0, cx, |_, _| {
- let theme = &theme.incoming_call_notification;
- Label::new("Accept", theme.accept_button.text.clone())
- .aligned()
- .contained()
- .with_style(theme.accept_button.container)
- })
- .with_cursor_style(CursorStyle::PointingHand)
- .on_click(MouseButton::Left, |_, this, cx| {
- this.respond(true, cx);
- })
- .flex(1., true),
+ fn render_caller(&self, cx: &mut ViewContext<Self>) -> impl Element {
+ h_stack()
+ .children(
+ self.state
+ .call
+ .calling_user
+ .avatar
+ .as_ref()
+ .map(|avatar| Avatar::new(avatar.clone())),
)
- .with_child(
- MouseEventHandler::new::<Decline, _>(0, cx, |_, _| {
- let theme = &theme.incoming_call_notification;
- Label::new("Decline", theme.decline_button.text.clone())
- .aligned()
- .contained()
- .with_style(theme.decline_button.container)
- })
- .with_cursor_style(CursorStyle::PointingHand)
- .on_click(MouseButton::Left, |_, this, cx| {
- this.respond(false, cx);
- })
- .flex(1., true),
+ .child(
+ v_stack()
+ .child(Label::new(format!(
+ "{} is sharing a project in Zed",
+ self.state.call.calling_user.github_login
+ )))
+ .child(self.render_buttons(cx)),
)
- .constrained()
- .with_width(theme.incoming_call_notification.button_width)
- .into_any()
+ // let theme = &theme::current(cx).incoming_call_notification;
+ // let default_project = proto::ParticipantProject::default();
+ // let initial_project = self
+ // .call
+ // .initial_project
+ // .as_ref()
+ // .unwrap_or(&default_project);
+ // Flex::row()
+ // .with_children(self.call.calling_user.avatar.clone().map(|avatar| {
+ // Image::from_data(avatar)
+ // .with_style(theme.caller_avatar)
+ // .aligned()
+ // }))
+ // .with_child(
+ // Flex::column()
+ // .with_child(
+ // Label::new(
+ // self.call.calling_user.github_login.clone(),
+ // theme.caller_username.text.clone(),
+ // )
+ // .contained()
+ // .with_style(theme.caller_username.container),
+ // )
+ // .with_child(
+ // Label::new(
+ // format!(
+ // "is sharing a project in Zed{}",
+ // if initial_project.worktree_root_names.is_empty() {
+ // ""
+ // } else {
+ // ":"
+ // }
+ // ),
+ // theme.caller_message.text.clone(),
+ // )
+ // .contained()
+ // .with_style(theme.caller_message.container),
+ // )
+ // .with_children(if initial_project.worktree_root_names.is_empty() {
+ // None
+ // } else {
+ // Some(
+ // Label::new(
+ // initial_project.worktree_root_names.join(", "),
+ // theme.worktree_roots.text.clone(),
+ // )
+ // .contained()
+ // .with_style(theme.worktree_roots.container),
+ // )
+ // })
+ // .contained()
+ // .with_style(theme.caller_metadata)
+ // .aligned(),
+ // )
+ // .contained()
+ // .with_style(theme.caller_container)
+ // .flex(1., true)
+ // .into_any()
}
-}
-impl Entity for IncomingCallNotification {
- type Event = ();
-}
+ fn render_buttons(&self, cx: &mut ViewContext<Self>) -> impl Element {
+ h_stack()
+ .child(Button::new("Accept").render(cx).bg(green()).on_click({
+ let state = self.state.clone();
+ move |_, cx| state.respond(true, cx)
+ }))
+ .child(Button::new("Decline").render(cx).bg(red()).on_click({
+ let state = self.state.clone();
+ move |_, cx| state.respond(false, cx)
+ }))
-impl View for IncomingCallNotification {
- fn ui_name() -> &'static str {
- "IncomingCallNotification"
- }
+ // enum Accept {}
+ // enum Decline {}
- fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
- let background = theme::current(cx).incoming_call_notification.background;
- Flex::row()
- .with_child(self.render_caller(cx))
- .with_child(self.render_buttons(cx))
- .contained()
- .with_background_color(background)
- .expanded()
- .into_any()
+ // let theme = theme::current(cx);
+ // Flex::column()
+ // .with_child(
+ // MouseEventHandler::new::<Accept, _>(0, cx, |_, _| {
+ // let theme = &theme.incoming_call_notification;
+ // Label::new("Accept", theme.accept_button.text.clone())
+ // .aligned()
+ // .contained()
+ // .with_style(theme.accept_button.container)
+ // })
+ // .with_cursor_style(CursorStyle::PointingHand)
+ // .on_click(MouseButton::Left, |_, this, cx| {
+ // this.respond(true, cx);
+ // })
+ // .flex(1., true),
+ // )
+ // .with_child(
+ // MouseEventHandler::new::<Decline, _>(0, cx, |_, _| {
+ // let theme = &theme.incoming_call_notification;
+ // Label::new("Decline", theme.decline_button.text.clone())
+ // .aligned()
+ // .contained()
+ // .with_style(theme.decline_button.container)
+ // })
+ // .with_cursor_style(CursorStyle::PointingHand)
+ // .on_click(MouseButton::Left, |_, this, cx| {
+ // this.respond(false, cx);
+ // })
+ // .flex(1., true),
+ // )
+ // .constrained()
+ // .with_width(theme.incoming_call_notification.button_width)
+ // .into_any()
+ }
+}
+impl Render for IncomingCallNotification {
+ type Element = Div;
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
+ div().bg(red()).flex_none().child(self.render_caller(cx))
+ // Flex::row()
+ // .with_child()
+ // .with_child(self.render_buttons(cx))
+ // .contained()
+ // .with_background_color(background)
+ // .expanded()
+ // .into_any()
}
}
@@ -16,7 +16,7 @@ path = "src/main.rs"
[dependencies]
ai = { package = "ai2", path = "../ai2"}
-# audio = { path = "../audio" }
+audio = { package = "audio2", path = "../audio2" }
# activity_indicator = { path = "../activity_indicator" }
auto_update = { package = "auto_update2", path = "../auto_update2" }
# breadcrumbs = { path = "../breadcrumbs" }
@@ -199,7 +199,7 @@ fn main() {
});
cx.set_global(Arc::downgrade(&app_state));
- // audio::init(Assets, cx);
+ audio::init(Assets, cx);
auto_update::init(http.clone(), client::ZED_SERVER_URL.clone(), cx);
workspace::init(app_state.clone(), cx);