macos.rs

  1use crate::{
  2    item::{Item, ItemEvent},
  3    ItemNavHistory, WorkspaceId,
  4};
  5use anyhow::Result;
  6use call::participant::{Frame, RemoteVideoTrack};
  7use client::{proto::PeerId, User};
  8use futures::StreamExt;
  9use gpui::{
 10    div, surface, AppContext, EventEmitter, FocusHandle, FocusableView, InteractiveElement,
 11    ParentElement, Render, SharedString, Styled, Task, View, ViewContext, VisualContext,
 12    WindowContext,
 13};
 14use std::sync::{Arc, Weak};
 15use ui::{prelude::*, Icon, IconName};
 16
 17pub enum Event {
 18    Close,
 19}
 20
 21pub struct SharedScreen {
 22    track: Weak<RemoteVideoTrack>,
 23    frame: Option<Frame>,
 24    pub peer_id: PeerId,
 25    user: Arc<User>,
 26    nav_history: Option<ItemNavHistory>,
 27    _maintain_frame: Task<Result<()>>,
 28    focus: FocusHandle,
 29}
 30
 31impl SharedScreen {
 32    pub fn new(
 33        track: Arc<RemoteVideoTrack>,
 34        peer_id: PeerId,
 35        user: Arc<User>,
 36        cx: &mut ViewContext<Self>,
 37    ) -> Self {
 38        cx.focus_handle();
 39        let mut frames = track.frames();
 40        Self {
 41            track: Arc::downgrade(&track),
 42            frame: None,
 43            peer_id,
 44            user,
 45            nav_history: Default::default(),
 46            _maintain_frame: cx.spawn(|this, mut cx| async move {
 47                while let Some(frame) = frames.next().await {
 48                    this.update(&mut cx, |this, cx| {
 49                        this.frame = Some(frame);
 50                        cx.notify();
 51                    })?;
 52                }
 53                this.update(&mut cx, |_, cx| cx.emit(Event::Close))?;
 54                Ok(())
 55            }),
 56            focus: cx.focus_handle(),
 57        }
 58    }
 59}
 60
 61impl EventEmitter<Event> for SharedScreen {}
 62
 63impl FocusableView for SharedScreen {
 64    fn focus_handle(&self, _: &AppContext) -> FocusHandle {
 65        self.focus.clone()
 66    }
 67}
 68impl Render for SharedScreen {
 69    fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
 70        div()
 71            .bg(cx.theme().colors().editor_background)
 72            .track_focus(&self.focus)
 73            .key_context("SharedScreen")
 74            .size_full()
 75            .children(
 76                self.frame
 77                    .as_ref()
 78                    .map(|frame| surface(frame.image()).size_full()),
 79            )
 80    }
 81}
 82
 83impl Item for SharedScreen {
 84    type Event = Event;
 85
 86    fn tab_tooltip_text(&self, _: &AppContext) -> Option<SharedString> {
 87        Some(format!("{}'s screen", self.user.github_login).into())
 88    }
 89
 90    fn deactivated(&mut self, cx: &mut ViewContext<Self>) {
 91        if let Some(nav_history) = self.nav_history.as_mut() {
 92            nav_history.push::<()>(None, cx);
 93        }
 94    }
 95
 96    fn tab_icon(&self, _cx: &WindowContext) -> Option<Icon> {
 97        Some(Icon::new(IconName::Screen))
 98    }
 99
100    fn tab_content_text(&self, _cx: &WindowContext) -> Option<SharedString> {
101        Some(format!("{}'s screen", self.user.github_login).into())
102    }
103
104    fn telemetry_event_text(&self) -> Option<&'static str> {
105        None
106    }
107
108    fn set_nav_history(&mut self, history: ItemNavHistory, _: &mut ViewContext<Self>) {
109        self.nav_history = Some(history);
110    }
111
112    fn clone_on_split(
113        &self,
114        _workspace_id: Option<WorkspaceId>,
115        cx: &mut ViewContext<Self>,
116    ) -> Option<View<Self>> {
117        let track = self.track.upgrade()?;
118        Some(cx.new_view(|cx| Self::new(track, self.peer_id, self.user.clone(), cx)))
119    }
120
121    fn to_item_events(event: &Self::Event, mut f: impl FnMut(ItemEvent)) {
122        match event {
123            Event::Close => f(ItemEvent::CloseItem),
124        }
125    }
126}