diff --git a/crates/collab_ui/src/branches_button.rs b/crates/collab_ui/src/branches_button.rs index 6b9fb9fb72bbc3312ca47453184d14ec69ed04e6..7146e7f86b12f45675e7e0ed08b747d3918288b8 100644 --- a/crates/collab_ui/src/branches_button.rs +++ b/crates/collab_ui/src/branches_button.rs @@ -7,6 +7,8 @@ use gpui::{ use settings::Settings; use workspace::Workspace; +///! TODO: This file will hold the branch switching UI once we build it. + pub struct BranchesButton { workspace: WeakViewHandle, popup_menu: ViewHandle, diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index a435a15130eef4db024e7a371fef56ffb4bebc44..d74e2452e0f84ba01c2f07def0e986b8af32406c 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -24,6 +24,8 @@ use theme::{AvatarStyle, Theme}; use util::ResultExt; use workspace::{FollowNextCollaborator, Workspace}; +const MAX_TITLE_LENGTH: usize = 75; + actions!( collab, [ @@ -48,7 +50,6 @@ pub struct CollabTitlebarItem { workspace: WeakViewHandle, contacts_popover: Option>, user_menu: ViewHandle, - branches: ViewHandle, _subscriptions: Vec, } @@ -73,10 +74,7 @@ impl View for CollabTitlebarItem { let mut left_container = Flex::row(); let mut right_container = Flex::row().align_children_center(); - let project_title = self.collect_title_root_names(&project, cx); - left_container.add_child(self.render_title_root_names(&project_title, theme.clone())); - - left_container.add_child(ChildView::new(&self.branches.clone().into_any(), cx)); + left_container.add_child(self.collect_title_root_names(&project, theme.clone(), cx)); let user = self.user_store.read(cx).current_user(); let peer_id = self.client.peer_id(); @@ -106,7 +104,14 @@ impl View for CollabTitlebarItem { Stack::new() .with_child(left_container) - .with_child(right_container.aligned().right()) + .with_child( + Flex::row() + .with_child(right_container.contained().with_background_color( + theme.workspace.titlebar.container.background_color.unwrap(), + )) + .aligned() + .right(), + ) .into_any() } } @@ -163,25 +168,60 @@ impl CollabTitlebarItem { menu.set_position_mode(OverlayPositionMode::Local); menu }), - branches: cx.add_view(|cx| BranchesButton::new(workspace_handle.to_owned(), cx)), _subscriptions: subscriptions, } } - fn collect_title_root_names(&self, project: &Project, cx: &ViewContext) -> String { - let decorated_root_names: Vec<&str> = project.worktree_root_names(cx).collect(); - if decorated_root_names.is_empty() { - "empty project".to_owned() - } else { - decorated_root_names.join(", ") + fn collect_title_root_names( + &self, + project: &Project, + theme: Arc, + cx: &ViewContext, + ) -> AnyElement { + let names_and_branches = project.visible_worktrees(cx).map(|worktree| { + let worktree = worktree.read(cx); + (worktree.root_name(), worktree.root_git_entry()) + }); + + fn push_str(buffer: &mut String, index: &mut usize, str: &str) { + buffer.push_str(str); + *index += str.chars().count(); + } + + let mut indices = Vec::new(); + let mut index = 0; + let mut title = String::new(); + let mut names_and_branches = names_and_branches.peekable(); + while let Some((name, entry)) = names_and_branches.next() { + push_str(&mut title, &mut index, name); + if let Some(branch) = entry.and_then(|entry| entry.branch()) { + push_str(&mut title, &mut index, "/"); + let pre_index = index; + push_str(&mut title, &mut index, &branch); + indices.extend((pre_index..index).into_iter()) + } + if names_and_branches.peek().is_some() { + push_str(&mut title, &mut index, ", "); + if index >= MAX_TITLE_LENGTH { + title.push_str(" …"); + break; + } + } } - } - fn render_title_root_names(&self, title: &str, theme: Arc) -> AnyElement { let text_style = theme.workspace.titlebar.title.clone(); let item_spacing = theme.workspace.titlebar.item_spacing; - Label::new(title.to_owned(), text_style) + let mut highlight = text_style.clone(); + highlight.color = theme.workspace.titlebar.highlight_color; + + let style = LabelStyle { + text: text_style, + highlight_text: Some(highlight), + }; + + Label::new(title, style) + .with_highlights(indices) .contained() .with_margin_right(item_spacing) .aligned() diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index fb6bd85f02b1f7f43d98d819613543c0a95d3ab0..0bd23a0b87598c02d41a2d5ae79aaaefa5ba2a14 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -93,6 +93,7 @@ pub struct Titlebar { pub container: ContainerStyle, pub height: f32, pub title: TextStyle, + pub highlight_color: Color, pub item_spacing: f32, pub face_pile_spacing: f32, pub avatar_ribbon: AvatarRibbon, diff --git a/styles/src/styleTree/workspace.ts b/styles/src/styleTree/workspace.ts index 9b53ecc5d2fd8702bbf7ade760160cfdbe83067b..9d0c4de9f78eef989a71ee33c1b9da3fcc8f8a50 100644 --- a/styles/src/styleTree/workspace.ts +++ b/styles/src/styleTree/workspace.ts @@ -140,6 +140,7 @@ export default function workspace(colorScheme: ColorScheme) { // Project title: text(layer, "sans", "variant"), + highlight_color: text(layer, "sans", "active").color, // Collaborators leaderAvatar: {