1use crate::active_call_popover::{self, ActiveCallPopover};
2use call::ActiveCall;
3use gpui::{
4 actions,
5 color::Color,
6 elements::*,
7 geometry::{rect::RectF, vector::vec2f},
8 Appearance, Entity, MouseButton, MutableAppContext, RenderContext, View, ViewContext,
9 ViewHandle, WindowKind,
10};
11
12actions!(menu_bar_extra, [ToggleActiveCallPopover]);
13
14pub fn init(cx: &mut MutableAppContext) {
15 cx.add_action(MenuBarExtra::toggle_active_call_popover);
16
17 let mut status_bar_item_id = None;
18 cx.observe(&ActiveCall::global(cx), move |call, cx| {
19 if let Some(status_bar_item_id) = status_bar_item_id.take() {
20 cx.remove_status_bar_item(status_bar_item_id);
21 }
22
23 if call.read(cx).room().is_some() {
24 let (id, _) = cx.add_status_bar_item(|_| MenuBarExtra::new());
25 status_bar_item_id = Some(id);
26 }
27 })
28 .detach();
29}
30
31struct MenuBarExtra {
32 popover: Option<ViewHandle<ActiveCallPopover>>,
33}
34
35impl Entity for MenuBarExtra {
36 type Event = ();
37}
38
39impl View for MenuBarExtra {
40 fn ui_name() -> &'static str {
41 "MenuBarExtra"
42 }
43
44 fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
45 let color = match cx.appearance {
46 Appearance::Light | Appearance::VibrantLight => Color::black(),
47 Appearance::Dark | Appearance::VibrantDark => Color::white(),
48 };
49 MouseEventHandler::<Self>::new(0, cx, |_, _| {
50 Svg::new("icons/zed_22.svg")
51 .with_color(color)
52 .aligned()
53 .boxed()
54 })
55 .on_click(MouseButton::Left, |_, cx| {
56 cx.dispatch_action(ToggleActiveCallPopover);
57 })
58 .boxed()
59 }
60}
61
62impl MenuBarExtra {
63 fn new() -> Self {
64 Self { popover: None }
65 }
66
67 fn toggle_active_call_popover(
68 &mut self,
69 _: &ToggleActiveCallPopover,
70 cx: &mut ViewContext<Self>,
71 ) {
72 match self.popover.take() {
73 Some(popover) => {
74 cx.remove_window(popover.window_id());
75 }
76 None => {
77 let window_bounds = cx.window_bounds();
78 let size = vec2f(360., 460.);
79 let origin = window_bounds.lower_left()
80 + vec2f(window_bounds.width() / 2. - size.x() / 2., 0.);
81 let (_, popover) = cx.add_window(
82 gpui::WindowOptions {
83 bounds: gpui::WindowBounds::Fixed(RectF::new(origin, size)),
84 titlebar: None,
85 center: false,
86 kind: WindowKind::PopUp,
87 is_movable: false,
88 },
89 |cx| ActiveCallPopover::new(cx),
90 );
91 cx.subscribe(&popover, Self::on_popover_event).detach();
92 self.popover = Some(popover);
93 }
94 }
95 }
96
97 fn on_popover_event(
98 &mut self,
99 popover: ViewHandle<ActiveCallPopover>,
100 event: &active_call_popover::Event,
101 cx: &mut ViewContext<Self>,
102 ) {
103 match event {
104 active_call_popover::Event::Deactivated => {
105 self.popover.take();
106 cx.remove_window(popover.window_id());
107 }
108 }
109 }
110}