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}