This commit is contained in:
Mikayla 2023-11-01 11:45:31 -07:00
parent 337a79e35f
commit 1c1b53ecf6
No known key found for this signature in database
5 changed files with 452 additions and 421 deletions

View file

@ -13,7 +13,7 @@ use client2::{
};
use gpui2::{
AnyElement, AnyView, AppContext, EventEmitter, HighlightStyle, Model, Pixels, Point, Render,
SharedString, Task, View, ViewContext, WeakView, WindowContext,
SharedString, Task, View, ViewContext, WeakView, WindowContext, WindowHandle,
};
use parking_lot::Mutex;
use project2::{Project, ProjectEntryId, ProjectPath};
@ -190,7 +190,7 @@ pub trait Item: Render + EventEmitter + Send {
fn deserialize(
_project: Model<Project>,
_workspace: WeakView<Workspace>,
_workspace: WindowHandle<Workspace>,
_workspace_id: WorkspaceId,
_item_id: ItemId,
_cx: &mut ViewContext<Pane>,
@ -401,8 +401,7 @@ impl<T: Item> ItemHandle for View<T> {
let pending_update = Arc::new(Mutex::new(None));
let pending_update_scheduled = Arc::new(AtomicBool::new(false));
let mut event_subscription =
Some(cx.subscribe(self, move |workspace, item, event, cx| {
let event_subscription = Some(cx.subscribe(self, move |workspace, item, event, cx| {
let pane = if let Some(pane) = workspace
.panes_by_item
.get(&item.id())
@ -494,12 +493,12 @@ impl<T: Item> ItemHandle for View<T> {
// })
// .detach();
let item_id = self.id();
cx.observe_release(self, move |workspace, _, _| {
workspace.panes_by_item.remove(&item_id);
event_subscription.take();
})
.detach();
// let item_id = self.id();
// cx.observe_release(self, move |workspace, _, _| {
// workspace.panes_by_item.remove(&item_id);
// event_subscription.take();
// })
// .detach();
}
cx.defer(|workspace, cx| {

View file

@ -1,21 +1,14 @@
use crate::{
item::ItemHandle, Axis, ItemDeserializers, Member, Pane, PaneAxis, Workspace, WorkspaceId,
};
use crate::{Axis, WorkspaceId};
use anyhow::{Context, Result};
use async_recursion::async_recursion;
use db2::sqlez::{
bindable::{Bind, Column, StaticColumnCount},
statement::Statement,
};
use gpui2::{
AsyncAppContext, AsyncWindowContext, Model, Task, View, WeakView, WindowBounds, WindowHandle,
};
use project2::Project;
use gpui2::WindowBounds;
use std::{
path::{Path, PathBuf},
sync::Arc,
};
use util::ResultExt;
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq)]
@ -149,73 +142,75 @@ impl Default for SerializedPaneGroup {
}
}
impl SerializedPaneGroup {
#[async_recursion(?Send)]
pub(crate) async fn deserialize(
self,
project: &Model<Project>,
workspace_id: WorkspaceId,
workspace: WindowHandle<Workspace>,
cx: &mut AsyncAppContext,
) -> Option<(Member, Option<View<Pane>>, Vec<Option<Box<dyn ItemHandle>>>)> {
match self {
SerializedPaneGroup::Group {
axis,
children,
flexes,
} => {
let mut current_active_pane = None;
let mut members = Vec::new();
let mut items = Vec::new();
for child in children {
if let Some((new_member, active_pane, new_items)) = child
.deserialize(project, workspace_id, workspace, cx)
.await
{
members.push(new_member);
items.extend(new_items);
current_active_pane = current_active_pane.or(active_pane);
}
}
// impl SerializedPaneGroup {
// #[async_recursion(?Send)]
// pub(crate) async fn deserialize(
// self,
// project: &Model<Project>,
// workspace_id: WorkspaceId,
// workspace: WeakView<Workspace>,
// cx: &mut AsyncAppContext,
// ) -> Option<(Member, Option<View<Pane>>, Vec<Option<Box<dyn ItemHandle>>>)> {
// match self {
// SerializedPaneGroup::Group {
// axis,
// children,
// flexes,
// } => {
// let mut current_active_pane = None;
// let mut members = Vec::new();
// let mut items = Vec::new();
// for child in children {
// if let Some((new_member, active_pane, new_items)) = child
// .deserialize(project, workspace_id, workspace, cx)
// .await
// {
// members.push(new_member);
// items.extend(new_items);
// current_active_pane = current_active_pane.or(active_pane);
// }
// }
if members.is_empty() {
return None;
}
// if members.is_empty() {
// return None;
// }
if members.len() == 1 {
return Some((members.remove(0), current_active_pane, items));
}
// if members.len() == 1 {
// return Some((members.remove(0), current_active_pane, items));
// }
Some((
Member::Axis(PaneAxis::load(axis, members, flexes)),
current_active_pane,
items,
))
}
SerializedPaneGroup::Pane(serialized_pane) => {
let pane = workspace
.update(cx, |workspace, cx| workspace.add_pane(cx).downgrade())
.log_err()?;
let active = serialized_pane.active;
let new_items = serialized_pane
.deserialize_to(project, &pane, workspace_id, workspace, cx)
.await
.log_err()?;
// Some((
// Member::Axis(PaneAxis::load(axis, members, flexes)),
// current_active_pane,
// items,
// ))
// }
// SerializedPaneGroup::Pane(serialized_pane) => {
// let pane = workspace
// .update(cx, |workspace, cx| workspace.add_pane(cx).downgrade())
// .log_err()?;
// let active = serialized_pane.active;
// let new_items = serialized_pane
// .deserialize_to(project, &pane, workspace_id, workspace, cx)
// .await
// .log_err()?;
if pane.update(cx, |pane, _| pane.items_len() != 0).log_err()? {
let pane = pane.upgrade()?;
Some((Member::Pane(pane.clone()), active.then(|| pane), new_items))
} else {
let pane = pane.upgrade()?;
workspace
.update(cx, |workspace, cx| workspace.force_remove_pane(&pane, cx))
.log_err()?;
None
}
}
}
}
}
// // todo!();
// // if pane.update(cx, |pane, _| pane.items_len() != 0).log_err()? {
// // let pane = pane.upgrade()?;
// // Some((Member::Pane(pane.clone()), active.then(|| pane), new_items))
// // } else {
// // let pane = pane.upgrade()?;
// // workspace
// // .update(cx, |workspace, cx| workspace.force_remove_pane(&pane, cx))
// // .log_err()?;
// // None
// // }
// None
// }
// }
// }
// }
#[derive(Debug, PartialEq, Eq, Default, Clone)]
pub struct SerializedPane {
@ -228,53 +223,55 @@ impl SerializedPane {
SerializedPane { children, active }
}
pub async fn deserialize_to(
&self,
project: &Model<Project>,
pane: &WeakView<Pane>,
workspace_id: WorkspaceId,
workspace: WindowHandle<Workspace>,
cx: &mut AsyncAppContext,
) -> Result<Vec<Option<Box<dyn ItemHandle>>>> {
let mut items = Vec::new();
let mut active_item_index = None;
for (index, item) in self.children.iter().enumerate() {
let project = project.clone();
let item_handle = pane
.update(cx, |_, cx| {
if let Some(deserializer) = cx.global::<ItemDeserializers>().get(&item.kind) {
deserializer(project, workspace, workspace_id, item.item_id, cx)
} else {
Task::ready(Err(anyhow::anyhow!(
"Deserializer does not exist for item kind: {}",
item.kind
)))
}
})?
.await
.log_err();
// pub async fn deserialize_to(
// &self,
// _project: &Model<Project>,
// _pane: &WeakView<Pane>,
// _workspace_id: WorkspaceId,
// _workspace: WindowHandle<Workspace>,
// _cx: &mut AsyncAppContext,
// ) -> Result<Vec<Option<Box<dyn ItemHandle>>>> {
// anyhow::bail!("todo!()")
// // todo!()
// // let mut items = Vec::new();
// // let mut active_item_index = None;
// // for (index, item) in self.children.iter().enumerate() {
// // let project = project.clone();
// // let item_handle = pane
// // .update(cx, |_, cx| {
// // if let Some(deserializer) = cx.global::<ItemDeserializers>().get(&item.kind) {
// // deserializer(project, workspace, workspace_id, item.item_id, cx)
// // } else {
// // Task::ready(Err(anyhow::anyhow!(
// // "Deserializer does not exist for item kind: {}",
// // item.kind
// // )))
// // }
// // })?
// // .await
// // .log_err();
items.push(item_handle.clone());
// // items.push(item_handle.clone());
if let Some(item_handle) = item_handle {
pane.update(cx, |pane, cx| {
pane.add_item(item_handle.clone(), true, true, None, cx);
})?;
}
// // if let Some(item_handle) = item_handle {
// // pane.update(cx, |pane, cx| {
// // pane.add_item(item_handle.clone(), true, true, None, cx);
// // })?;
// // }
if item.active {
active_item_index = Some(index);
}
}
// // if item.active {
// // active_item_index = Some(index);
// // }
// // }
if let Some(active_item_index) = active_item_index {
pane.update(cx, |pane, cx| {
pane.activate_item(active_item_index, false, false, cx);
})?;
}
// // if let Some(active_item_index) = active_item_index {
// // pane.update(cx, |pane, cx| {
// // pane.activate_item(active_item_index, false, false, cx);
// // })?;
// // }
anyhow::Ok(items)
}
// // anyhow::Ok(items)
// }
}
pub type GroupId = i64;
@ -288,15 +285,15 @@ pub struct SerializedItem {
pub active: bool,
}
impl SerializedItem {
pub fn new(kind: impl AsRef<str>, item_id: ItemId, active: bool) -> Self {
Self {
kind: Arc::from(kind.as_ref()),
item_id,
active,
}
}
}
// impl SerializedItem {
// pub fn new(kind: impl AsRef<str>, item_id: ItemId, active: bool) -> Self {
// Self {
// kind: Arc::from(kind.as_ref()),
// item_id,
// active,
// }
// }
// }
#[cfg(test)]
impl Default for SerializedItem {

View file

@ -25,16 +25,16 @@ use dock::{Dock, DockPosition, PanelButtons};
use futures::{
channel::{mpsc, oneshot},
future::try_join_all,
FutureExt, StreamExt,
Future, FutureExt, StreamExt,
};
use gpui2::{
div, point, size, AnyModel, AnyView, AppContext, AsyncAppContext, AsyncWindowContext, Bounds,
Context, Div, Entity, EventEmitter, GlobalPixels, MainThread, Model, ModelContext, Point,
Render, Size, Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowBounds,
WindowContext, WindowHandle, WindowOptions,
Context, Div, EventEmitter, GlobalPixels, MainThread, Model, ModelContext, Point, Render, Size,
Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowBounds, WindowContext,
WindowHandle, WindowOptions,
};
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ProjectItem};
use language2::LanguageRegistry;
use language2::{LanguageRegistry, LocalFile};
use lazy_static::lazy_static;
use node_runtime::NodeRuntime;
use notifications::{simple_message_notification::MessageNotification, NotificationHandle};
@ -412,7 +412,7 @@ pub fn register_deserializable_item<I: Item>(cx: &mut AppContext) {
Arc::from(serialized_item_kind),
|project, workspace, workspace_id, item_id, cx| {
let task = I::deserialize(project, workspace, workspace_id, item_id, cx);
cx.spawn_on_main(|cx| async { Ok(Box::new(task.await?) as Box<_>) })
cx.spawn_on_main(|_| async { Ok(Box::new(task.await?) as Box<_>) })
},
);
}
@ -428,10 +428,10 @@ pub struct AppState {
pub build_window_options:
fn(Option<WindowBounds>, Option<Uuid>, &mut MainThread<AppContext>) -> WindowOptions,
pub initialize_workspace: fn(
WindowHandle<Workspace>,
WeakView<Workspace>,
bool,
Arc<AppState>,
AsyncAppContext,
AsyncWindowContext,
) -> Task<anyhow::Result<()>>,
pub node_runtime: Arc<dyn NodeRuntime>,
}
@ -568,6 +568,9 @@ pub struct Workspace {
pane_history_timestamp: Arc<AtomicUsize>,
}
trait AssertSend: Send {}
impl AssertSend for WindowHandle<Workspace> {}
// struct ActiveModal {
// view: Box<dyn ModalHandle>,
// previously_focused_view_id: Option<usize>,
@ -700,7 +703,7 @@ impl Workspace {
cx.build_view(|cx| PanelButtons::new(bottom_dock.clone(), weak_handle.clone(), cx));
let right_dock_buttons =
cx.build_view(|cx| PanelButtons::new(right_dock.clone(), weak_handle.clone(), cx));
let status_bar = cx.build_view(|cx| {
let _status_bar = cx.build_view(|cx| {
let mut status_bar = StatusBar::new(&center_pane.clone(), cx);
status_bar.add_left_item(left_dock_buttons, cx);
status_bar.add_right_item(right_dock_buttons, cx);
@ -791,12 +794,14 @@ impl Workspace {
fn new_local(
abs_paths: Vec<PathBuf>,
app_state: Arc<AppState>,
requesting_window: Option<WindowHandle<Workspace>>,
_requesting_window: Option<WindowHandle<Workspace>>,
cx: &mut MainThread<AppContext>,
) -> Task<(
WeakView<Workspace>,
) -> Task<
anyhow::Result<(
WindowHandle<Workspace>,
Vec<Option<Result<Box<dyn ItemHandle>, anyhow::Error>>>,
)> {
)>,
> {
let project_handle = Project::local(
app_state.client.clone(),
app_state.node_runtime.clone(),
@ -807,7 +812,7 @@ impl Workspace {
);
cx.spawn_on_main(|mut cx| async move {
let serialized_workspace = persistence::DB.workspace_for_roots(&abs_paths.as_slice());
let serialized_workspace: Option<SerializedWorkspace> = None; //persistence::DB.workspace_for_roots(&abs_paths.as_slice());
let paths_to_open = Arc::new(abs_paths);
@ -836,14 +841,15 @@ impl Workspace {
DB.next_id().await.unwrap_or(0)
};
let window = if let Some(window) = requesting_window {
// todo!()
let window = /*if let Some(window) = requesting_window {
cx.update_window(window.into(), |old_workspace, cx| {
cx.replace_root_view(|cx| {
Workspace::new(workspace_id, project_handle.clone(), app_state.clone(), cx)
});
});
window
} else {
} else */ {
let window_bounds_override = window_bounds_env_override(&cx);
let (bounds, display) = if let Some(bounds) = window_bounds_override {
(Some(bounds), None)
@ -873,23 +879,34 @@ impl Workspace {
// Use the serialized workspace to construct the new window
let options =
cx.update(|cx| (app_state.build_window_options)(bounds, display, cx))?;
cx.open_window(options, |cx| {
cx.open_window(options, {
let app_state = app_state.clone();
let workspace_id = workspace_id.clone();
let project_handle = project_handle.clone();
move |cx| {
cx.build_view(|cx| {
Workspace::new(workspace_id, project_handle.clone(), app_state.clone(), cx)
Workspace::new(workspace_id, project_handle, app_state, cx)
})
})?
}})?
};
// todo!() Ask how to do this
let weak_view = window.update(&mut cx, |_, cx| cx.view().downgrade())?;
let async_cx = window.update(&mut cx, |_, cx| cx.to_async())?;
(app_state.initialize_workspace)(
window,
weak_view,
serialized_workspace.is_some(),
app_state.clone(),
cx.clone(),
async_cx,
)
.await
.log_err();
window.update(&mut cx, |_, cx| cx.activate_window());
window
.update(&mut cx, |_, cx| cx.activate_window())
.log_err();
notify_if_database_failed(window, &mut cx);
let opened_items = window
@ -897,16 +914,16 @@ impl Workspace {
let workspace = cx.view().downgrade();
open_items(
serialized_workspace,
&workspace,
// &workspace,
project_paths,
app_state,
cx,
)
})
})?
.await
.unwrap_or_default();
(window, opened_items)
Ok((window, opened_items))
})
}
@ -2102,9 +2119,9 @@ impl Workspace {
> {
let project = self.project().clone();
let project_item = project.update(cx, |project, cx| project.open_path(path, cx));
cx.spawn(|_, cx| async move {
cx.spawn(|_, mut cx| async move {
let (project_entry_id, project_item) = project_item.await?;
let build_item = cx.update(|cx| {
let build_item = cx.update(|_, cx| {
cx.default_global::<ProjectItemBuilders>()
.get(&project_item.type_id())
.ok_or_else(|| anyhow!("no item builder for project item"))
@ -2747,7 +2764,7 @@ impl Workspace {
title.push_str("");
}
todo!()
// todo!()
// cx.set_window_title(&title);
}
@ -3372,122 +3389,126 @@ impl Workspace {
cx: &mut ViewContext<Workspace>,
) -> Task<Result<Vec<Option<Box<dyn ItemHandle>>>>> {
cx.spawn(|workspace, mut cx| async move {
let (project, old_center_pane) = workspace.update(&mut cx, |workspace, _| {
(
workspace.project().clone(),
workspace.last_active_center_pane.clone(),
)
})?;
// let (project, old_center_pane) = workspace.update(&mut cx, |workspace, _| {
// (
// workspace.project().clone(),
// workspace.last_active_center_pane.clone(),
// )
// })?;
let mut center_group = None;
let mut center_items = None;
// Traverse the splits tree and add to things
if let Some((group, active_pane, items)) = serialized_workspace
.center_group
.deserialize(&project, serialized_workspace.id, workspace, &mut cx)
.await
{
center_items = Some(items);
center_group = Some((group, active_pane))
}
// // let mut center_group: Option = None;
// // let mut center_items: Option<Vec<Option<Box<dyn ItemHandle>>>> = None;
let mut items_by_project_path = cx.update(|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<_, _>>()
})?;
// // todo!()
// // // Traverse the splits tree and add to things
// if let Some((group, active_pane, items)) = serialized_workspace
// .center_group
// .deserialize(&project, serialized_workspace.id, workspace, &mut cx)
// .await
// {
// center_items = Some(items);
// center_group = Some((group, active_pane))
// }
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<_>>();
// let mut items_by_project_path = cx.update(|_, 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<_, _>>()
// })?;
// 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);
// 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<_>>();
// Swap workspace center group
workspace.center = PaneGroup::with_root(center_group);
// todo!()
// // 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);
// Change the focus to the workspace first so that we retrigger focus in on the pane.
cx.focus_self();
// // Swap workspace center group
// workspace.center = PaneGroup::with_root(center_group);
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());
if let Some(old_center_handle) = old_center_handle {
cx.focus(&old_center_handle)
} else {
cx.focus_self()
}
}
// // Change the focus to the workspace first so that we retrigger focus in on the pane.
// cx.focus_self();
let docks = serialized_workspace.docks;
workspace.left_dock.update(cx, |dock, 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);
}
}
dock.active_panel()
.map(|panel| panel.set_zoomed(docks.right.zoom, cx));
// 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());
// if let Some(old_center_handle) = old_center_handle {
// cx.focus(&old_center_handle)
// } else {
// cx.focus_self()
// }
// }
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;
// workspace.left_dock.update(cx, |dock, 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);
// }
// }
// dock.active_panel()
// .map(|panel| panel.set_zoomed(docks.right.zoom, cx));
dock.active_panel()
.map(|panel| panel.set_zoomed(docks.bottom.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);
// }
// }
if docks.bottom.visible && docks.bottom.zoom {
cx.focus_self()
}
});
// dock.active_panel()
// .map(|panel| panel.set_zoomed(docks.bottom.zoom, cx));
cx.notify();
})?;
// if docks.bottom.visible && docks.bottom.zoom {
// cx.focus_self()
// }
// });
// cx.notify();
// })?;
// Serialize ourself to make sure our timestamps and any pane / item changes are replicated
workspace.update(&mut cx, |workspace, cx| workspace.serialize_workspace(cx))?;
// workspace.update(&mut cx, |workspace, cx| workspace.serialize_workspace(cx))?;
Ok(opened_items)
// Ok(opened_items)
anyhow::bail!("todo")
})
}
@ -3558,49 +3579,50 @@ fn window_bounds_env_override(cx: &MainThread<AsyncAppContext>) -> Option<Window
})
}
async fn open_items(
serialized_workspace: Option<SerializedWorkspace>,
mut project_paths_to_open: Vec<(PathBuf, Option<ProjectPath>)>,
fn open_items(
_serialized_workspace: Option<SerializedWorkspace>,
project_paths_to_open: Vec<(PathBuf, Option<ProjectPath>)>,
app_state: Arc<AppState>,
mut cx: &mut MainThread<ViewContext<'_, Workspace>>,
) -> Result<Vec<Option<Result<Box<dyn ItemHandle>>>>> {
cx: &mut MainThread<ViewContext<'_, Workspace>>,
) -> impl Future<Output = Result<Vec<Option<Result<Box<dyn ItemHandle>>>>>> {
let mut opened_items = Vec::with_capacity(project_paths_to_open.len());
if let Some(serialized_workspace) = serialized_workspace {
let restored_items = Workspace::load_workspace(
serialized_workspace,
project_paths_to_open
.iter()
.map(|(_, project_path)| project_path)
.cloned()
.collect(),
cx,
)
.await?;
// todo!()
// if let Some(serialized_workspace) = serialized_workspace {
// let restored_items = Workspace::load_workspace(
// serialized_workspace,
// project_paths_to_open
// .iter()
// .map(|(_, project_path)| project_path)
// .cloned()
// .collect(),
// cx,
// )
// .await?;
let restored_project_paths = restored_items
.iter()
.filter_map(|item| item.as_ref()?.project_path(cx))
.collect::<HashSet<_>>();
// let restored_project_paths = restored_items
// .iter()
// .filter_map(|item| item.as_ref()?.project_path(cx))
// .collect::<HashSet<_>>();
for restored_item in restored_items {
opened_items.push(restored_item.map(Ok));
}
// for restored_item in restored_items {
// opened_items.push(restored_item.map(Ok));
// }
project_paths_to_open
.iter_mut()
.for_each(|(_, project_path)| {
if let Some(project_path_to_open) = project_path {
if restored_project_paths.contains(project_path_to_open) {
*project_path = None;
}
}
});
} else {
// project_paths_to_open
// .iter_mut()
// .for_each(|(_, project_path)| {
// if let Some(project_path_to_open) = project_path {
// if restored_project_paths.contains(project_path_to_open) {
// *project_path = None;
// }
// }
// });
// } else {
for _ in 0..project_paths_to_open.len() {
opened_items.push(None);
}
}
// }
assert!(opened_items.len() == project_paths_to_open.len());
let tasks =
@ -3629,10 +3651,10 @@ async fn open_items(
})
});
for maybe_opened_path in futures::future::join_all(tasks.into_iter())
.await
.into_iter()
{
let tasks = tasks.collect::<Vec<_>>();
async move {
let tasks = futures::future::join_all(tasks.into_iter());
for maybe_opened_path in tasks.await.into_iter() {
if let Some((i, path_open_result)) = maybe_opened_path {
opened_items[i] = Some(path_open_result);
}
@ -3640,6 +3662,7 @@ async fn open_items(
Ok(opened_items)
}
}
// fn notify_of_new_dock(workspace: &WeakView<Workspace>, cx: &mut AsyncAppContext) {
// const NEW_PANEL_BLOG_POST: &str = "https://zed.dev/blog/new-panel-system";
@ -4102,8 +4125,8 @@ pub async fn activate_workspace_for_project(
continue;
};
let predicate = cx
.update_window_root(&workspace, |workspace, cx| {
let predicate = workspace
.update(cx, |workspace, cx| {
let project = workspace.project.read(cx);
if predicate(project, cx) {
cx.activate_window();
@ -4326,10 +4349,11 @@ pub fn open_paths(
> {
let app_state = app_state.clone();
let abs_paths = abs_paths.to_vec();
cx.spawn(move |mut cx| async move {
cx.spawn_on_main(move |mut cx| async move {
// Open paths in existing workspace if possible
let existing = activate_workspace_for_project(&mut cx, move |project, cx| {
project.contains_paths(&abs_paths, cx)
let existing = activate_workspace_for_project(&mut cx, {
let abs_paths = abs_paths.clone();
move |project, cx| project.contains_paths(&abs_paths, cx)
})
.await;
@ -4343,25 +4367,22 @@ pub fn open_paths(
// ))
todo!()
} else {
// Ok(cx
// .update(|cx| {
// Workspace::new_local(abs_paths, app_state.clone(), requesting_window, cx)
// })
// .await)
todo!()
cx.update(move |cx| {
Workspace::new_local(abs_paths, app_state.clone(), requesting_window, cx)
})?
.await
}
})
}
pub fn open_new(
app_state: &Arc<AppState>,
cx: &mut AppContext,
init: impl FnOnce(&mut Workspace, &mut ViewContext<Workspace>) + 'static,
cx: &mut MainThread<AppContext>,
init: impl FnOnce(&mut Workspace, &mut ViewContext<Workspace>) + 'static + Send,
) -> Task<()> {
let task = Workspace::new_local(Vec::new(), app_state.clone(), None, cx);
cx.spawn(|mut cx| async move {
let (workspace, opened_paths) = task.await;
cx.spawn_on_main(|mut cx| async move {
if let Some((workspace, opened_paths)) = task.await.log_err() {
workspace
.update(&mut cx, |workspace, cx| {
if opened_paths.is_empty() {
@ -4369,6 +4390,7 @@ pub fn open_new(
}
})
.log_err();
}
})
}

View file

@ -12,7 +12,7 @@ use client2::UserStore;
use db2::kvp::KEY_VALUE_STORE;
use fs2::RealFs;
use futures::{channel::mpsc, SinkExt, StreamExt};
use gpui2::{Action, App, AppContext, AsyncAppContext, Context, SemanticVersion, Task};
use gpui2::{Action, App, AppContext, AsyncAppContext, Context, MainThread, SemanticVersion, Task};
use isahc::{prelude::Configurable, Request};
use language2::LanguageRegistry;
use log::LevelFilter;
@ -24,7 +24,7 @@ use settings2::{
default_settings, handle_settings_file_changes, watch_config_file, Settings, SettingsStore,
};
use simplelog::ConfigBuilder;
use smol::process::Command;
use smol::{future::FutureExt, process::Command};
use std::{
env,
ffi::OsStr,
@ -40,6 +40,7 @@ use std::{
time::{SystemTime, UNIX_EPOCH},
};
use util::{
async_maybe,
channel::{parse_zed_link, ReleaseChannel, RELEASE_CHANNEL},
http::{self, HttpClient},
paths, ResultExt,
@ -242,7 +243,7 @@ fn main() {
// .detach_and_log_err(cx)
}
Ok(None) | Err(_) => cx
.spawn({
.spawn_on_main({
let app_state = app_state.clone();
|cx| async move { restore_or_create_workspace(&app_state, cx).await }
})
@ -313,21 +314,33 @@ async fn installation_id() -> Result<String> {
}
}
async fn restore_or_create_workspace(app_state: &Arc<AppState>, mut cx: AsyncAppContext) {
async fn restore_or_create_workspace(
app_state: &Arc<AppState>,
mut cx: MainThread<AsyncAppContext>,
) {
async_maybe!({
if let Some(location) = workspace2::last_opened_workspace_paths().await {
cx.update(|cx| workspace2::open_paths(location.paths().as_ref(), app_state, None, cx))?
.await
.log_err();
} else if matches!(KEY_VALUE_STORE.read_kvp(FIRST_OPEN), Ok(None)) {
cx.update(|cx| show_welcome_experience(app_state, cx));
} else if matches!(KEY_VALUE_STORE.read_kvp("******* THIS IS A BAD KEY PLEASE UNCOMMENT BELOW TO FIX THIS VERY LONG LINE *******"), Ok(None)) {
// todo!(welcome)
//} else if matches!(KEY_VALUE_STORE.read_kvp(FIRST_OPEN), Ok(None)) {
//todo!()
// cx.update(|cx| show_welcome_experience(app_state, cx));
} else {
cx.update(|cx| {
workspace2::open_new(app_state, cx, |workspace, cx| {
Editor::new_file(workspace, &Default::default(), cx)
// todo!(editor)
// Editor::new_file(workspace, &Default::default(), cx)
})
.detach();
});
})?;
}
anyhow::Ok(())
})
.await
.log_err();
}
fn init_paths() {

View file

@ -7,7 +7,7 @@ pub use assets::*;
use collections::HashMap;
use gpui2::{
point, px, AppContext, AsyncAppContext, AsyncWindowContext, MainThread, Point, Task,
TitlebarOptions, WeakView, WindowBounds, WindowKind, WindowOptions,
TitlebarOptions, WeakView, WindowBounds, WindowHandle, WindowKind, WindowOptions,
};
pub use only_instance::*;
pub use open_listener::*;
@ -165,7 +165,7 @@ pub async fn handle_cli_connection(
if paths.is_empty() {
let (done_tx, done_rx) = oneshot::channel();
let _subscription =
cx.update_window_root(&workspace, move |_, cx| {
workspace.update(&mut cx, move |_, cx| {
cx.on_release(|_, _| {
let _ = done_tx.send(());
})