@SomeoneToIgnore This code should 100% work for future Zed users, but for current Zed users, Zed's internal list of recents may not be synced w/ macOS' Recent Documents at first. If needed this can be fixed by calling `cx.refresh_recent_documents` on startup, but that feels a bit unnecessary. Release Notes: - Fixes behavior of Recent Documents list on macOS
This commit is contained in:
parent
35e1229fbb
commit
30193647f3
9 changed files with 17 additions and 89 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -7648,11 +7648,9 @@ dependencies = [
|
||||||
name = "recent_projects"
|
name = "recent_projects"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"collections",
|
|
||||||
"editor",
|
"editor",
|
||||||
"fuzzy",
|
"fuzzy",
|
||||||
"gpui",
|
"gpui",
|
||||||
"itertools 0.11.0",
|
|
||||||
"language",
|
"language",
|
||||||
"menu",
|
"menu",
|
||||||
"ordered-float 2.10.0",
|
"ordered-float 2.10.0",
|
||||||
|
|
|
@ -1129,17 +1129,14 @@ impl AppContext {
|
||||||
self.platform.set_menus(menus, &self.keymap.borrow());
|
self.platform.set_menus(menus, &self.keymap.borrow());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds given path to list of recent paths for the application.
|
/// Adds given path to the bottom of the list of recent paths for the application.
|
||||||
/// The list is usually shown on the application icon's context menu in the dock,
|
/// The list is usually shown on the application icon's context menu in the dock,
|
||||||
/// and allows to open the recent files via that context menu.
|
/// and allows to open the recent files via that context menu.
|
||||||
pub fn add_recent_documents(&mut self, paths: &[PathBuf]) {
|
/// If the path is already in the list, it will be moved to the bottom of the list.
|
||||||
self.platform.add_recent_documents(paths);
|
pub fn add_recent_document(&mut self, path: &Path) {
|
||||||
|
self.platform.add_recent_document(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clears the list of recent paths from the application.
|
|
||||||
pub fn clear_recent_documents(&mut self) {
|
|
||||||
self.platform.clear_recent_documents();
|
|
||||||
}
|
|
||||||
/// Dispatch an action to the currently active window or global action handler
|
/// Dispatch an action to the currently active window or global action handler
|
||||||
/// See [action::Action] for more information on how actions work
|
/// See [action::Action] for more information on how actions work
|
||||||
pub fn dispatch_action(&mut self, action: &dyn Action) {
|
pub fn dispatch_action(&mut self, action: &dyn Action) {
|
||||||
|
|
|
@ -118,8 +118,7 @@ pub(crate) trait Platform: 'static {
|
||||||
fn on_event(&self, callback: Box<dyn FnMut(PlatformInput) -> bool>);
|
fn on_event(&self, callback: Box<dyn FnMut(PlatformInput) -> bool>);
|
||||||
|
|
||||||
fn set_menus(&self, menus: Vec<Menu>, keymap: &Keymap);
|
fn set_menus(&self, menus: Vec<Menu>, keymap: &Keymap);
|
||||||
fn add_recent_documents(&self, _paths: &[PathBuf]) {}
|
fn add_recent_document(&self, _path: &Path) {}
|
||||||
fn clear_recent_documents(&self) {}
|
|
||||||
fn on_app_menu_action(&self, callback: Box<dyn FnMut(&dyn Action)>);
|
fn on_app_menu_action(&self, callback: Box<dyn FnMut(&dyn Action)>);
|
||||||
fn on_will_open_app_menu(&self, callback: Box<dyn FnMut()>);
|
fn on_will_open_app_menu(&self, callback: Box<dyn FnMut()>);
|
||||||
fn on_validate_app_menu_command(&self, callback: Box<dyn FnMut(&dyn Action) -> bool>);
|
fn on_validate_app_menu_command(&self, callback: Box<dyn FnMut(&dyn Action) -> bool>);
|
||||||
|
|
|
@ -764,12 +764,8 @@ impl Platform for MacPlatform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_recent_documents(&self, paths: &[PathBuf]) {
|
fn add_recent_document(&self, path: &Path) {
|
||||||
for path in paths {
|
if let Some(path_str) = path.to_str() {
|
||||||
let Some(path_str) = path.to_str() else {
|
|
||||||
log::error!("Not adding to recent documents a non-unicode path: {path:?}");
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let document_controller: id =
|
let document_controller: id =
|
||||||
msg_send![class!(NSDocumentController), sharedDocumentController];
|
msg_send![class!(NSDocumentController), sharedDocumentController];
|
||||||
|
@ -779,14 +775,6 @@ impl Platform for MacPlatform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear_recent_documents(&self) {
|
|
||||||
unsafe {
|
|
||||||
let document_controller: id =
|
|
||||||
msg_send![class!(NSDocumentController), sharedDocumentController];
|
|
||||||
let _: () = msg_send![document_controller, clearRecentDocuments:nil];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn local_timezone(&self) -> UtcOffset {
|
fn local_timezone(&self) -> UtcOffset {
|
||||||
unsafe {
|
unsafe {
|
||||||
let local_timezone: id = msg_send![class!(NSTimeZone), localTimeZone];
|
let local_timezone: id = msg_send![class!(NSTimeZone), localTimeZone];
|
||||||
|
|
|
@ -9,7 +9,7 @@ use futures::channel::oneshot;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
path::PathBuf,
|
path::{Path, PathBuf},
|
||||||
rc::{Rc, Weak},
|
rc::{Rc, Weak},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
@ -239,9 +239,7 @@ impl Platform for TestPlatform {
|
||||||
|
|
||||||
fn set_menus(&self, _menus: Vec<crate::Menu>, _keymap: &Keymap) {}
|
fn set_menus(&self, _menus: Vec<crate::Menu>, _keymap: &Keymap) {}
|
||||||
|
|
||||||
fn add_recent_documents(&self, _paths: &[PathBuf]) {}
|
fn add_recent_document(&self, _paths: &Path) {}
|
||||||
|
|
||||||
fn clear_recent_documents(&self) {}
|
|
||||||
|
|
||||||
fn on_app_menu_action(&self, _callback: Box<dyn FnMut(&dyn crate::Action)>) {}
|
fn on_app_menu_action(&self, _callback: Box<dyn FnMut(&dyn crate::Action)>) {}
|
||||||
|
|
||||||
|
|
|
@ -6749,6 +6749,12 @@ impl Project {
|
||||||
let worktree = worktree?;
|
let worktree = worktree?;
|
||||||
project
|
project
|
||||||
.update(&mut cx, |project, cx| project.add_worktree(&worktree, cx))?;
|
.update(&mut cx, |project, cx| project.add_worktree(&worktree, cx))?;
|
||||||
|
|
||||||
|
cx.update(|cx| {
|
||||||
|
cx.add_recent_document(&path);
|
||||||
|
})
|
||||||
|
.log_err();
|
||||||
|
|
||||||
Ok(worktree)
|
Ok(worktree)
|
||||||
}
|
}
|
||||||
.map_err(Arc::new)
|
.map_err(Arc::new)
|
||||||
|
|
|
@ -13,10 +13,8 @@ path = "src/recent_projects.rs"
|
||||||
doctest = false
|
doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
collections.workspace = true
|
|
||||||
fuzzy.workspace = true
|
fuzzy.workspace = true
|
||||||
gpui.workspace = true
|
gpui.workspace = true
|
||||||
itertools.workspace = true
|
|
||||||
menu.workspace = true
|
menu.workspace = true
|
||||||
ordered-float.workspace = true
|
ordered-float.workspace = true
|
||||||
picker.workspace = true
|
picker.workspace = true
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
use collections::HashMap;
|
|
||||||
use fuzzy::{StringMatch, StringMatchCandidate};
|
use fuzzy::{StringMatch, StringMatchCandidate};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
AnyElement, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, Result,
|
AnyElement, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, Result,
|
||||||
Subscription, Task, View, ViewContext, WeakView,
|
Subscription, Task, View, ViewContext, WeakView,
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
use picker::{
|
use picker::{
|
||||||
highlighted_match_with_paths::{HighlightedMatchWithPaths, HighlightedText},
|
highlighted_match_with_paths::{HighlightedMatchWithPaths, HighlightedText},
|
||||||
|
@ -431,20 +429,7 @@ impl RecentProjectsDelegate {
|
||||||
.recent_workspaces_on_disk()
|
.recent_workspaces_on_disk()
|
||||||
.await
|
.await
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let mut unique_added_paths = HashMap::default();
|
|
||||||
for (id, workspace) in &workspaces {
|
|
||||||
for path in workspace.paths().iter() {
|
|
||||||
unique_added_paths.insert(path.clone(), id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let updated_paths = unique_added_paths
|
|
||||||
.into_iter()
|
|
||||||
.sorted_by_key(|(_, id)| *id)
|
|
||||||
.map(|(path, _)| path)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
this.update(&mut cx, move |picker, cx| {
|
this.update(&mut cx, move |picker, cx| {
|
||||||
cx.clear_recent_documents();
|
|
||||||
cx.add_recent_documents(&updated_paths);
|
|
||||||
picker.delegate.workspaces = workspaces;
|
picker.delegate.workspaces = workspaces;
|
||||||
picker.delegate.set_selected_index(ix - 1, cx);
|
picker.delegate.set_selected_index(ix - 1, cx);
|
||||||
picker.delegate.reset_selected_match_index = false;
|
picker.delegate.reset_selected_match_index = false;
|
||||||
|
|
|
@ -607,16 +607,7 @@ impl Workspace {
|
||||||
|
|
||||||
project::Event::WorktreeRemoved(_) | project::Event::WorktreeAdded => {
|
project::Event::WorktreeRemoved(_) | project::Event::WorktreeAdded => {
|
||||||
this.update_window_title(cx);
|
this.update_window_title(cx);
|
||||||
let workspace_serialization = this.serialize_workspace(cx);
|
this.serialize_workspace(cx).detach();
|
||||||
cx.spawn(|workspace, mut cx| async move {
|
|
||||||
workspace_serialization.await;
|
|
||||||
workspace
|
|
||||||
.update(&mut cx, |workspace, cx| {
|
|
||||||
workspace.refresh_recent_documents(cx)
|
|
||||||
})?
|
|
||||||
.await
|
|
||||||
})
|
|
||||||
.detach_and_log_err(cx)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
project::Event::DisconnectedFromHost => {
|
project::Event::DisconnectedFromHost => {
|
||||||
|
@ -946,12 +937,7 @@ impl Workspace {
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
window
|
window
|
||||||
.update(&mut cx, |workspace, cx| {
|
.update(&mut cx, |_, cx| cx.activate_window())
|
||||||
workspace
|
|
||||||
.refresh_recent_documents(cx)
|
|
||||||
.detach_and_log_err(cx);
|
|
||||||
cx.activate_window()
|
|
||||||
})
|
|
||||||
.log_err();
|
.log_err();
|
||||||
Ok((window, opened_items))
|
Ok((window, opened_items))
|
||||||
})
|
})
|
||||||
|
@ -3491,33 +3477,6 @@ impl Workspace {
|
||||||
Task::ready(())
|
Task::ready(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn refresh_recent_documents(&self, cx: &mut AppContext) -> Task<Result<()>> {
|
|
||||||
if !self.project.read(cx).is_local() {
|
|
||||||
return Task::ready(Ok(()));
|
|
||||||
}
|
|
||||||
cx.spawn(|cx| async move {
|
|
||||||
let recents = WORKSPACE_DB
|
|
||||||
.recent_workspaces_on_disk()
|
|
||||||
.await
|
|
||||||
.unwrap_or_default();
|
|
||||||
let mut unique_paths = HashMap::default();
|
|
||||||
for (id, workspace) in &recents {
|
|
||||||
for path in workspace.paths().iter() {
|
|
||||||
unique_paths.insert(path.clone(), id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let current_paths = unique_paths
|
|
||||||
.into_iter()
|
|
||||||
.sorted_by_key(|(_, id)| *id)
|
|
||||||
.map(|(path, _)| path)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
cx.update(|cx| {
|
|
||||||
cx.clear_recent_documents();
|
|
||||||
cx.add_recent_documents(¤t_paths);
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn load_workspace(
|
pub(crate) fn load_workspace(
|
||||||
serialized_workspace: SerializedWorkspace,
|
serialized_workspace: SerializedWorkspace,
|
||||||
paths_to_open: Vec<Option<ProjectPath>>,
|
paths_to_open: Vec<Option<ProjectPath>>,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue