@@ -80,7 +80,7 @@ macro_rules! query {
let sql_stmt = $crate::sqlez_macros::sql!($($sql)+);
- self.select::<$return_type>(sql_stmt)?(())
+ self.select::<$return_type>(sql_stmt)?()
.context(::std::format!(
"Error in {}, select_row failed to execute or parse for: {}",
::std::stringify!($id),
@@ -95,7 +95,7 @@ macro_rules! query {
self.write(|connection| {
let sql_stmt = $crate::sqlez_macros::sql!($($sql)+);
- connection.select::<$return_type>(sql_stmt)?(())
+ connection.select::<$return_type>(sql_stmt)?()
.context(::std::format!(
"Error in {}, select_row failed to execute or parse for: {}",
::std::stringify!($id),
@@ -11,9 +11,7 @@ use highlighted_workspace_location::HighlightedWorkspaceLocation;
use ordered_float::OrderedFloat;
use picker::{Picker, PickerDelegate};
use settings::Settings;
-use workspace::{OpenPaths, Workspace, WorkspaceLocation};
-
-const RECENT_LIMIT: usize = 100;
+use workspace::{OpenPaths, Workspace, WorkspaceLocation, WORKSPACE_DB};
actions!(recent_projects, [Toggle]);
@@ -30,14 +28,8 @@ struct RecentProjectsView {
}
impl RecentProjectsView {
- fn new(cx: &mut ViewContext<Self>) -> Self {
+ fn new(workspace_locations: Vec<WorkspaceLocation>, cx: &mut ViewContext<Self>) -> Self {
let handle = cx.weak_handle();
- let workspace_locations: Vec<WorkspaceLocation> = workspace::WORKSPACE_DB
- .recent_workspaces(RECENT_LIMIT)
- .unwrap_or_default()
- .into_iter()
- .map(|(_, location)| location)
- .collect();
Self {
picker: cx.add_view(|cx| {
Picker::new("Recent Projects...", handle, cx).with_max_size(800., 1200.)
@@ -48,12 +40,30 @@ impl RecentProjectsView {
}
}
- fn toggle(workspace: &mut Workspace, _: &Toggle, cx: &mut ViewContext<Workspace>) {
- workspace.toggle_modal(cx, |_, cx| {
- let view = cx.add_view(|cx| Self::new(cx));
- cx.subscribe(&view, Self::on_event).detach();
- view
- });
+ fn toggle(_: &mut Workspace, _: &Toggle, cx: &mut ViewContext<Workspace>) {
+ cx.spawn(|workspace, mut cx| async move {
+ let workspace_locations = cx
+ .background()
+ .spawn(async {
+ WORKSPACE_DB
+ .recent_workspaces_on_disk()
+ .await
+ .unwrap_or_default()
+ .into_iter()
+ .map(|(_, location)| location)
+ .collect()
+ })
+ .await;
+
+ workspace.update(&mut cx, |workspace, cx| {
+ workspace.toggle_modal(cx, |_, cx| {
+ let view = cx.add_view(|cx| Self::new(workspace_locations, cx));
+ cx.subscribe(&view, Self::on_event).detach();
+ view
+ });
+ })
+ })
+ .detach();
}
fn on_event(
@@ -196,14 +196,37 @@ impl WorkspaceDb {
}
query! {
- pub fn recent_workspaces(limit: usize) -> Result<Vec<(WorkspaceId, WorkspaceLocation)>> {
+ fn recent_workspaces() -> Result<Vec<(WorkspaceId, WorkspaceLocation)>> {
SELECT workspace_id, workspace_location
FROM workspaces
WHERE workspace_location IS NOT NULL
ORDER BY timestamp DESC
- LIMIT ?
}
}
+
+ query! {
+ async fn delete_stale_workspace(id: WorkspaceId) -> Result<()> {
+ DELETE FROM workspaces
+ WHERE workspace_id IS ?
+ }
+ }
+
+ // Returns the recent locations which are still valid on disk and deletes ones which no longer
+ // exist.
+ pub async fn recent_workspaces_on_disk(&self) -> Result<Vec<(WorkspaceId, WorkspaceLocation)>> {
+ let mut result = Vec::new();
+ let mut delete_tasks = Vec::new();
+ for (id, location) in self.recent_workspaces()? {
+ if location.paths().iter().all(|path| dbg!(path).exists()) {
+ result.push((id, location));
+ } else {
+ delete_tasks.push(self.delete_stale_workspace(id));
+ }
+ }
+
+ futures::future::join_all(delete_tasks).await;
+ Ok(result)
+ }
fn get_center_pane_group(&self, workspace_id: WorkspaceId) -> Result<SerializedPaneGroup> {
self.get_pane_group(workspace_id, None)?