shared_screen.rs

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