Fix panic when immediately closing a window while opening paths

This commit is contained in:
Max Brunsfeld 2023-10-05 16:17:49 -07:00
parent b3c9473bc8
commit 8fafae2cfa

View file

@ -79,7 +79,7 @@ use status_bar::StatusBar;
pub use status_bar::StatusItemView; pub use status_bar::StatusItemView;
use theme::{Theme, ThemeSettings}; use theme::{Theme, ThemeSettings};
pub use toolbar::{ToolbarItemLocation, ToolbarItemView}; pub use toolbar::{ToolbarItemLocation, ToolbarItemView};
use util::{async_iife, ResultExt}; use util::ResultExt;
pub use workspace_settings::{AutosaveSetting, GitGutterSetting, WorkspaceSettings}; pub use workspace_settings::{AutosaveSetting, GitGutterSetting, WorkspaceSettings};
lazy_static! { lazy_static! {
@ -936,7 +936,8 @@ impl Workspace {
app_state, app_state,
cx, cx,
) )
.await; .await
.unwrap_or_default();
(workspace, opened_items) (workspace, opened_items)
}) })
@ -3400,30 +3401,29 @@ impl Workspace {
serialized_workspace: SerializedWorkspace, serialized_workspace: SerializedWorkspace,
paths_to_open: Vec<Option<ProjectPath>>, paths_to_open: Vec<Option<ProjectPath>>,
cx: &mut AppContext, cx: &mut AppContext,
) -> Task<Vec<Option<Result<Box<dyn ItemHandle>, anyhow::Error>>>> { ) -> Task<Result<Vec<Option<Box<dyn ItemHandle>>>>> {
cx.spawn(|mut cx| async move { cx.spawn(|mut cx| async move {
let result = async_iife! {{ let (project, old_center_pane) = workspace.read_with(&cx, |workspace, _| {
let (project, old_center_pane) =
workspace.read_with(&cx, |workspace, _| {
( (
workspace.project().clone(), workspace.project().clone(),
workspace.last_active_center_pane.clone(), workspace.last_active_center_pane.clone(),
) )
})?; })?;
let mut center_items = None;
let mut center_group = None; let mut center_group = None;
let mut center_items = None;
// Traverse the splits tree and add to things // Traverse the splits tree and add to things
if let Some((group, active_pane, items)) = serialized_workspace if let Some((group, active_pane, items)) = serialized_workspace
.center_group .center_group
.deserialize(&project, serialized_workspace.id, &workspace, &mut cx) .deserialize(&project, serialized_workspace.id, &workspace, &mut cx)
.await { .await
{
center_items = Some(items); center_items = Some(items);
center_group = Some((group, active_pane)) center_group = Some((group, active_pane))
} }
let resulting_list = cx.read(|cx| { let mut items_by_project_path = cx.read(|cx| {
let mut opened_items = center_items center_items
.unwrap_or_default() .unwrap_or_default()
.into_iter() .into_iter()
.filter_map(|item| { .filter_map(|item| {
@ -3431,20 +3431,16 @@ impl Workspace {
let project_path = item.project_path(cx)?; let project_path = item.project_path(cx)?;
Some((project_path, item)) Some((project_path, item))
}) })
.collect::<HashMap<_, _>>(); .collect::<HashMap<_, _>>()
});
paths_to_open let opened_items = paths_to_open
.into_iter() .into_iter()
.map(|path_to_open| { .map(|path_to_open| {
path_to_open.map(|path_to_open| { path_to_open
Ok(opened_items.remove(&path_to_open)) .and_then(|path_to_open| items_by_project_path.remove(&path_to_open))
}) })
.transpose() .collect::<Vec<_>>();
.map(|item| item.flatten())
.transpose()
})
.collect::<Vec<_>>()
});
// Remove old panes from workspace panes list // Remove old panes from workspace panes list
workspace.update(&mut cx, |workspace, cx| { workspace.update(&mut cx, |workspace, cx| {
@ -3480,9 +3476,7 @@ impl Workspace {
} }
} }
dock.active_panel() dock.active_panel()
.map(|panel| { .map(|panel| panel.set_zoomed(docks.left.zoom, cx));
panel.set_zoomed(docks.left.zoom, cx)
});
if docks.left.visible && docks.left.zoom { if docks.left.visible && docks.left.zoom {
cx.focus_self() cx.focus_self()
} }
@ -3493,13 +3487,10 @@ impl Workspace {
if let Some(active_panel) = docks.right.active_panel { if let Some(active_panel) = docks.right.active_panel {
if let Some(ix) = dock.panel_index_for_ui_name(&active_panel, cx) { if let Some(ix) = dock.panel_index_for_ui_name(&active_panel, cx) {
dock.activate_panel(ix, cx); dock.activate_panel(ix, cx);
} }
} }
dock.active_panel() dock.active_panel()
.map(|panel| { .map(|panel| panel.set_zoomed(docks.right.zoom, cx));
panel.set_zoomed(docks.right.zoom, cx)
});
if docks.right.visible && docks.right.zoom { if docks.right.visible && docks.right.zoom {
cx.focus_self() cx.focus_self()
@ -3514,26 +3505,20 @@ impl Workspace {
} }
dock.active_panel() dock.active_panel()
.map(|panel| { .map(|panel| panel.set_zoomed(docks.bottom.zoom, cx));
panel.set_zoomed(docks.bottom.zoom, cx)
});
if docks.bottom.visible && docks.bottom.zoom { if docks.bottom.visible && docks.bottom.zoom {
cx.focus_self() cx.focus_self()
} }
}); });
cx.notify(); cx.notify();
})?; })?;
// Serialize ourself to make sure our timestamps and any pane / item changes are replicated // Serialize ourself to make sure our timestamps and any pane / item changes are replicated
workspace.read_with(&cx, |workspace, cx| workspace.serialize_workspace(cx))?; workspace.read_with(&cx, |workspace, cx| workspace.serialize_workspace(cx))?;
Ok::<_, anyhow::Error>(resulting_list) Ok(opened_items)
}};
result.await.unwrap_or_default()
}) })
} }
@ -3607,7 +3592,7 @@ async fn open_items(
mut project_paths_to_open: Vec<(PathBuf, Option<ProjectPath>)>, mut project_paths_to_open: Vec<(PathBuf, Option<ProjectPath>)>,
app_state: Arc<AppState>, app_state: Arc<AppState>,
mut cx: AsyncAppContext, mut cx: AsyncAppContext,
) -> Vec<Option<anyhow::Result<Box<dyn ItemHandle>>>> { ) -> Result<Vec<Option<Result<Box<dyn ItemHandle>>>>> {
let mut opened_items = Vec::with_capacity(project_paths_to_open.len()); let mut opened_items = Vec::with_capacity(project_paths_to_open.len());
if let Some(serialized_workspace) = serialized_workspace { if let Some(serialized_workspace) = serialized_workspace {
@ -3625,16 +3610,19 @@ async fn open_items(
cx, cx,
) )
}) })
.await; .await?;
let restored_project_paths = cx.read(|cx| { let restored_project_paths = cx.read(|cx| {
restored_items restored_items
.iter() .iter()
.filter_map(|item| item.as_ref()?.as_ref().ok()?.project_path(cx)) .filter_map(|item| item.as_ref()?.project_path(cx))
.collect::<HashSet<_>>() .collect::<HashSet<_>>()
}); });
opened_items = restored_items; for restored_item in restored_items {
opened_items.push(restored_item.map(Ok));
}
project_paths_to_open project_paths_to_open
.iter_mut() .iter_mut()
.for_each(|(_, project_path)| { .for_each(|(_, project_path)| {
@ -3687,7 +3675,7 @@ async fn open_items(
} }
} }
opened_items Ok(opened_items)
} }
fn notify_of_new_dock(workspace: &WeakViewHandle<Workspace>, cx: &mut AsyncAppContext) { fn notify_of_new_dock(workspace: &WeakViewHandle<Workspace>, cx: &mut AsyncAppContext) {