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, ParentElement,
  7    Render, SharedString, Styled, 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()
 74            .size_full()
 75            .children(frame.map(|frame| img(frame.image()).w_full()))
 76    }
 77}
 78// impl View for SharedScreen {
 79//     fn ui_name() -> &'static str {
 80//         "SharedScreen"
 81//     }
 82
 83//     fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
 84//         enum Focus {}
 85
 86//         let frame = self.frame.clone();
 87//         MouseEventHandler::new::<Focus, _>(0, cx, |_, cx| {
 88//             Canvas::new(move |bounds, _, _, cx| {
 89//                 if let Some(frame) = frame.clone() {
 90//                     let size = constrain_size_preserving_aspect_ratio(
 91//                         bounds.size(),
 92//                         vec2f(frame.width() as f32, frame.height() as f32),
 93//                     );
 94//                     let origin = bounds.origin() + (bounds.size() / 2.) - size / 2.;
 95//                     cx.scene().push_surface(gpui::platform::mac::Surface {
 96//                         bounds: RectF::new(origin, size),
 97//                         image_buffer: frame.image(),
 98//                     });
 99//                 }
100//             })
101//             .contained()
102//             .with_style(theme::current(cx).shared_screen)
103//         })
104//         .on_down(MouseButton::Left, |_, _, cx| cx.focus_parent())
105//         .into_any()
106//     }
107// }
108
109impl Item for SharedScreen {
110    fn tab_tooltip_text(&self, _: &AppContext) -> Option<SharedString> {
111        Some(format!("{}'s screen", self.user.github_login).into())
112    }
113    fn deactivated(&mut self, cx: &mut ViewContext<Self>) {
114        if let Some(nav_history) = self.nav_history.as_mut() {
115            nav_history.push::<()>(None, cx);
116        }
117    }
118
119    fn tab_content(&self, _: Option<usize>, _: &WindowContext<'_>) -> gpui::AnyElement {
120        div().child("Shared screen").into_any()
121        // Flex::row()
122        //     .with_child(
123        //         Svg::new("icons/desktop.svg")
124        //             .with_color(style.label.text.color)
125        //             .constrained()
126        //             .with_width(style.type_icon_width)
127        //             .aligned()
128        //             .contained()
129        //             .with_margin_right(style.spacing),
130        //     )
131        //     .with_child(
132        //         Label::new(
133        //             format!("{}'s screen", self.user.github_login),
134        //             style.label.clone(),
135        //         )
136        //         .aligned(),
137        //     )
138        //     .into_any()
139    }
140
141    fn set_nav_history(&mut self, history: ItemNavHistory, _: &mut ViewContext<Self>) {
142        self.nav_history = Some(history);
143    }
144
145    fn clone_on_split(
146        &self,
147        _workspace_id: WorkspaceId,
148        cx: &mut ViewContext<Self>,
149    ) -> Option<View<Self>> {
150        let track = self.track.upgrade()?;
151        Some(cx.build_view(|cx| Self::new(&track, self.peer_id, self.user.clone(), cx)))
152    }
153}