Show host in titlebar

Co-Authored-By: Max Brunsfeld <max@zed.dev>
This commit is contained in:
Conrad Irwin 2023-09-29 16:02:36 -06:00
parent 219715449d
commit 1cfc2f0c07
7 changed files with 110 additions and 2 deletions

View file

@ -453,6 +453,10 @@ impl Client {
self.state.read().status.1.clone()
}
pub fn is_connected(&self) -> bool {
matches!(&*self.status().borrow(), Status::Connected { .. })
}
fn set_status(self: &Arc<Self>, status: Status, cx: &AsyncAppContext) {
log::info!("set status on client {}: {:?}", self.id, status);
let mut state = self.state.write();

View file

@ -595,6 +595,10 @@ impl UserStore {
self.load_users(proto::FuzzySearchUsers { query }, cx)
}
pub fn get_cached_user(&self, user_id: u64) -> Option<Arc<User>> {
self.users.get(&user_id).cloned()
}
pub fn get_user(
&mut self,
user_id: u64,

View file

@ -215,7 +215,13 @@ impl CollabTitlebarItem {
let git_style = theme.titlebar.git_menu_button.clone();
let item_spacing = theme.titlebar.item_spacing;
let mut ret = Flex::row().with_child(
let mut ret = Flex::row();
if let Some(project_host) = self.collect_project_host(theme.clone(), cx) {
ret = ret.with_child(project_host)
}
ret = ret.with_child(
Stack::new()
.with_child(
MouseEventHandler::new::<ToggleProjectMenu, _>(0, cx, |mouse_state, cx| {
@ -283,6 +289,71 @@ impl CollabTitlebarItem {
ret.into_any()
}
fn collect_project_host(
&self,
theme: Arc<Theme>,
cx: &mut ViewContext<Self>,
) -> Option<AnyElement<Self>> {
if ActiveCall::global(cx).read(cx).room().is_none() {
return None;
}
let project = self.project.read(cx);
let user_store = self.user_store.read(cx);
if project.is_local() {
return None;
}
let Some(host) = project.host() else {
return None;
};
let (Some(host_user), Some(participant_index)) = (
user_store.get_cached_user(host.user_id),
user_store.participant_indices().get(&host.user_id),
) else {
return None;
};
enum ProjectHost {}
enum ProjectHostTooltip {}
let host_style = theme.titlebar.project_host.clone();
let selection_style = theme
.editor
.selection_style_for_room_participant(participant_index.0);
let peer_id = host.peer_id.clone();
Some(
MouseEventHandler::new::<ProjectHost, _>(0, cx, |mouse_state, _| {
let mut host_style = host_style.style_for(mouse_state).clone();
host_style.text.color = selection_style.cursor;
Label::new(host_user.github_login.clone(), host_style.text)
.contained()
.with_style(host_style.container)
.aligned()
.left()
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, this, cx| {
if let Some(workspace) = this.workspace.upgrade(cx) {
if let Some(task) =
workspace.update(cx, |workspace, cx| workspace.follow(peer_id, cx))
{
task.detach_and_log_err(cx);
}
}
})
.with_tooltip::<ProjectHostTooltip>(
0,
host_user.github_login.clone() + " is sharing this project. Click to follow.",
None,
theme.tooltip.clone(),
cx,
)
.into_any_named("project-host"),
)
}
fn window_activation_changed(&mut self, active: bool, cx: &mut ViewContext<Self>) {
let project = if active {
Some(self.project.clone())

View file

@ -975,6 +975,10 @@ impl Project {
&self.collaborators
}
pub fn host(&self) -> Option<&Collaborator> {
self.collaborators.values().find(|c| c.replica_id == 0)
}
/// Collect all worktrees, including ones that don't appear in the project panel
pub fn worktrees<'a>(
&'a self,

View file

@ -131,6 +131,7 @@ pub struct Titlebar {
pub menu: TitlebarMenu,
pub project_menu_button: Toggleable<Interactive<ContainedText>>,
pub git_menu_button: Toggleable<Interactive<ContainedText>>,
pub project_host: Interactive<ContainedText>,
pub item_spacing: f32,
pub face_pile_spacing: f32,
pub avatar_ribbon: AvatarRibbon,

View file

@ -2608,6 +2608,24 @@ impl Workspace {
.and_then(|leader_id| self.toggle_follow(leader_id, cx))
}
pub fn follow(
&mut self,
leader_id: PeerId,
cx: &mut ViewContext<Self>,
) -> Option<Task<Result<()>>> {
for (existing_leader_id, states_by_pane) in &mut self.follower_states_by_leader {
if leader_id == *existing_leader_id {
for (pane, _) in states_by_pane {
cx.focus(pane);
return None;
}
}
}
// not currently following, so follow.
self.toggle_follow(leader_id, cx)
}
pub fn unfollow(
&mut self,
pane: &ViewHandle<Pane>,

View file

@ -1,4 +1,4 @@
import { icon_button, toggleable_icon_button, toggleable_text_button } from "../component"
import { icon_button, text_button, toggleable_icon_button, toggleable_text_button } from "../component"
import { interactive, toggleable } from "../element"
import { useTheme, with_opacity } from "../theme"
import { background, border, foreground, text } from "./components"
@ -191,6 +191,12 @@ export function titlebar(): any {
color: "variant",
}),
project_host: text_button({
text_properties: {
weight: "bold"
}
}),
// Collaborators
leader_avatar: {
width: avatar_width,