From dc0075b8e6961f6abebf66579ace5e2cd5711893 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Tue, 7 Jan 2025 11:45:38 +0800 Subject: [PATCH] Fix empty title in Recent Projects (#21952) Close #13595 Release Notes: - Fixed empty title in Recent Projects. --- | Before | After | | --- | --- | | SCR-20241213-nzxr | image | This is because the `LocalPathsOrder` get empty list. ``` [crates/recent_projects/src/recent_projects.rs:385:9] &location = Local( LocalPaths( [ "/Users/jason/Library/Application Support/Zed/prettier/node_modules", ], ), LocalPathsOrder( [], ), ) [crates/recent_projects/src/recent_projects.rs:386:9] &paths = [ "~/Library/Application Support/Zed/prettier/node_modules", ] [crates/recent_projects/src/recent_projects.rs:385:9] &location = Local( LocalPaths( [ "/Users/jason/github/tree-sitter-csv", ], ), LocalPathsOrder( [], ), ) [crates/recent_projects/src/recent_projects.rs:386:9] &paths = [ "~/github/tree-sitter-csv", ] [crates/recent_projects/src/recent_projects.rs:385:9] &location = Local( LocalPaths( [ "/Users/jason/work/autocorrect/autocorrect-website/dist", ], ), LocalPathsOrder( [], ), ) ``` --- Cargo.lock | 1 - crates/recent_projects/Cargo.toml | 1 - crates/recent_projects/src/recent_projects.rs | 39 +++------ crates/workspace/src/persistence/model.rs | 81 +++++++++++++++++++ crates/workspace/src/workspace.rs | 14 +--- 5 files changed, 93 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6cca9c2180..9d10fe090a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10340,7 +10340,6 @@ dependencies = [ "futures 0.3.31", "fuzzy", "gpui", - "itertools 0.13.0", "language", "log", "markdown", diff --git a/crates/recent_projects/Cargo.toml b/crates/recent_projects/Cargo.toml index 336ced57a8..be0556db39 100644 --- a/crates/recent_projects/Cargo.toml +++ b/crates/recent_projects/Cargo.toml @@ -22,7 +22,6 @@ file_finder.workspace = true futures.workspace = true fuzzy.workspace = true gpui.workspace = true -itertools.workspace = true log.workspace = true language.workspace = true markdown.workspace = true diff --git a/crates/recent_projects/src/recent_projects.rs b/crates/recent_projects/src/recent_projects.rs index 54129b85e8..7e425d2c0d 100644 --- a/crates/recent_projects/src/recent_projects.rs +++ b/crates/recent_projects/src/recent_projects.rs @@ -9,7 +9,6 @@ use gpui::{ Action, AnyElement, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, Subscription, Task, View, ViewContext, WeakView, }; -use itertools::Itertools; use ordered_float::OrderedFloat; use picker::{ highlighted_match_with_paths::{HighlightedMatchWithPaths, HighlightedText}, @@ -211,22 +210,12 @@ impl PickerDelegate for RecentProjectsDelegate { .enumerate() .filter(|(_, (id, _))| !self.is_current_workspace(*id, cx)) .map(|(id, (_, location))| { - let combined_string = match location { - SerializedWorkspaceLocation::Local(paths, order) => order - .order() - .iter() - .zip(paths.paths().iter()) - .sorted_by_key(|(i, _)| *i) - .map(|(_, path)| path.compact().to_string_lossy().into_owned()) - .collect::>() - .join(""), - SerializedWorkspaceLocation::Ssh(ssh_project) => ssh_project - .ssh_urls() - .iter() - .map(|path| path.to_string_lossy().to_string()) - .collect::>() - .join(""), - }; + let combined_string = location + .sorted_paths() + .iter() + .map(|path| path.compact().to_string_lossy().into_owned()) + .collect::>() + .join(""); StringMatchCandidate::new(id, &combined_string) }) @@ -364,21 +353,11 @@ impl PickerDelegate for RecentProjectsDelegate { let (_, location) = self.workspaces.get(hit.candidate_id)?; let mut path_start_offset = 0; - let paths = match location { - SerializedWorkspaceLocation::Local(paths, order) => Arc::new( - order - .order() - .iter() - .zip(paths.paths().iter()) - .sorted_by_key(|(i, _)| **i) - .map(|(_, path)| path.compact()) - .collect(), - ), - SerializedWorkspaceLocation::Ssh(ssh_project) => Arc::new(ssh_project.ssh_urls()), - }; - let (match_labels, paths): (Vec<_>, Vec<_>) = paths + let (match_labels, paths): (Vec<_>, Vec<_>) = location + .sorted_paths() .iter() + .map(|p| p.compact()) .map(|path| { let highlighted_text = highlights_for_path(path.as_ref(), &hit.positions, path_start_offset); diff --git a/crates/workspace/src/persistence/model.rs b/crates/workspace/src/persistence/model.rs index 7a368ee441..ac0c144aa3 100644 --- a/crates/workspace/src/persistence/model.rs +++ b/crates/workspace/src/persistence/model.rs @@ -9,6 +9,7 @@ use db::sqlez::{ statement::Statement, }; use gpui::{AsyncWindowContext, Model, View, WeakView}; +use itertools::Itertools as _; use project::Project; use remote::ssh_session::SshProjectId; use serde::{Deserialize, Serialize}; @@ -228,6 +229,28 @@ impl SerializedWorkspaceLocation { Self::Local(LocalPaths::new(sorted_paths), LocalPathsOrder::new(order)) } + + /// Get sorted paths + pub fn sorted_paths(&self) -> Arc> { + match self { + SerializedWorkspaceLocation::Local(paths, order) => { + if order.order().len() == 0 { + paths.paths().clone() + } else { + Arc::new( + order + .order() + .iter() + .zip(paths.paths().iter()) + .sorted_by_key(|(i, _)| **i) + .map(|(_, p)| p.clone()) + .collect(), + ) + } + } + SerializedWorkspaceLocation::Ssh(ssh_project) => Arc::new(ssh_project.ssh_urls()), + } + } } #[derive(Debug, PartialEq, Clone)] @@ -564,4 +587,62 @@ mod tests { ) ); } + + #[test] + fn test_sorted_paths() { + let paths = vec!["b", "a", "c"]; + let serialized = SerializedWorkspaceLocation::from_local_paths(paths); + assert_eq!( + serialized.sorted_paths(), + Arc::new(vec![ + PathBuf::from("b"), + PathBuf::from("a"), + PathBuf::from("c"), + ]) + ); + + let paths = Arc::new(vec![ + PathBuf::from("a"), + PathBuf::from("b"), + PathBuf::from("c"), + ]); + let order = vec![2, 0, 1]; + let serialized = + SerializedWorkspaceLocation::Local(LocalPaths(paths.clone()), LocalPathsOrder(order)); + assert_eq!( + serialized.sorted_paths(), + Arc::new(vec![ + PathBuf::from("b"), + PathBuf::from("c"), + PathBuf::from("a"), + ]) + ); + + let paths = Arc::new(vec![ + PathBuf::from("a"), + PathBuf::from("b"), + PathBuf::from("c"), + ]); + let order = vec![]; + let serialized = + SerializedWorkspaceLocation::Local(LocalPaths(paths.clone()), LocalPathsOrder(order)); + assert_eq!(serialized.sorted_paths(), paths); + + let urls = ["/a", "/b", "/c"]; + let serialized = SerializedWorkspaceLocation::Ssh(SerializedSshProject { + id: SshProjectId(0), + host: "host".to_string(), + port: Some(22), + paths: urls.iter().map(|s| s.to_string()).collect(), + user: Some("user".to_string()), + }); + assert_eq!( + serialized.sorted_paths(), + Arc::new( + urls.iter() + .map(|p| PathBuf::from(format!("user@host:22{}", p))) + .collect() + ) + ); + } } diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 1e285276cc..f9104525a0 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -1127,22 +1127,14 @@ impl Workspace { .as_ref() .map(|ws| &ws.location) .and_then(|loc| match loc { - SerializedWorkspaceLocation::Local(paths, order) => { - Some((paths.paths(), order.order())) + SerializedWorkspaceLocation::Local(_, order) => { + Some((loc.sorted_paths(), order.order())) } _ => None, }); if let Some((paths, order)) = workspace_location { - // todo: should probably move this logic to a method on the SerializedWorkspaceLocation - // it's only valid for Local and would be more clear there and be able to be tested - // and reused elsewhere - paths_to_open = order - .iter() - .zip(paths.iter()) - .sorted_by_key(|(i, _)| *i) - .map(|(_, path)| path.clone()) - .collect(); + paths_to_open = paths.iter().cloned().collect(); if order.iter().enumerate().any(|(i, &j)| i != j) { project_handle