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