From 9f81699e0114da7a6818d2e3a00eacfa7dc3b48d Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 6 Oct 2022 16:10:45 +0200 Subject: [PATCH] WIP: start on menu bar extra --- crates/collab_ui/src/active_call_popover.rs | 40 +++++++ crates/collab_ui/src/collab_ui.rs | 5 +- crates/collab_ui/src/menu_bar_extra.rs | 110 ++++++++++++++++++++ crates/gpui/src/app.rs | 4 + 4 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 crates/collab_ui/src/active_call_popover.rs create mode 100644 crates/collab_ui/src/menu_bar_extra.rs diff --git a/crates/collab_ui/src/active_call_popover.rs b/crates/collab_ui/src/active_call_popover.rs new file mode 100644 index 0000000000..01a4e4721d --- /dev/null +++ b/crates/collab_ui/src/active_call_popover.rs @@ -0,0 +1,40 @@ +use gpui::{color::Color, elements::*, Entity, RenderContext, View, ViewContext}; + +pub enum Event { + Deactivated, +} + +pub struct ActiveCallPopover { + _subscription: gpui::Subscription, +} + +impl Entity for ActiveCallPopover { + type Event = Event; +} + +impl View for ActiveCallPopover { + fn ui_name() -> &'static str { + "ActiveCallPopover" + } + + fn render(&mut self, _: &mut RenderContext) -> ElementBox { + Empty::new() + .contained() + .with_background_color(Color::red()) + .boxed() + } +} + +impl ActiveCallPopover { + pub fn new(cx: &mut ViewContext) -> Self { + Self { + _subscription: cx.observe_window_activation(Self::window_activation_changed), + } + } + + fn window_activation_changed(&mut self, is_active: bool, cx: &mut ViewContext) { + if !is_active { + cx.emit(Event::Deactivated); + } + } +} diff --git a/crates/collab_ui/src/collab_ui.rs b/crates/collab_ui/src/collab_ui.rs index 438a41ae7d..421258114e 100644 --- a/crates/collab_ui/src/collab_ui.rs +++ b/crates/collab_ui/src/collab_ui.rs @@ -1,8 +1,10 @@ +mod active_call_popover; mod collab_titlebar_item; mod contact_finder; mod contact_notification; mod contacts_popover; mod incoming_call_notification; +mod menu_bar_extra; mod notifications; mod project_shared_notification; @@ -14,11 +16,12 @@ use std::sync::Arc; use workspace::{AppState, JoinProject, ToggleFollow, Workspace}; pub fn init(app_state: Arc, cx: &mut MutableAppContext) { + collab_titlebar_item::init(cx); contact_notification::init(cx); contact_finder::init(cx); contacts_popover::init(cx); - collab_titlebar_item::init(cx); incoming_call_notification::init(cx); + menu_bar_extra::init(cx); project_shared_notification::init(cx); cx.add_global_action(move |action: &JoinProject, cx| { diff --git a/crates/collab_ui/src/menu_bar_extra.rs b/crates/collab_ui/src/menu_bar_extra.rs new file mode 100644 index 0000000000..8b2baa53eb --- /dev/null +++ b/crates/collab_ui/src/menu_bar_extra.rs @@ -0,0 +1,110 @@ +use crate::active_call_popover::{self, ActiveCallPopover}; +use call::ActiveCall; +use gpui::{ + actions, + color::Color, + elements::*, + geometry::{rect::RectF, vector::vec2f}, + Appearance, Entity, MouseButton, MutableAppContext, RenderContext, View, ViewContext, + ViewHandle, WindowKind, +}; + +actions!(menu_bar_extra, [ToggleActiveCallPopover]); + +pub fn init(cx: &mut MutableAppContext) { + cx.add_action(MenuBarExtra::toggle_active_call_popover); + + let mut status_bar_item_id = None; + cx.observe(&ActiveCall::global(cx), move |call, cx| { + if let Some(status_bar_item_id) = status_bar_item_id.take() { + cx.remove_status_bar_item(status_bar_item_id); + } + + if call.read(cx).room().is_some() { + let (id, _) = cx.add_status_bar_item(|_| MenuBarExtra::new()); + status_bar_item_id = Some(id); + } + }) + .detach(); +} + +struct MenuBarExtra { + popover: Option>, +} + +impl Entity for MenuBarExtra { + type Event = (); +} + +impl View for MenuBarExtra { + fn ui_name() -> &'static str { + "MenuBarExtra" + } + + fn render(&mut self, cx: &mut RenderContext) -> ElementBox { + let color = match cx.appearance { + Appearance::Light | Appearance::VibrantLight => Color::black(), + Appearance::Dark | Appearance::VibrantDark => Color::white(), + }; + MouseEventHandler::::new(0, cx, |_, _| { + Svg::new("icons/zed_22.svg") + .with_color(color) + .aligned() + .boxed() + }) + .on_click(MouseButton::Left, |_, cx| { + cx.dispatch_action(ToggleActiveCallPopover); + }) + .boxed() + } +} + +impl MenuBarExtra { + fn new() -> Self { + Self { popover: None } + } + + fn toggle_active_call_popover( + &mut self, + _: &ToggleActiveCallPopover, + cx: &mut ViewContext, + ) { + match self.popover.take() { + Some(popover) => { + cx.remove_window(popover.window_id()); + } + None => { + let window_bounds = cx.window_bounds(); + let size = vec2f(360., 460.); + let origin = window_bounds.lower_left() + + vec2f(window_bounds.width() / 2. - size.x() / 2., 0.); + let (_, popover) = cx.add_window( + gpui::WindowOptions { + bounds: gpui::WindowBounds::Fixed(RectF::new(origin, size)), + titlebar: None, + center: false, + kind: WindowKind::PopUp, + is_movable: false, + }, + |cx| ActiveCallPopover::new(cx), + ); + cx.subscribe(&popover, Self::on_popover_event).detach(); + self.popover = Some(popover); + } + } + } + + fn on_popover_event( + &mut self, + popover: ViewHandle, + event: &active_call_popover::Event, + cx: &mut ViewContext, + ) { + match event { + active_call_popover::Event::Deactivated => { + self.popover.take(); + cx.remove_window(popover.window_id()); + } + } + } +} diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 668071d046..f55dd2b464 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -1990,6 +1990,10 @@ impl MutableAppContext { }) } + pub fn remove_status_bar_item(&mut self, id: usize) { + self.remove_window(id); + } + fn register_platform_window( &mut self, window_id: usize,