mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-27 12:02:07 +03:00
Add control to toggle screen-sharing
This commit is contained in:
parent
219793afcc
commit
773f569385
3
assets/icons/disable_screen_sharing_12.svg
Normal file
3
assets/icons/disable_screen_sharing_12.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M11 0.666656H1C0.447917 0.666656 0 1.11457 0 1.66666V8.33332C0 8.88541 0.447917 9.33332 1 9.33332H5L4.66667 10.3333H3.16667C2.89167 10.3333 2.66667 10.5583 2.66667 10.8333C2.66667 11.1083 2.89167 11.3333 3.16667 11.3333H8.83333C9.10938 11.3333 9.33333 11.1094 9.33333 10.8333C9.33333 10.5573 9.10938 10.3333 8.83333 10.3333H7.33333L7 9.33332H11C11.5521 9.33332 12 8.88541 12 8.33332V1.66666C12 1.11457 11.5521 0.666656 11 0.666656ZM10.6667 7.99999H1.33333V1.99999H10.6667V7.99999Z" fill="#979DB4"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 611 B |
3
assets/icons/enable_screen_sharing_12.svg
Normal file
3
assets/icons/enable_screen_sharing_12.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M8.53324 9.90014H7.18324L6.88324 9.00014H7.63305L6.10211 7.80014H1.78324V4.41577L0.583236 3.47452V8.10014C0.583217 8.59702 0.986361 9.00014 1.46636 9.00014H5.04949L4.74949 9.90014H3.43324C3.1848 9.90014 2.98324 10.1017 2.98324 10.3501C2.98324 10.5986 3.1848 10.8001 3.43324 10.8001H8.51637C8.7648 10.8001 8.96637 10.5986 8.96637 10.3501C8.96637 10.1017 8.79762 9.90014 8.53324 9.90014ZM11.8276 9.99577L10.5507 8.99489C11.0234 8.96789 11.3999 8.57939 11.3999 8.09996V2.09995C11.3999 1.60308 10.9968 1.19995 10.4999 1.19995H1.5168C1.28617 1.19995 1.07786 1.28939 0.918674 1.43208L0.727799 1.29595C0.645299 1.23145 0.547423 1.19995 0.450673 1.19995C0.316986 1.19995 0.184611 1.2592 0.0961106 1.37226C-0.057452 1.56801 -0.023327 1.85095 0.172236 2.00414L11.2724 10.7041C11.4693 10.8579 11.7519 10.8226 11.9041 10.6276C12.0581 10.4321 12.0224 10.149 11.8274 9.99521L11.8276 9.99577ZM10.1832 7.80014H9.00968L2.11905 2.40014H10.1816L10.1832 7.80014Z" fill="#93A1A1"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.0 KiB |
@ -132,8 +132,6 @@ impl ActiveCall {
|
|||||||
Room::create(recipient_user_id, initial_project, client, user_store, cx)
|
Room::create(recipient_user_id, initial_project, client, user_store, cx)
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
room.update(&mut cx, |room, cx| room.share_screen(cx))
|
|
||||||
.await?;
|
|
||||||
this.update(&mut cx, |this, cx| this.set_room(Some(room), cx));
|
this.update(&mut cx, |this, cx| this.set_room(Some(room), cx));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -606,6 +606,12 @@ impl Room {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_screen_sharing(&self) -> bool {
|
||||||
|
self.live_kit
|
||||||
|
.as_ref()
|
||||||
|
.map_or(false, |live_kit| live_kit.screen_track.is_some())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn share_screen(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
|
pub fn share_screen(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
|
||||||
if self.status.is_offline() {
|
if self.status.is_offline() {
|
||||||
return Task::ready(Err(anyhow!("room is offline")));
|
return Task::ready(Err(anyhow!("room is offline")));
|
||||||
@ -617,22 +623,49 @@ impl Room {
|
|||||||
.first()
|
.first()
|
||||||
.ok_or_else(|| anyhow!("no display found"))?;
|
.ok_or_else(|| anyhow!("no display found"))?;
|
||||||
let track = LocalVideoTrack::screen_share_for_display(&display);
|
let track = LocalVideoTrack::screen_share_for_display(&display);
|
||||||
|
|
||||||
let publication = this
|
let publication = this
|
||||||
.upgrade(&cx)?
|
.upgrade(&cx)
|
||||||
|
.ok_or_else(|| anyhow!("room was dropped"))?
|
||||||
.read_with(&cx, |this, _| {
|
.read_with(&cx, |this, _| {
|
||||||
this.live_kit
|
this.live_kit
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|live_kit| live_kit.room.publish_video_track(&track))
|
.map(|live_kit| live_kit.room.publish_video_track(&track))
|
||||||
})?
|
})
|
||||||
|
.ok_or_else(|| anyhow!("live-kit was not initialized"))?
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
this.upgrade(&cx)?.update(cx, |this, _| {
|
this.upgrade(&cx)
|
||||||
this.live_kit.as_mut()?.screen_track = Some(publication);
|
.ok_or_else(|| anyhow!("room was dropped"))?
|
||||||
Some(())
|
.update(&mut cx, |this, cx| {
|
||||||
})
|
let live_kit = this
|
||||||
|
.live_kit
|
||||||
|
.as_mut()
|
||||||
|
.ok_or_else(|| anyhow!("live-kit was not initialized"))?;
|
||||||
|
live_kit.screen_track = Some(publication);
|
||||||
|
cx.notify();
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn unshare_screen(&mut self, cx: &mut ModelContext<Self>) -> Result<()> {
|
||||||
|
if self.status.is_offline() {
|
||||||
|
return Err(anyhow!("room is offline"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let live_kit = self
|
||||||
|
.live_kit
|
||||||
|
.as_mut()
|
||||||
|
.ok_or_else(|| anyhow!("live-kit was not initialized"))?;
|
||||||
|
let track = live_kit
|
||||||
|
.screen_track
|
||||||
|
.take()
|
||||||
|
.ok_or_else(|| anyhow!("screen was not shared"))?;
|
||||||
|
live_kit.room.unpublish_track(track);
|
||||||
|
cx.notify();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LiveKitRoom {
|
struct LiveKitRoom {
|
||||||
|
@ -10,17 +10,21 @@ use gpui::{
|
|||||||
geometry::{rect::RectF, vector::vec2f, PathBuilder},
|
geometry::{rect::RectF, vector::vec2f, PathBuilder},
|
||||||
json::{self, ToJson},
|
json::{self, ToJson},
|
||||||
Border, CursorStyle, Entity, ModelHandle, MouseButton, MutableAppContext, RenderContext,
|
Border, CursorStyle, Entity, ModelHandle, MouseButton, MutableAppContext, RenderContext,
|
||||||
Subscription, View, ViewContext, ViewHandle, WeakViewHandle,
|
Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle,
|
||||||
};
|
};
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use theme::Theme;
|
use theme::Theme;
|
||||||
use workspace::{FollowNextCollaborator, JoinProject, ToggleFollow, Workspace};
|
use workspace::{FollowNextCollaborator, JoinProject, ToggleFollow, Workspace};
|
||||||
|
|
||||||
actions!(collab, [ToggleCollaborationMenu, ShareProject]);
|
actions!(
|
||||||
|
collab,
|
||||||
|
[ToggleCollaborationMenu, ToggleScreenSharing, ShareProject]
|
||||||
|
);
|
||||||
|
|
||||||
pub fn init(cx: &mut MutableAppContext) {
|
pub fn init(cx: &mut MutableAppContext) {
|
||||||
cx.add_action(CollabTitlebarItem::toggle_contacts_popover);
|
cx.add_action(CollabTitlebarItem::toggle_contacts_popover);
|
||||||
|
cx.add_action(CollabTitlebarItem::toggle_screen_sharing);
|
||||||
cx.add_action(CollabTitlebarItem::share_project);
|
cx.add_action(CollabTitlebarItem::share_project);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,10 +52,12 @@ impl View for CollabTitlebarItem {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let theme = cx.global::<Settings>().theme.clone();
|
let theme = cx.global::<Settings>().theme.clone();
|
||||||
let project = workspace.read(cx).project().read(cx);
|
|
||||||
|
|
||||||
let mut container = Flex::row();
|
let mut container = Flex::row();
|
||||||
|
container.add_children(self.render_toggle_screen_sharing_button(&theme, cx));
|
||||||
|
|
||||||
if workspace.read(cx).client().status().borrow().is_connected() {
|
if workspace.read(cx).client().status().borrow().is_connected() {
|
||||||
|
let project = workspace.read(cx).project().read(cx);
|
||||||
if project.is_shared()
|
if project.is_shared()
|
||||||
|| project.is_remote()
|
|| project.is_remote()
|
||||||
|| ActiveCall::global(cx).read(cx).room().is_none()
|
|| ActiveCall::global(cx).read(cx).room().is_none()
|
||||||
@ -169,6 +175,19 @@ impl CollabTitlebarItem {
|
|||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn toggle_screen_sharing(&mut self, _: &ToggleScreenSharing, cx: &mut ViewContext<Self>) {
|
||||||
|
if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
|
||||||
|
let toggle_screen_sharing = room.update(cx, |room, cx| {
|
||||||
|
if room.is_screen_sharing() {
|
||||||
|
Task::ready(room.unshare_screen(cx))
|
||||||
|
} else {
|
||||||
|
room.share_screen(cx)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
toggle_screen_sharing.detach_and_log_err(cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn render_toggle_contacts_button(
|
fn render_toggle_contacts_button(
|
||||||
&self,
|
&self,
|
||||||
theme: &Theme,
|
theme: &Theme,
|
||||||
@ -237,6 +256,43 @@ impl CollabTitlebarItem {
|
|||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_toggle_screen_sharing_button(
|
||||||
|
&self,
|
||||||
|
theme: &Theme,
|
||||||
|
cx: &mut RenderContext<Self>,
|
||||||
|
) -> Option<ElementBox> {
|
||||||
|
let active_call = ActiveCall::global(cx);
|
||||||
|
let room = active_call.read(cx).room().cloned()?;
|
||||||
|
let icon = if room.read(cx).is_screen_sharing() {
|
||||||
|
"icons/disable_screen_sharing_12.svg"
|
||||||
|
} else {
|
||||||
|
"icons/enable_screen_sharing_12.svg"
|
||||||
|
};
|
||||||
|
let titlebar = &theme.workspace.titlebar;
|
||||||
|
Some(
|
||||||
|
MouseEventHandler::<ToggleScreenSharing>::new(0, cx, |state, _| {
|
||||||
|
let style = titlebar.call_control.style_for(state, false);
|
||||||
|
Svg::new(icon)
|
||||||
|
.with_color(style.color)
|
||||||
|
.constrained()
|
||||||
|
.with_width(style.icon_width)
|
||||||
|
.aligned()
|
||||||
|
.constrained()
|
||||||
|
.with_width(style.button_width)
|
||||||
|
.with_height(style.button_width)
|
||||||
|
.contained()
|
||||||
|
.with_style(style.container)
|
||||||
|
.boxed()
|
||||||
|
})
|
||||||
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
|
.on_click(MouseButton::Left, move |_, cx| {
|
||||||
|
cx.dispatch_action(ToggleScreenSharing);
|
||||||
|
})
|
||||||
|
.aligned()
|
||||||
|
.boxed(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn render_share_button(&self, theme: &Theme, cx: &mut RenderContext<Self>) -> ElementBox {
|
fn render_share_button(&self, theme: &Theme, cx: &mut RenderContext<Self>) -> ElementBox {
|
||||||
enum Share {}
|
enum Share {}
|
||||||
|
|
||||||
|
@ -95,6 +95,13 @@ public func LKRoomPublishVideoTrack(room: UnsafeRawPointer, track: UnsafeRawPoin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@_cdecl("LKRoomUnpublishTrack")
|
||||||
|
public func LKRoomUnpublishTrack(room: UnsafeRawPointer, publication: UnsafeRawPointer) {
|
||||||
|
let room = Unmanaged<Room>.fromOpaque(room).takeUnretainedValue()
|
||||||
|
let publication = Unmanaged<LocalTrackPublication>.fromOpaque(publication).takeUnretainedValue()
|
||||||
|
room.localParticipant?.unpublish(publication: publication)
|
||||||
|
}
|
||||||
|
|
||||||
@_cdecl("LKRoomVideoTracksForRemoteParticipant")
|
@_cdecl("LKRoomVideoTracksForRemoteParticipant")
|
||||||
public func LKRoomVideoTracksForRemoteParticipant(room: UnsafeRawPointer, participantId: CFString) -> CFArray? {
|
public func LKRoomVideoTracksForRemoteParticipant(room: UnsafeRawPointer, participantId: CFString) -> CFArray? {
|
||||||
let room = Unmanaged<Room>.fromOpaque(room).takeUnretainedValue()
|
let room = Unmanaged<Room>.fromOpaque(room).takeUnretainedValue()
|
||||||
|
@ -48,6 +48,7 @@ extern "C" {
|
|||||||
callback: extern "C" fn(*mut c_void, *mut c_void, CFStringRef),
|
callback: extern "C" fn(*mut c_void, *mut c_void, CFStringRef),
|
||||||
callback_data: *mut c_void,
|
callback_data: *mut c_void,
|
||||||
);
|
);
|
||||||
|
fn LKRoomUnpublishTrack(room: *const c_void, publication: *const c_void);
|
||||||
fn LKRoomVideoTracksForRemoteParticipant(
|
fn LKRoomVideoTracksForRemoteParticipant(
|
||||||
room: *const c_void,
|
room: *const c_void,
|
||||||
participant_id: CFStringRef,
|
participant_id: CFStringRef,
|
||||||
@ -134,6 +135,12 @@ impl Room {
|
|||||||
async { rx.await.unwrap().context("error publishing video track") }
|
async { rx.await.unwrap().context("error publishing video track") }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn unpublish_track(&self, publication: LocalTrackPublication) {
|
||||||
|
unsafe {
|
||||||
|
LKRoomUnpublishTrack(self.native_room, publication.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn remote_video_tracks(&self, participant_id: &str) -> Vec<Arc<RemoteVideoTrack>> {
|
pub fn remote_video_tracks(&self, participant_id: &str) -> Vec<Arc<RemoteVideoTrack>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let tracks = LKRoomVideoTracksForRemoteParticipant(
|
let tracks = LKRoomVideoTracksForRemoteParticipant(
|
||||||
|
@ -79,6 +79,7 @@ pub struct Titlebar {
|
|||||||
pub sign_in_prompt: Interactive<ContainedText>,
|
pub sign_in_prompt: Interactive<ContainedText>,
|
||||||
pub outdated_warning: ContainedText,
|
pub outdated_warning: ContainedText,
|
||||||
pub share_button: Interactive<ContainedText>,
|
pub share_button: Interactive<ContainedText>,
|
||||||
|
pub call_control: Interactive<IconButton>,
|
||||||
pub toggle_contacts_button: Interactive<IconButton>,
|
pub toggle_contacts_button: Interactive<IconButton>,
|
||||||
pub toggle_contacts_badge: ContainerStyle,
|
pub toggle_contacts_badge: ContainerStyle,
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,18 @@ export default function workspace(theme: Theme) {
|
|||||||
},
|
},
|
||||||
cornerRadius: 6,
|
cornerRadius: 6,
|
||||||
},
|
},
|
||||||
|
callControl: {
|
||||||
|
cornerRadius: 6,
|
||||||
|
color: iconColor(theme, "secondary"),
|
||||||
|
iconWidth: 12,
|
||||||
|
buttonWidth: 20,
|
||||||
|
hover: {
|
||||||
|
background: backgroundColor(theme, "on300", "hovered"),
|
||||||
|
color: iconColor(theme, "active"),
|
||||||
|
},
|
||||||
|
},
|
||||||
toggleContactsButton: {
|
toggleContactsButton: {
|
||||||
|
margin: { left: 6 },
|
||||||
cornerRadius: 6,
|
cornerRadius: 6,
|
||||||
color: iconColor(theme, "secondary"),
|
color: iconColor(theme, "secondary"),
|
||||||
iconWidth: 8,
|
iconWidth: 8,
|
||||||
|
Loading…
Reference in New Issue
Block a user