diff --git a/crates/workspace2/src/item.rs b/crates/workspace2/src/item.rs index 4c09ab06bf..d839f39203 100644 --- a/crates/workspace2/src/item.rs +++ b/crates/workspace2/src/item.rs @@ -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, - _workspace: WeakView, + _workspace: WindowHandle, _workspace_id: WorkspaceId, _item_id: ItemId, _cx: &mut ViewContext, @@ -401,87 +401,86 @@ impl ItemHandle for View { 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 pane = if let Some(pane) = workspace - .panes_by_item - .get(&item.id()) - .and_then(|pane| pane.upgrade()) - { - pane - } else { - log::error!("unexpected item event after pane was dropped"); - return; - }; + 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()) + .and_then(|pane| pane.upgrade()) + { + pane + } else { + log::error!("unexpected item event after pane was dropped"); + return; + }; - if let Some(item) = item.to_followable_item_handle(cx) { - let _is_project_item = item.is_project_item(cx); - let leader_id = workspace.leader_for_pane(&pane); + if let Some(item) = item.to_followable_item_handle(cx) { + let _is_project_item = item.is_project_item(cx); + let leader_id = workspace.leader_for_pane(&pane); - if leader_id.is_some() && item.should_unfollow_on_event(event, cx) { - workspace.unfollow(&pane, cx); - } - - if item.add_event_to_update_proto(event, &mut *pending_update.lock(), cx) - && !pending_update_scheduled.load(Ordering::SeqCst) - { - pending_update_scheduled.store(true, Ordering::SeqCst); - todo!("replace with on_next_frame?"); - // cx.after_window_update({ - // let pending_update = pending_update.clone(); - // let pending_update_scheduled = pending_update_scheduled.clone(); - // move |this, cx| { - // pending_update_scheduled.store(false, Ordering::SeqCst); - // this.update_followers( - // is_project_item, - // proto::update_followers::Variant::UpdateView( - // proto::UpdateView { - // id: item - // .remote_id(&this.app_state.client, cx) - // .map(|id| id.to_proto()), - // variant: pending_update.borrow_mut().take(), - // leader_id, - // }, - // ), - // cx, - // ); - // } - // }); - } + if leader_id.is_some() && item.should_unfollow_on_event(event, cx) { + workspace.unfollow(&pane, cx); } - for item_event in T::to_item_events(event).into_iter() { - match item_event { - ItemEvent::CloseItem => { - pane.update(cx, |pane, cx| { - pane.close_item_by_id(item.id(), crate::SaveIntent::Close, cx) - }) - .detach_and_log_err(cx); - return; - } + if item.add_event_to_update_proto(event, &mut *pending_update.lock(), cx) + && !pending_update_scheduled.load(Ordering::SeqCst) + { + pending_update_scheduled.store(true, Ordering::SeqCst); + todo!("replace with on_next_frame?"); + // cx.after_window_update({ + // let pending_update = pending_update.clone(); + // let pending_update_scheduled = pending_update_scheduled.clone(); + // move |this, cx| { + // pending_update_scheduled.store(false, Ordering::SeqCst); + // this.update_followers( + // is_project_item, + // proto::update_followers::Variant::UpdateView( + // proto::UpdateView { + // id: item + // .remote_id(&this.app_state.client, cx) + // .map(|id| id.to_proto()), + // variant: pending_update.borrow_mut().take(), + // leader_id, + // }, + // ), + // cx, + // ); + // } + // }); + } + } - ItemEvent::UpdateTab => { - pane.update(cx, |_, cx| { - cx.emit(pane::Event::ChangeItemTitle); - cx.notify(); + for item_event in T::to_item_events(event).into_iter() { + match item_event { + ItemEvent::CloseItem => { + pane.update(cx, |pane, cx| { + pane.close_item_by_id(item.id(), crate::SaveIntent::Close, cx) + }) + .detach_and_log_err(cx); + return; + } + + ItemEvent::UpdateTab => { + pane.update(cx, |_, cx| { + cx.emit(pane::Event::ChangeItemTitle); + cx.notify(); + }); + } + + ItemEvent::Edit => { + let autosave = WorkspaceSettings::get_global(cx).autosave; + if let AutosaveSetting::AfterDelay { milliseconds } = autosave { + let delay = Duration::from_millis(milliseconds); + let item = item.clone(); + pending_autosave.fire_new(delay, cx, move |workspace, cx| { + Pane::autosave_item(&item, workspace.project().clone(), cx) }); } - - ItemEvent::Edit => { - let autosave = WorkspaceSettings::get_global(cx).autosave; - if let AutosaveSetting::AfterDelay { milliseconds } = autosave { - let delay = Duration::from_millis(milliseconds); - let item = item.clone(); - pending_autosave.fire_new(delay, cx, move |workspace, cx| { - Pane::autosave_item(&item, workspace.project().clone(), cx) - }); - } - } - - _ => {} } + + _ => {} } - })); + } + })); todo!("observe focus"); // cx.observe_focus(self, move |workspace, item, focused, cx| { @@ -494,12 +493,12 @@ impl ItemHandle for View { // }) // .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| { diff --git a/crates/workspace2/src/persistence/model.rs b/crates/workspace2/src/persistence/model.rs index b1efd35b6b..13b0560a19 100644 --- a/crates/workspace2/src/persistence/model.rs +++ b/crates/workspace2/src/persistence/model.rs @@ -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, - workspace_id: WorkspaceId, - workspace: WindowHandle, - cx: &mut AsyncAppContext, - ) -> Option<(Member, Option>, Vec>>)> { - 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, +// workspace_id: WorkspaceId, +// workspace: WeakView, +// cx: &mut AsyncAppContext, +// ) -> Option<(Member, Option>, Vec>>)> { +// 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, - pane: &WeakView, - workspace_id: WorkspaceId, - workspace: WindowHandle, - cx: &mut AsyncAppContext, - ) -> Result>>> { - 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::().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, + // _pane: &WeakView, + // _workspace_id: WorkspaceId, + // _workspace: WindowHandle, + // _cx: &mut AsyncAppContext, + // ) -> Result>>> { + // 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::().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, item_id: ItemId, active: bool) -> Self { - Self { - kind: Arc::from(kind.as_ref()), - item_id, - active, - } - } -} +// impl SerializedItem { +// pub fn new(kind: impl AsRef, item_id: ItemId, active: bool) -> Self { +// Self { +// kind: Arc::from(kind.as_ref()), +// item_id, +// active, +// } +// } +// } #[cfg(test)] impl Default for SerializedItem { diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index aa57b317d2..f813dd5c03 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -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(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, Option, &mut MainThread) -> WindowOptions, pub initialize_workspace: fn( - WindowHandle, + WeakView, bool, Arc, - AsyncAppContext, + AsyncWindowContext, ) -> Task>, pub node_runtime: Arc, } @@ -568,6 +568,9 @@ pub struct Workspace { pane_history_timestamp: Arc, } +trait AssertSend: Send {} +impl AssertSend for WindowHandle {} + // struct ActiveModal { // view: Box, // previously_focused_view_id: Option, @@ -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(¢er_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, app_state: Arc, - requesting_window: Option>, + _requesting_window: Option>, cx: &mut MainThread, - ) -> Task<( - WeakView, - Vec, anyhow::Error>>>, - )> { + ) -> Task< + anyhow::Result<( + WindowHandle, + Vec, 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 = 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::() .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, ) -> Task>>>> { 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>>> = 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::>() - })?; + // // 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::>(); + // 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::>() + // })?; - // 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::>(); - // 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) -> Option, - mut project_paths_to_open: Vec<(PathBuf, Option)>, +fn open_items( + _serialized_workspace: Option, + project_paths_to_open: Vec<(PathBuf, Option)>, app_state: Arc, - mut cx: &mut MainThread>, -) -> Result>>>> { + cx: &mut MainThread>, +) -> impl Future>>>>> { 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::>(); + // let restored_project_paths = restored_items + // .iter() + // .filter_map(|item| item.as_ref()?.project_path(cx)) + // .collect::>(); - 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 { - for _ in 0..project_paths_to_open.len() { - opened_items.push(None); - } + // 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,16 +3651,17 @@ async fn open_items( }) }); - for maybe_opened_path in futures::future::join_all(tasks.into_iter()) - .await - .into_iter() - { - if let Some((i, path_open_result)) = maybe_opened_path { - opened_items[i] = Some(path_open_result); + let tasks = tasks.collect::>(); + 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); + } } - } - Ok(opened_items) + Ok(opened_items) + } } // fn notify_of_new_dock(workspace: &WeakView, cx: &mut AsyncAppContext) { @@ -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,32 +4367,30 @@ 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, - cx: &mut AppContext, - init: impl FnOnce(&mut Workspace, &mut ViewContext) + 'static, + cx: &mut MainThread, + init: impl FnOnce(&mut Workspace, &mut ViewContext) + '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; - - workspace - .update(&mut cx, |workspace, cx| { - if opened_paths.is_empty() { - init(workspace, cx) - } - }) - .log_err(); + 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() { + init(workspace, cx) + } + }) + .log_err(); + } }) } diff --git a/crates/zed2/src/main.rs b/crates/zed2/src/main.rs index b5b22db140..a3535960cd 100644 --- a/crates/zed2/src/main.rs +++ b/crates/zed2/src/main.rs @@ -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 { } } -async fn restore_or_create_workspace(app_state: &Arc, mut cx: AsyncAppContext) { - 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 { - cx.update(|cx| { - workspace2::open_new(app_state, cx, |workspace, cx| { - Editor::new_file(workspace, &Default::default(), cx) - }) - .detach(); - }); - } +async fn restore_or_create_workspace( + app_state: &Arc, + mut cx: MainThread, +) { + 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("******* 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| { + // todo!(editor) + // Editor::new_file(workspace, &Default::default(), cx) + }) + .detach(); + })?; + } + anyhow::Ok(()) + }) + .await + .log_err(); } fn init_paths() { diff --git a/crates/zed2/src/zed2.rs b/crates/zed2/src/zed2.rs index 7bc90c282c..d49bec8c56 100644 --- a/crates/zed2/src/zed2.rs +++ b/crates/zed2/src/zed2.rs @@ -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(()); })