shared_screen.rs

  1use crate::participant::{Frame, RemoteVideoTrack};
  2use anyhow::Result;
  3use client::{proto::PeerId, User};
  4use futures::StreamExt;
  5use gpui::{
  6    div, img, AppContext, Div, Element, EventEmitter, FocusHandle, FocusableView, ImageData,
  7    ParentElement, Render, SharedString, Task, View, ViewContext, VisualContext, WindowContext,
  8};
  9use std::sync::{Arc, Weak};
 10use workspace::{item::Item, ItemNavHistory, WorkspaceId};
 11
 12pub enum Event {
 13    Close,
 14}
 15
 16pub struct SharedScreen {
 17    track: Weak<RemoteVideoTrack>,
 18    frame: Option<Frame>,
 19    pub peer_id: PeerId,
 20    user: Arc<User>,
 21    nav_history: Option<ItemNavHistory>,
 22    _maintain_frame: Task<Result<()>>,
 23    focus: FocusHandle,
 24}
 25
 26impl SharedScreen {
 27    pub fn new(
 28        track: &Arc<RemoteVideoTrack>,
 29        peer_id: PeerId,
 30        user: Arc<User>,
 31        cx: &mut ViewContext<Self>,
 32    ) -> Self {
 33        cx.focus_handle();
 34        let mut frames = track.frames();
 35        Self {
 36            track: Arc::downgrade(track),
 37            frame: None,
 38            peer_id,
 39            user,
 40            nav_history: Default::default(),
 41            _maintain_frame: cx.spawn(|this, mut cx| async move {
 42                while let Some(frame) = frames.next().await {
 43                    this.update(&mut cx, |this, cx| {
 44                        this.frame = Some(frame);
 45                        cx.notify();
 46                    })?;
 47                }
 48                this.update(&mut cx, |_, cx| cx.emit(Event::Close))?;
 49                Ok(())
 50            }),
 51            focus: cx.focus_handle(),
 52        }
 53    }
 54}
 55
 56impl EventEmitter<Event> for SharedScreen {}
 57impl EventEmitter<workspace::item::ItemEvent> for SharedScreen {}
 58
 59impl FocusableView for SharedScreen {
 60    fn focus_handle(&self, _: &AppContext) -> FocusHandle {
 61        self.focus.clone()
 62    }
 63}
 64impl Render for SharedScreen {
 65    type Element = Div;
 66    fn render(&mut self, _: &mut ViewContext<Self>) -> Self::Element {
 67        let frame = self.frame.clone();
 68        div().children(frame.map(|frame| {
 69            img().data(Arc::new(ImageData::new(image::ImageBuffer::new(
 70                frame.width() as u32,
 71                frame.height() as u32,
 72            ))))
 73        }))
 74    }
 75}
 76// impl View for SharedScreen {
 77//     fn ui_name() -> &'static str {
 78//         "SharedScreen"
 79//     }
 80
 81//     fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
 82//         enum Focus {}
 83
 84//         let frame = self.frame.clone();
 85//         MouseEventHandler::new::<Focus, _>(0, cx, |_, cx| {
 86//             Canvas::new(move |bounds, _, _, cx| {
 87//                 if let Some(frame) = frame.clone() {
 88//                     let size = constrain_size_preserving_aspect_ratio(
 89//                         bounds.size(),
 90//                         vec2f(frame.width() as f32, frame.height() as f32),
 91//                     );
 92//                     let origin = bounds.origin() + (bounds.size() / 2.) - size / 2.;
 93//                     cx.scene().push_surface(gpui::platform::mac::Surface {
 94//                         bounds: RectF::new(origin, size),
 95//                         image_buffer: frame.image(),
 96//                     });
 97//                 }
 98//             })
 99//             .contained()
100//             .with_style(theme::current(cx).shared_screen)
101//         })
102//         .on_down(MouseButton::Left, |_, _, cx| cx.focus_parent())
103//         .into_any()
104//     }
105// }
106
107impl Item for SharedScreen {
108    fn tab_tooltip_text(&self, _: &AppContext) -> Option<SharedString> {
109        Some(format!("{}'s screen", self.user.github_login).into())
110    }
111    fn deactivated(&mut self, cx: &mut ViewContext<Self>) {
112        if let Some(nav_history) = self.nav_history.as_mut() {
113            nav_history.push::<()>(None, cx);
114        }
115    }
116
117    fn tab_content(&self, _: Option<usize>, _: &WindowContext<'_>) -> gpui::AnyElement {
118        div().child("Shared screen").into_any()
119        // Flex::row()
120        //     .with_child(
121        //         Svg::new("icons/desktop.svg")
122        //             .with_color(style.label.text.color)
123        //             .constrained()
124        //             .with_width(style.type_icon_width)
125        //             .aligned()
126        //             .contained()
127        //             .with_margin_right(style.spacing),
128        //     )
129        //     .with_child(
130        //         Label::new(
131        //             format!("{}'s screen", self.user.github_login),
132        //             style.label.clone(),
133        //         )
134        //         .aligned(),
135        //     )
136        //     .into_any()
137    }
138
139    fn set_nav_history(&mut self, history: ItemNavHistory, _: &mut ViewContext<Self>) {
140        self.nav_history = Some(history);
141    }
142
143    fn clone_on_split(
144        &self,
145        _workspace_id: WorkspaceId,
146        cx: &mut ViewContext<Self>,
147    ) -> Option<View<Self>> {
148        let track = self.track.upgrade()?;
149        Some(cx.build_view(|cx| Self::new(&track, self.peer_id, self.user.clone(), cx)))
150    }
151}