diff --git a/crates/gpui/src/elements.rs b/crates/gpui/src/elements.rs index 59269f8af6..68c0b25f20 100644 --- a/crates/gpui/src/elements.rs +++ b/crates/gpui/src/elements.rs @@ -495,7 +495,7 @@ pub trait ParentElement<'a>: Extend + Sized { impl<'a, T> ParentElement<'a> for T where T: Extend {} -fn constrain_size_preserving_aspect_ratio(max_size: Vector2F, size: Vector2F) -> Vector2F { +pub fn constrain_size_preserving_aspect_ratio(max_size: Vector2F, size: Vector2F) -> Vector2F { if max_size.x().is_infinite() && max_size.y().is_infinite() { size } else if max_size.x().is_infinite() || max_size.x() / max_size.y() > size.x() / size.y() { diff --git a/crates/workspace/src/pane_group.rs b/crates/workspace/src/pane_group.rs index c1c4aef096..b99aba3b3a 100644 --- a/crates/workspace/src/pane_group.rs +++ b/crates/workspace/src/pane_group.rs @@ -1,8 +1,10 @@ use crate::{FollowerStatesByLeader, JoinProject, Pane, Workspace}; use anyhow::{anyhow, Result}; -use call::ActiveCall; +use call::{ActiveCall, ParticipantLocation}; use gpui::{ - elements::*, Axis, Border, CursorStyle, ModelHandle, MouseButton, RenderContext, ViewHandle, + elements::*, + geometry::{rect::RectF, vector::vec2f}, + Axis, Border, CursorStyle, ModelHandle, MouseButton, RenderContext, ViewHandle, }; use project::Project; use serde::Deserialize; @@ -130,18 +132,45 @@ impl Member { Some((collaborator.replica_id, participant)) }); - let mut border = Border::default(); - - let prompt = if let Some((replica_id, leader)) = leader { - let leader_color = theme.editor.replica_selection_style(replica_id).cursor; - border = Border::all(theme.workspace.leader_border_width, leader_color); + let border = if let Some((replica_id, _)) = leader.as_ref() { + let leader_color = theme.editor.replica_selection_style(*replica_id).cursor; + let mut border = Border::all(theme.workspace.leader_border_width, leader_color); border .color .fade_out(1. - theme.workspace.leader_border_opacity); border.overlay = true; + border + } else { + Border::default() + }; + let content = if leader.as_ref().map_or(false, |(_, leader)| { + leader.location == ParticipantLocation::External && !leader.tracks.is_empty() + }) { + let (_, leader) = leader.unwrap(); + let track = leader.tracks.values().next().unwrap(); + let frame = track.frame().cloned(); + Canvas::new(move |bounds, _, cx| { + if let Some(frame) = frame.clone() { + let size = constrain_size_preserving_aspect_ratio( + bounds.size(), + vec2f(frame.width() as f32, frame.height() as f32), + ); + let origin = bounds.origin() + (bounds.size() / 2.) - size / 2.; + cx.scene.push_surface(gpui::mac::Surface { + bounds: RectF::new(origin, size), + image_buffer: frame, + }); + } + }) + .boxed() + } else { + ChildView::new(pane, cx).boxed() + }; + + let prompt = if let Some((_, leader)) = leader { match leader.location { - call::ParticipantLocation::SharedProject { + ParticipantLocation::SharedProject { project_id: leader_project_id, } => { if Some(leader_project_id) == project.read(cx).remote_id() { @@ -186,7 +215,7 @@ impl Member { ) } } - call::ParticipantLocation::UnsharedProject => Some( + ParticipantLocation::UnsharedProject => Some( Label::new( format!( "{} is viewing an unshared Zed project", @@ -201,35 +230,28 @@ impl Member { .right() .boxed(), ), - call::ParticipantLocation::External => { - let frame = leader - .tracks - .values() - .next() - .and_then(|track| track.frame()) - .cloned(); - return Canvas::new(move |bounds, _, cx| { - if let Some(frame) = frame.clone() { - cx.scene.push_surface(gpui::mac::Surface { - bounds, - image_buffer: frame, - }); - } - }) - .boxed(); - } + ParticipantLocation::External => Some( + Label::new( + format!( + "{} is viewing a window outside of Zed", + leader.user.github_login + ), + theme.workspace.external_location_message.text.clone(), + ) + .contained() + .with_style(theme.workspace.external_location_message.container) + .aligned() + .bottom() + .right() + .boxed(), + ), } } else { None }; Stack::new() - .with_child( - ChildView::new(pane, cx) - .contained() - .with_border(border) - .boxed(), - ) + .with_child(Container::new(content).with_border(border).boxed()) .with_children(prompt) .boxed() } diff --git a/styles/src/styleTree/workspace.ts b/styles/src/styleTree/workspace.ts index cfbda49056..c8d32ae1a8 100644 --- a/styles/src/styleTree/workspace.ts +++ b/styles/src/styleTree/workspace.ts @@ -49,7 +49,7 @@ export default function workspace(theme: Theme) { ...text(theme, "sans", "primary", { size: "lg" }), }, externalLocationMessage: { - background: backgroundColor(theme, "info"), + background: backgroundColor(theme, "on500Info"), border: border(theme, "secondary"), cornerRadius: 6, padding: 12,