Disambiguate branch name in title bar (#44793)

Cole Miller created

Add the repository name when:

- there's more than one repository, and
- the name of the active repository doesn't match the name of the
project (to avoid stuttering with the adjacent project switcher button)

Release Notes:

- The branch name in the title bar now includes the name of the current
repository when needed to disambiguate.

Change summary

crates/title_bar/src/title_bar.rs | 60 +++++++++++++++++++++-----------
1 file changed, 39 insertions(+), 21 deletions(-)

Detailed changes

crates/title_bar/src/title_bar.rs 🔗

@@ -167,7 +167,7 @@ impl Render for TitleBar {
                                         .child(self.render_project_name(cx))
                                 })
                                 .when(title_bar_settings.show_branch_name, |title_bar| {
-                                    title_bar.children(self.render_project_branch(cx))
+                                    title_bar.children(self.render_project_repo(cx))
                                 })
                         })
                 })
@@ -319,6 +319,27 @@ impl TitleBar {
         }
     }
 
+    fn project_name(&self, cx: &Context<Self>) -> Option<SharedString> {
+        self.project
+            .read(cx)
+            .visible_worktrees(cx)
+            .map(|worktree| {
+                let worktree = worktree.read(cx);
+                let settings_location = SettingsLocation {
+                    worktree_id: worktree.id(),
+                    path: RelPath::empty(),
+                };
+
+                let settings = WorktreeSettings::get(Some(settings_location), cx);
+                let name = match &settings.project_name {
+                    Some(name) => name.as_str(),
+                    None => worktree.root_name_str(),
+                };
+                SharedString::new(name)
+            })
+            .next()
+    }
+
     fn render_remote_project_connection(&self, cx: &mut Context<Self>) -> Option<AnyElement> {
         let options = self.project.read(cx).remote_connection_options(cx)?;
         let host: SharedString = options.display_name().into();
@@ -451,27 +472,10 @@ impl TitleBar {
     }
 
     pub fn render_project_name(&self, cx: &mut Context<Self>) -> impl IntoElement {
-        let name = self
-            .project
-            .read(cx)
-            .visible_worktrees(cx)
-            .map(|worktree| {
-                let worktree = worktree.read(cx);
-                let settings_location = SettingsLocation {
-                    worktree_id: worktree.id(),
-                    path: RelPath::empty(),
-                };
-
-                let settings = WorktreeSettings::get(Some(settings_location), cx);
-                match &settings.project_name {
-                    Some(name) => name.as_str(),
-                    None => worktree.root_name_str(),
-                }
-            })
-            .next();
+        let name = self.project_name(cx);
         let is_project_selected = name.is_some();
         let name = if let Some(name) = name {
-            util::truncate_and_trailoff(name, MAX_PROJECT_NAME_LENGTH)
+            util::truncate_and_trailoff(&name, MAX_PROJECT_NAME_LENGTH)
         } else {
             "Open recent project".to_string()
         };
@@ -500,9 +504,10 @@ impl TitleBar {
             }))
     }
 
-    pub fn render_project_branch(&self, cx: &mut Context<Self>) -> Option<impl IntoElement> {
+    pub fn render_project_repo(&self, cx: &mut Context<Self>) -> Option<impl IntoElement> {
         let settings = TitleBarSettings::get_global(cx);
         let repository = self.project.read(cx).active_repository(cx)?;
+        let repository_count = self.project.read(cx).repositories(cx).len();
         let workspace = self.workspace.upgrade()?;
         let repo = repository.read(cx);
         let branch_name = repo
@@ -519,6 +524,19 @@ impl TitleBar {
                         .collect::<String>()
                 })
             })?;
+        let project_name = self.project_name(cx);
+        let repo_name = repo
+            .work_directory_abs_path
+            .file_name()
+            .and_then(|name| name.to_str())
+            .map(SharedString::new);
+        let show_repo_name =
+            repository_count > 1 && repo.branch.is_some() && repo_name != project_name;
+        let branch_name = if let Some(repo_name) = repo_name.filter(|_| show_repo_name) {
+            format!("{repo_name}/{branch_name}")
+        } else {
+            branch_name
+        };
 
         Some(
             Button::new("project_branch_trigger", branch_name)