From 36557bd0b5f2a56460217033c3d545eb9ff212c6 Mon Sep 17 00:00:00 2001 From: Bennet Bo Fenner Date: Thu, 16 Apr 2026 13:49:00 +0200 Subject: [PATCH] workspace: Fix incorrect project paths on welcome page (#54056) Fixes an issue where we would only display the first path of the project on the welcome page Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Fixed an issue where incorrect project paths would be displayed on the welcome tab --- crates/workspace/src/welcome.rs | 60 +++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/crates/workspace/src/welcome.rs b/crates/workspace/src/welcome.rs index 5bfed0ceed93a4b1216b5117486d6ef5f1d5571b..a13ec56b2e07a81667fe096a8780393d93bf6f48 100644 --- a/crates/workspace/src/welcome.rs +++ b/crates/workspace/src/welcome.rs @@ -399,18 +399,11 @@ impl WelcomePage { location: &SerializedWorkspaceLocation, paths: &PathList, ) -> impl IntoElement { + let name = project_name(paths); + let (icon, title) = match location { - SerializedWorkspaceLocation::Local => { - let path = paths.paths().first().map(|p| p.as_path()); - let name = path - .and_then(|p| p.file_name()) - .map(|n| n.to_string_lossy().to_string()) - .unwrap_or_else(|| "Untitled".to_string()); - (IconName::Folder, name) - } - SerializedWorkspaceLocation::Remote(_) => { - (IconName::Server, "Remote Project".to_string()) - } + SerializedWorkspaceLocation::Local => (IconName::Folder, name), + SerializedWorkspaceLocation::Remote(_) => (IconName::Server, name), }; SectionButton::new( @@ -661,3 +654,48 @@ mod persistence { } } } + +fn project_name(paths: &PathList) -> String { + let joined = paths + .paths() + .iter() + .filter_map(|p| p.file_name().map(|n| n.to_string_lossy().to_string())) + .collect::>() + .join(", "); + if joined.is_empty() { + "Untitled".to_string() + } else { + joined + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_project_name_empty() { + let paths = PathList::new::<&str>(&[]); + assert_eq!(project_name(&paths), "Untitled"); + } + + #[test] + fn test_project_name_single() { + let paths = PathList::new(&["/home/user/my-project"]); + assert_eq!(project_name(&paths), "my-project"); + } + + #[test] + fn test_project_name_multiple() { + // PathList sorts lexicographically, so filenames appear in alpha order + let paths = PathList::new(&["/home/user/zed", "/home/user/api"]); + assert_eq!(project_name(&paths), "api, zed"); + } + + #[test] + fn test_project_name_root_path_filtered() { + // A bare root "/" has no file_name(), falls back to "Untitled" + let paths = PathList::new(&["/"]); + assert_eq!(project_name(&paths), "Untitled"); + } +}