Fix panic when immediately closing a window while opening paths
This commit is contained in:
parent
b3c9473bc8
commit
8fafae2cfa
1 changed files with 117 additions and 129 deletions
|
@ -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,140 +3401,124 @@ 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.last_active_center_pane.clone(),
|
||||||
workspace.project().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_group = Some((group, active_pane))
|
center_items = Some(items);
|
||||||
|
center_group = Some((group, active_pane))
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut items_by_project_path = cx.read(|cx| {
|
||||||
|
center_items
|
||||||
|
.unwrap_or_default()
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|item| {
|
||||||
|
let item = item?;
|
||||||
|
let project_path = item.project_path(cx)?;
|
||||||
|
Some((project_path, item))
|
||||||
|
})
|
||||||
|
.collect::<HashMap<_, _>>()
|
||||||
|
});
|
||||||
|
|
||||||
|
let opened_items = paths_to_open
|
||||||
|
.into_iter()
|
||||||
|
.map(|path_to_open| {
|
||||||
|
path_to_open
|
||||||
|
.and_then(|path_to_open| items_by_project_path.remove(&path_to_open))
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// Remove old panes from workspace panes list
|
||||||
|
workspace.update(&mut cx, |workspace, cx| {
|
||||||
|
if let Some((center_group, active_pane)) = center_group {
|
||||||
|
workspace.remove_panes(workspace.center.root.clone(), cx);
|
||||||
|
|
||||||
|
// Swap workspace center group
|
||||||
|
workspace.center = PaneGroup::with_root(center_group);
|
||||||
|
|
||||||
|
// Change the focus to the workspace first so that we retrigger focus in on the pane.
|
||||||
|
cx.focus_self();
|
||||||
|
|
||||||
|
if let Some(active_pane) = active_pane {
|
||||||
|
cx.focus(&active_pane);
|
||||||
|
} else {
|
||||||
|
cx.focus(workspace.panes.last().unwrap());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let old_center_handle = old_center_pane.and_then(|weak| weak.upgrade(cx));
|
||||||
|
if let Some(old_center_handle) = old_center_handle {
|
||||||
|
cx.focus(&old_center_handle)
|
||||||
|
} else {
|
||||||
|
cx.focus_self()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let resulting_list = cx.read(|cx| {
|
let docks = serialized_workspace.docks;
|
||||||
let mut opened_items = center_items
|
workspace.left_dock.update(cx, |dock, cx| {
|
||||||
.unwrap_or_default()
|
dock.set_open(docks.left.visible, cx);
|
||||||
.into_iter()
|
if let Some(active_panel) = docks.left.active_panel {
|
||||||
.filter_map(|item| {
|
if let Some(ix) = dock.panel_index_for_ui_name(&active_panel, cx) {
|
||||||
let item = item?;
|
dock.activate_panel(ix, cx);
|
||||||
let project_path = item.project_path(cx)?;
|
|
||||||
Some((project_path, item))
|
|
||||||
})
|
|
||||||
.collect::<HashMap<_, _>>();
|
|
||||||
|
|
||||||
paths_to_open
|
|
||||||
.into_iter()
|
|
||||||
.map(|path_to_open| {
|
|
||||||
path_to_open.map(|path_to_open| {
|
|
||||||
Ok(opened_items.remove(&path_to_open))
|
|
||||||
})
|
|
||||||
.transpose()
|
|
||||||
.map(|item| item.flatten())
|
|
||||||
.transpose()
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
});
|
|
||||||
|
|
||||||
// Remove old panes from workspace panes list
|
|
||||||
workspace.update(&mut cx, |workspace, cx| {
|
|
||||||
if let Some((center_group, active_pane)) = center_group {
|
|
||||||
workspace.remove_panes(workspace.center.root.clone(), cx);
|
|
||||||
|
|
||||||
// Swap workspace center group
|
|
||||||
workspace.center = PaneGroup::with_root(center_group);
|
|
||||||
|
|
||||||
// Change the focus to the workspace first so that we retrigger focus in on the pane.
|
|
||||||
cx.focus_self();
|
|
||||||
|
|
||||||
if let Some(active_pane) = active_pane {
|
|
||||||
cx.focus(&active_pane);
|
|
||||||
} else {
|
|
||||||
cx.focus(workspace.panes.last().unwrap());
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
let old_center_handle = old_center_pane.and_then(|weak| weak.upgrade(cx));
|
dock.active_panel()
|
||||||
if let Some(old_center_handle) = old_center_handle {
|
.map(|panel| panel.set_zoomed(docks.left.zoom, cx));
|
||||||
cx.focus(&old_center_handle)
|
if docks.left.visible && docks.left.zoom {
|
||||||
} else {
|
cx.focus_self()
|
||||||
cx.focus_self()
|
}
|
||||||
|
});
|
||||||
|
// TODO: I think the bug is that setting zoom or active undoes the bottom zoom or something
|
||||||
|
workspace.right_dock.update(cx, |dock, cx| {
|
||||||
|
dock.set_open(docks.right.visible, cx);
|
||||||
|
if let Some(active_panel) = docks.right.active_panel {
|
||||||
|
if let Some(ix) = dock.panel_index_for_ui_name(&active_panel, cx) {
|
||||||
|
dock.activate_panel(ix, cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dock.active_panel()
|
||||||
|
.map(|panel| panel.set_zoomed(docks.right.zoom, cx));
|
||||||
|
|
||||||
|
if docks.right.visible && docks.right.zoom {
|
||||||
|
cx.focus_self()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
workspace.bottom_dock.update(cx, |dock, cx| {
|
||||||
|
dock.set_open(docks.bottom.visible, cx);
|
||||||
|
if let Some(active_panel) = docks.bottom.active_panel {
|
||||||
|
if let Some(ix) = dock.panel_index_for_ui_name(&active_panel, cx) {
|
||||||
|
dock.activate_panel(ix, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let docks = serialized_workspace.docks;
|
dock.active_panel()
|
||||||
workspace.left_dock.update(cx, |dock, cx| {
|
.map(|panel| panel.set_zoomed(docks.bottom.zoom, cx));
|
||||||
dock.set_open(docks.left.visible, cx);
|
|
||||||
if let Some(active_panel) = docks.left.active_panel {
|
|
||||||
if let Some(ix) = dock.panel_index_for_ui_name(&active_panel, cx) {
|
|
||||||
dock.activate_panel(ix, cx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dock.active_panel()
|
|
||||||
.map(|panel| {
|
|
||||||
panel.set_zoomed(docks.left.zoom, cx)
|
|
||||||
});
|
|
||||||
if docks.left.visible && docks.left.zoom {
|
|
||||||
cx.focus_self()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// TODO: I think the bug is that setting zoom or active undoes the bottom zoom or something
|
|
||||||
workspace.right_dock.update(cx, |dock, cx| {
|
|
||||||
dock.set_open(docks.right.visible, cx);
|
|
||||||
if let Some(active_panel) = docks.right.active_panel {
|
|
||||||
if let Some(ix) = dock.panel_index_for_ui_name(&active_panel, cx) {
|
|
||||||
dock.activate_panel(ix, cx);
|
|
||||||
|
|
||||||
}
|
if docks.bottom.visible && docks.bottom.zoom {
|
||||||
}
|
cx.focus_self()
|
||||||
dock.active_panel()
|
}
|
||||||
.map(|panel| {
|
});
|
||||||
panel.set_zoomed(docks.right.zoom, cx)
|
|
||||||
});
|
|
||||||
|
|
||||||
if docks.right.visible && docks.right.zoom {
|
cx.notify();
|
||||||
cx.focus_self()
|
})?;
|
||||||
}
|
|
||||||
});
|
|
||||||
workspace.bottom_dock.update(cx, |dock, cx| {
|
|
||||||
dock.set_open(docks.bottom.visible, cx);
|
|
||||||
if let Some(active_panel) = docks.bottom.active_panel {
|
|
||||||
if let Some(ix) = dock.panel_index_for_ui_name(&active_panel, cx) {
|
|
||||||
dock.activate_panel(ix, cx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dock.active_panel()
|
// Serialize ourself to make sure our timestamps and any pane / item changes are replicated
|
||||||
.map(|panel| {
|
workspace.read_with(&cx, |workspace, cx| workspace.serialize_workspace(cx))?;
|
||||||
panel.set_zoomed(docks.bottom.zoom, cx)
|
|
||||||
});
|
|
||||||
|
|
||||||
if docks.bottom.visible && docks.bottom.zoom {
|
Ok(opened_items)
|
||||||
cx.focus_self()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
cx.notify();
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Serialize ourself to make sure our timestamps and any pane / item changes are replicated
|
|
||||||
workspace.read_with(&cx, |workspace, cx| workspace.serialize_workspace(cx))?;
|
|
||||||
|
|
||||||
Ok::<_, anyhow::Error>(resulting_list)
|
|
||||||
}};
|
|
||||||
|
|
||||||
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) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue