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}