WIP
This commit is contained in:
parent
337a79e35f
commit
1c1b53ecf6
5 changed files with 452 additions and 421 deletions
|
@ -13,7 +13,7 @@ use client2::{
|
||||||
};
|
};
|
||||||
use gpui2::{
|
use gpui2::{
|
||||||
AnyElement, AnyView, AppContext, EventEmitter, HighlightStyle, Model, Pixels, Point, Render,
|
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 parking_lot::Mutex;
|
||||||
use project2::{Project, ProjectEntryId, ProjectPath};
|
use project2::{Project, ProjectEntryId, ProjectPath};
|
||||||
|
@ -190,7 +190,7 @@ pub trait Item: Render + EventEmitter + Send {
|
||||||
|
|
||||||
fn deserialize(
|
fn deserialize(
|
||||||
_project: Model<Project>,
|
_project: Model<Project>,
|
||||||
_workspace: WeakView<Workspace>,
|
_workspace: WindowHandle<Workspace>,
|
||||||
_workspace_id: WorkspaceId,
|
_workspace_id: WorkspaceId,
|
||||||
_item_id: ItemId,
|
_item_id: ItemId,
|
||||||
_cx: &mut ViewContext<Pane>,
|
_cx: &mut ViewContext<Pane>,
|
||||||
|
@ -401,87 +401,86 @@ impl<T: Item> ItemHandle for View<T> {
|
||||||
let pending_update = Arc::new(Mutex::new(None));
|
let pending_update = Arc::new(Mutex::new(None));
|
||||||
let pending_update_scheduled = Arc::new(AtomicBool::new(false));
|
let pending_update_scheduled = Arc::new(AtomicBool::new(false));
|
||||||
|
|
||||||
let mut event_subscription =
|
let event_subscription = Some(cx.subscribe(self, move |workspace, item, event, cx| {
|
||||||
Some(cx.subscribe(self, move |workspace, item, event, cx| {
|
let pane = if let Some(pane) = workspace
|
||||||
let pane = if let Some(pane) = workspace
|
.panes_by_item
|
||||||
.panes_by_item
|
.get(&item.id())
|
||||||
.get(&item.id())
|
.and_then(|pane| pane.upgrade())
|
||||||
.and_then(|pane| pane.upgrade())
|
{
|
||||||
{
|
pane
|
||||||
pane
|
} else {
|
||||||
} else {
|
log::error!("unexpected item event after pane was dropped");
|
||||||
log::error!("unexpected item event after pane was dropped");
|
return;
|
||||||
return;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(item) = item.to_followable_item_handle(cx) {
|
if let Some(item) = item.to_followable_item_handle(cx) {
|
||||||
let _is_project_item = item.is_project_item(cx);
|
let _is_project_item = item.is_project_item(cx);
|
||||||
let leader_id = workspace.leader_for_pane(&pane);
|
let leader_id = workspace.leader_for_pane(&pane);
|
||||||
|
|
||||||
if leader_id.is_some() && item.should_unfollow_on_event(event, cx) {
|
if leader_id.is_some() && item.should_unfollow_on_event(event, cx) {
|
||||||
workspace.unfollow(&pane, 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,
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for item_event in T::to_item_events(event).into_iter() {
|
if item.add_event_to_update_proto(event, &mut *pending_update.lock(), cx)
|
||||||
match item_event {
|
&& !pending_update_scheduled.load(Ordering::SeqCst)
|
||||||
ItemEvent::CloseItem => {
|
{
|
||||||
pane.update(cx, |pane, cx| {
|
pending_update_scheduled.store(true, Ordering::SeqCst);
|
||||||
pane.close_item_by_id(item.id(), crate::SaveIntent::Close, cx)
|
todo!("replace with on_next_frame?");
|
||||||
})
|
// cx.after_window_update({
|
||||||
.detach_and_log_err(cx);
|
// let pending_update = pending_update.clone();
|
||||||
return;
|
// 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 => {
|
for item_event in T::to_item_events(event).into_iter() {
|
||||||
pane.update(cx, |_, cx| {
|
match item_event {
|
||||||
cx.emit(pane::Event::ChangeItemTitle);
|
ItemEvent::CloseItem => {
|
||||||
cx.notify();
|
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");
|
todo!("observe focus");
|
||||||
// cx.observe_focus(self, move |workspace, item, focused, cx| {
|
// cx.observe_focus(self, move |workspace, item, focused, cx| {
|
||||||
|
@ -494,12 +493,12 @@ impl<T: Item> ItemHandle for View<T> {
|
||||||
// })
|
// })
|
||||||
// .detach();
|
// .detach();
|
||||||
|
|
||||||
let item_id = self.id();
|
// let item_id = self.id();
|
||||||
cx.observe_release(self, move |workspace, _, _| {
|
// cx.observe_release(self, move |workspace, _, _| {
|
||||||
workspace.panes_by_item.remove(&item_id);
|
// workspace.panes_by_item.remove(&item_id);
|
||||||
event_subscription.take();
|
// event_subscription.take();
|
||||||
})
|
// })
|
||||||
.detach();
|
// .detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.defer(|workspace, cx| {
|
cx.defer(|workspace, cx| {
|
||||||
|
|
|
@ -1,21 +1,14 @@
|
||||||
use crate::{
|
use crate::{Axis, WorkspaceId};
|
||||||
item::ItemHandle, Axis, ItemDeserializers, Member, Pane, PaneAxis, Workspace, WorkspaceId,
|
|
||||||
};
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use async_recursion::async_recursion;
|
|
||||||
use db2::sqlez::{
|
use db2::sqlez::{
|
||||||
bindable::{Bind, Column, StaticColumnCount},
|
bindable::{Bind, Column, StaticColumnCount},
|
||||||
statement::Statement,
|
statement::Statement,
|
||||||
};
|
};
|
||||||
use gpui2::{
|
use gpui2::WindowBounds;
|
||||||
AsyncAppContext, AsyncWindowContext, Model, Task, View, WeakView, WindowBounds, WindowHandle,
|
|
||||||
};
|
|
||||||
use project2::Project;
|
|
||||||
use std::{
|
use std::{
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use util::ResultExt;
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
@ -149,73 +142,75 @@ impl Default for SerializedPaneGroup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SerializedPaneGroup {
|
// impl SerializedPaneGroup {
|
||||||
#[async_recursion(?Send)]
|
// #[async_recursion(?Send)]
|
||||||
pub(crate) async fn deserialize(
|
// pub(crate) async fn deserialize(
|
||||||
self,
|
// self,
|
||||||
project: &Model<Project>,
|
// project: &Model<Project>,
|
||||||
workspace_id: WorkspaceId,
|
// workspace_id: WorkspaceId,
|
||||||
workspace: WindowHandle<Workspace>,
|
// workspace: WeakView<Workspace>,
|
||||||
cx: &mut AsyncAppContext,
|
// cx: &mut AsyncAppContext,
|
||||||
) -> Option<(Member, Option<View<Pane>>, Vec<Option<Box<dyn ItemHandle>>>)> {
|
// ) -> Option<(Member, Option<View<Pane>>, Vec<Option<Box<dyn ItemHandle>>>)> {
|
||||||
match self {
|
// match self {
|
||||||
SerializedPaneGroup::Group {
|
// SerializedPaneGroup::Group {
|
||||||
axis,
|
// axis,
|
||||||
children,
|
// children,
|
||||||
flexes,
|
// flexes,
|
||||||
} => {
|
// } => {
|
||||||
let mut current_active_pane = None;
|
// let mut current_active_pane = None;
|
||||||
let mut members = Vec::new();
|
// let mut members = Vec::new();
|
||||||
let mut items = Vec::new();
|
// let mut items = Vec::new();
|
||||||
for child in children {
|
// for child in children {
|
||||||
if let Some((new_member, active_pane, new_items)) = child
|
// if let Some((new_member, active_pane, new_items)) = child
|
||||||
.deserialize(project, workspace_id, workspace, cx)
|
// .deserialize(project, workspace_id, workspace, cx)
|
||||||
.await
|
// .await
|
||||||
{
|
// {
|
||||||
members.push(new_member);
|
// members.push(new_member);
|
||||||
items.extend(new_items);
|
// items.extend(new_items);
|
||||||
current_active_pane = current_active_pane.or(active_pane);
|
// current_active_pane = current_active_pane.or(active_pane);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
if members.is_empty() {
|
// if members.is_empty() {
|
||||||
return None;
|
// return None;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if members.len() == 1 {
|
// if members.len() == 1 {
|
||||||
return Some((members.remove(0), current_active_pane, items));
|
// return Some((members.remove(0), current_active_pane, items));
|
||||||
}
|
// }
|
||||||
|
|
||||||
Some((
|
// Some((
|
||||||
Member::Axis(PaneAxis::load(axis, members, flexes)),
|
// Member::Axis(PaneAxis::load(axis, members, flexes)),
|
||||||
current_active_pane,
|
// current_active_pane,
|
||||||
items,
|
// items,
|
||||||
))
|
// ))
|
||||||
}
|
// }
|
||||||
SerializedPaneGroup::Pane(serialized_pane) => {
|
// SerializedPaneGroup::Pane(serialized_pane) => {
|
||||||
let pane = workspace
|
// let pane = workspace
|
||||||
.update(cx, |workspace, cx| workspace.add_pane(cx).downgrade())
|
// .update(cx, |workspace, cx| workspace.add_pane(cx).downgrade())
|
||||||
.log_err()?;
|
// .log_err()?;
|
||||||
let active = serialized_pane.active;
|
// let active = serialized_pane.active;
|
||||||
let new_items = serialized_pane
|
// let new_items = serialized_pane
|
||||||
.deserialize_to(project, &pane, workspace_id, workspace, cx)
|
// .deserialize_to(project, &pane, workspace_id, workspace, cx)
|
||||||
.await
|
// .await
|
||||||
.log_err()?;
|
// .log_err()?;
|
||||||
|
|
||||||
if pane.update(cx, |pane, _| pane.items_len() != 0).log_err()? {
|
// // todo!();
|
||||||
let pane = pane.upgrade()?;
|
// // if pane.update(cx, |pane, _| pane.items_len() != 0).log_err()? {
|
||||||
Some((Member::Pane(pane.clone()), active.then(|| pane), new_items))
|
// // let pane = pane.upgrade()?;
|
||||||
} else {
|
// // Some((Member::Pane(pane.clone()), active.then(|| pane), new_items))
|
||||||
let pane = pane.upgrade()?;
|
// // } else {
|
||||||
workspace
|
// // let pane = pane.upgrade()?;
|
||||||
.update(cx, |workspace, cx| workspace.force_remove_pane(&pane, cx))
|
// // workspace
|
||||||
.log_err()?;
|
// // .update(cx, |workspace, cx| workspace.force_remove_pane(&pane, cx))
|
||||||
None
|
// // .log_err()?;
|
||||||
}
|
// // None
|
||||||
}
|
// // }
|
||||||
}
|
// None
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Default, Clone)]
|
#[derive(Debug, PartialEq, Eq, Default, Clone)]
|
||||||
pub struct SerializedPane {
|
pub struct SerializedPane {
|
||||||
|
@ -228,53 +223,55 @@ impl SerializedPane {
|
||||||
SerializedPane { children, active }
|
SerializedPane { children, active }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn deserialize_to(
|
// pub async fn deserialize_to(
|
||||||
&self,
|
// &self,
|
||||||
project: &Model<Project>,
|
// _project: &Model<Project>,
|
||||||
pane: &WeakView<Pane>,
|
// _pane: &WeakView<Pane>,
|
||||||
workspace_id: WorkspaceId,
|
// _workspace_id: WorkspaceId,
|
||||||
workspace: WindowHandle<Workspace>,
|
// _workspace: WindowHandle<Workspace>,
|
||||||
cx: &mut AsyncAppContext,
|
// _cx: &mut AsyncAppContext,
|
||||||
) -> Result<Vec<Option<Box<dyn ItemHandle>>>> {
|
// ) -> Result<Vec<Option<Box<dyn ItemHandle>>>> {
|
||||||
let mut items = Vec::new();
|
// anyhow::bail!("todo!()")
|
||||||
let mut active_item_index = None;
|
// // todo!()
|
||||||
for (index, item) in self.children.iter().enumerate() {
|
// // let mut items = Vec::new();
|
||||||
let project = project.clone();
|
// // let mut active_item_index = None;
|
||||||
let item_handle = pane
|
// // for (index, item) in self.children.iter().enumerate() {
|
||||||
.update(cx, |_, cx| {
|
// // let project = project.clone();
|
||||||
if let Some(deserializer) = cx.global::<ItemDeserializers>().get(&item.kind) {
|
// // let item_handle = pane
|
||||||
deserializer(project, workspace, workspace_id, item.item_id, cx)
|
// // .update(cx, |_, cx| {
|
||||||
} else {
|
// // if let Some(deserializer) = cx.global::<ItemDeserializers>().get(&item.kind) {
|
||||||
Task::ready(Err(anyhow::anyhow!(
|
// // deserializer(project, workspace, workspace_id, item.item_id, cx)
|
||||||
"Deserializer does not exist for item kind: {}",
|
// // } else {
|
||||||
item.kind
|
// // Task::ready(Err(anyhow::anyhow!(
|
||||||
)))
|
// // "Deserializer does not exist for item kind: {}",
|
||||||
}
|
// // item.kind
|
||||||
})?
|
// // )))
|
||||||
.await
|
// // }
|
||||||
.log_err();
|
// // })?
|
||||||
|
// // .await
|
||||||
|
// // .log_err();
|
||||||
|
|
||||||
items.push(item_handle.clone());
|
// // items.push(item_handle.clone());
|
||||||
|
|
||||||
if let Some(item_handle) = item_handle {
|
// // if let Some(item_handle) = item_handle {
|
||||||
pane.update(cx, |pane, cx| {
|
// // pane.update(cx, |pane, cx| {
|
||||||
pane.add_item(item_handle.clone(), true, true, None, cx);
|
// // pane.add_item(item_handle.clone(), true, true, None, cx);
|
||||||
})?;
|
// // })?;
|
||||||
}
|
// // }
|
||||||
|
|
||||||
if item.active {
|
// // if item.active {
|
||||||
active_item_index = Some(index);
|
// // active_item_index = Some(index);
|
||||||
}
|
// // }
|
||||||
}
|
// // }
|
||||||
|
|
||||||
if let Some(active_item_index) = active_item_index {
|
// // if let Some(active_item_index) = active_item_index {
|
||||||
pane.update(cx, |pane, cx| {
|
// // pane.update(cx, |pane, cx| {
|
||||||
pane.activate_item(active_item_index, false, false, cx);
|
// // pane.activate_item(active_item_index, false, false, cx);
|
||||||
})?;
|
// // })?;
|
||||||
}
|
// // }
|
||||||
|
|
||||||
anyhow::Ok(items)
|
// // anyhow::Ok(items)
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type GroupId = i64;
|
pub type GroupId = i64;
|
||||||
|
@ -288,15 +285,15 @@ pub struct SerializedItem {
|
||||||
pub active: bool,
|
pub active: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SerializedItem {
|
// impl SerializedItem {
|
||||||
pub fn new(kind: impl AsRef<str>, item_id: ItemId, active: bool) -> Self {
|
// pub fn new(kind: impl AsRef<str>, item_id: ItemId, active: bool) -> Self {
|
||||||
Self {
|
// Self {
|
||||||
kind: Arc::from(kind.as_ref()),
|
// kind: Arc::from(kind.as_ref()),
|
||||||
item_id,
|
// item_id,
|
||||||
active,
|
// active,
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
impl Default for SerializedItem {
|
impl Default for SerializedItem {
|
||||||
|
|
|
@ -25,16 +25,16 @@ use dock::{Dock, DockPosition, PanelButtons};
|
||||||
use futures::{
|
use futures::{
|
||||||
channel::{mpsc, oneshot},
|
channel::{mpsc, oneshot},
|
||||||
future::try_join_all,
|
future::try_join_all,
|
||||||
FutureExt, StreamExt,
|
Future, FutureExt, StreamExt,
|
||||||
};
|
};
|
||||||
use gpui2::{
|
use gpui2::{
|
||||||
div, point, size, AnyModel, AnyView, AppContext, AsyncAppContext, AsyncWindowContext, Bounds,
|
div, point, size, AnyModel, AnyView, AppContext, AsyncAppContext, AsyncWindowContext, Bounds,
|
||||||
Context, Div, Entity, EventEmitter, GlobalPixels, MainThread, Model, ModelContext, Point,
|
Context, Div, EventEmitter, GlobalPixels, MainThread, Model, ModelContext, Point, Render, Size,
|
||||||
Render, Size, Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowBounds,
|
Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowBounds, WindowContext,
|
||||||
WindowContext, WindowHandle, WindowOptions,
|
WindowHandle, WindowOptions,
|
||||||
};
|
};
|
||||||
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ProjectItem};
|
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ProjectItem};
|
||||||
use language2::LanguageRegistry;
|
use language2::{LanguageRegistry, LocalFile};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use node_runtime::NodeRuntime;
|
use node_runtime::NodeRuntime;
|
||||||
use notifications::{simple_message_notification::MessageNotification, NotificationHandle};
|
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),
|
Arc::from(serialized_item_kind),
|
||||||
|project, workspace, workspace_id, item_id, cx| {
|
|project, workspace, workspace_id, item_id, cx| {
|
||||||
let task = I::deserialize(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:
|
pub build_window_options:
|
||||||
fn(Option<WindowBounds>, Option<Uuid>, &mut MainThread<AppContext>) -> WindowOptions,
|
fn(Option<WindowBounds>, Option<Uuid>, &mut MainThread<AppContext>) -> WindowOptions,
|
||||||
pub initialize_workspace: fn(
|
pub initialize_workspace: fn(
|
||||||
WindowHandle<Workspace>,
|
WeakView<Workspace>,
|
||||||
bool,
|
bool,
|
||||||
Arc<AppState>,
|
Arc<AppState>,
|
||||||
AsyncAppContext,
|
AsyncWindowContext,
|
||||||
) -> Task<anyhow::Result<()>>,
|
) -> Task<anyhow::Result<()>>,
|
||||||
pub node_runtime: Arc<dyn NodeRuntime>,
|
pub node_runtime: Arc<dyn NodeRuntime>,
|
||||||
}
|
}
|
||||||
|
@ -568,6 +568,9 @@ pub struct Workspace {
|
||||||
pane_history_timestamp: Arc<AtomicUsize>,
|
pane_history_timestamp: Arc<AtomicUsize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait AssertSend: Send {}
|
||||||
|
impl AssertSend for WindowHandle<Workspace> {}
|
||||||
|
|
||||||
// struct ActiveModal {
|
// struct ActiveModal {
|
||||||
// view: Box<dyn ModalHandle>,
|
// view: Box<dyn ModalHandle>,
|
||||||
// previously_focused_view_id: Option<usize>,
|
// 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));
|
cx.build_view(|cx| PanelButtons::new(bottom_dock.clone(), weak_handle.clone(), cx));
|
||||||
let right_dock_buttons =
|
let right_dock_buttons =
|
||||||
cx.build_view(|cx| PanelButtons::new(right_dock.clone(), weak_handle.clone(), cx));
|
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);
|
let mut status_bar = StatusBar::new(¢er_pane.clone(), cx);
|
||||||
status_bar.add_left_item(left_dock_buttons, cx);
|
status_bar.add_left_item(left_dock_buttons, cx);
|
||||||
status_bar.add_right_item(right_dock_buttons, cx);
|
status_bar.add_right_item(right_dock_buttons, cx);
|
||||||
|
@ -791,12 +794,14 @@ impl Workspace {
|
||||||
fn new_local(
|
fn new_local(
|
||||||
abs_paths: Vec<PathBuf>,
|
abs_paths: Vec<PathBuf>,
|
||||||
app_state: Arc<AppState>,
|
app_state: Arc<AppState>,
|
||||||
requesting_window: Option<WindowHandle<Workspace>>,
|
_requesting_window: Option<WindowHandle<Workspace>>,
|
||||||
cx: &mut MainThread<AppContext>,
|
cx: &mut MainThread<AppContext>,
|
||||||
) -> Task<(
|
) -> Task<
|
||||||
WeakView<Workspace>,
|
anyhow::Result<(
|
||||||
Vec<Option<Result<Box<dyn ItemHandle>, anyhow::Error>>>,
|
WindowHandle<Workspace>,
|
||||||
)> {
|
Vec<Option<Result<Box<dyn ItemHandle>, anyhow::Error>>>,
|
||||||
|
)>,
|
||||||
|
> {
|
||||||
let project_handle = Project::local(
|
let project_handle = Project::local(
|
||||||
app_state.client.clone(),
|
app_state.client.clone(),
|
||||||
app_state.node_runtime.clone(),
|
app_state.node_runtime.clone(),
|
||||||
|
@ -807,7 +812,7 @@ impl Workspace {
|
||||||
);
|
);
|
||||||
|
|
||||||
cx.spawn_on_main(|mut cx| async move {
|
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);
|
let paths_to_open = Arc::new(abs_paths);
|
||||||
|
|
||||||
|
@ -836,14 +841,15 @@ impl Workspace {
|
||||||
DB.next_id().await.unwrap_or(0)
|
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.update_window(window.into(), |old_workspace, cx| {
|
||||||
cx.replace_root_view(|cx| {
|
cx.replace_root_view(|cx| {
|
||||||
Workspace::new(workspace_id, project_handle.clone(), app_state.clone(), cx)
|
Workspace::new(workspace_id, project_handle.clone(), app_state.clone(), cx)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
window
|
window
|
||||||
} else {
|
} else */ {
|
||||||
let window_bounds_override = window_bounds_env_override(&cx);
|
let window_bounds_override = window_bounds_env_override(&cx);
|
||||||
let (bounds, display) = if let Some(bounds) = window_bounds_override {
|
let (bounds, display) = if let Some(bounds) = window_bounds_override {
|
||||||
(Some(bounds), None)
|
(Some(bounds), None)
|
||||||
|
@ -873,23 +879,34 @@ impl Workspace {
|
||||||
// Use the serialized workspace to construct the new window
|
// Use the serialized workspace to construct the new window
|
||||||
let options =
|
let options =
|
||||||
cx.update(|cx| (app_state.build_window_options)(bounds, display, cx))?;
|
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| {
|
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)(
|
(app_state.initialize_workspace)(
|
||||||
window,
|
weak_view,
|
||||||
serialized_workspace.is_some(),
|
serialized_workspace.is_some(),
|
||||||
app_state.clone(),
|
app_state.clone(),
|
||||||
cx.clone(),
|
async_cx,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.log_err();
|
.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);
|
notify_if_database_failed(window, &mut cx);
|
||||||
let opened_items = window
|
let opened_items = window
|
||||||
|
@ -897,16 +914,16 @@ impl Workspace {
|
||||||
let workspace = cx.view().downgrade();
|
let workspace = cx.view().downgrade();
|
||||||
open_items(
|
open_items(
|
||||||
serialized_workspace,
|
serialized_workspace,
|
||||||
&workspace,
|
// &workspace,
|
||||||
project_paths,
|
project_paths,
|
||||||
app_state,
|
app_state,
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
})
|
})?
|
||||||
.await
|
.await
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
(window, opened_items)
|
Ok((window, opened_items))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2102,9 +2119,9 @@ impl Workspace {
|
||||||
> {
|
> {
|
||||||
let project = self.project().clone();
|
let project = self.project().clone();
|
||||||
let project_item = project.update(cx, |project, cx| project.open_path(path, cx));
|
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 (project_entry_id, project_item) = project_item.await?;
|
||||||
let build_item = cx.update(|cx| {
|
let build_item = cx.update(|_, cx| {
|
||||||
cx.default_global::<ProjectItemBuilders>()
|
cx.default_global::<ProjectItemBuilders>()
|
||||||
.get(&project_item.type_id())
|
.get(&project_item.type_id())
|
||||||
.ok_or_else(|| anyhow!("no item builder for project item"))
|
.ok_or_else(|| anyhow!("no item builder for project item"))
|
||||||
|
@ -2747,7 +2764,7 @@ impl Workspace {
|
||||||
title.push_str(" ↗");
|
title.push_str(" ↗");
|
||||||
}
|
}
|
||||||
|
|
||||||
todo!()
|
// todo!()
|
||||||
// cx.set_window_title(&title);
|
// cx.set_window_title(&title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3372,122 +3389,126 @@ impl Workspace {
|
||||||
cx: &mut ViewContext<Workspace>,
|
cx: &mut ViewContext<Workspace>,
|
||||||
) -> Task<Result<Vec<Option<Box<dyn ItemHandle>>>>> {
|
) -> Task<Result<Vec<Option<Box<dyn ItemHandle>>>>> {
|
||||||
cx.spawn(|workspace, mut cx| async move {
|
cx.spawn(|workspace, mut cx| async move {
|
||||||
let (project, old_center_pane) = workspace.update(&mut cx, |workspace, _| {
|
// let (project, old_center_pane) = workspace.update(&mut cx, |workspace, _| {
|
||||||
(
|
// (
|
||||||
workspace.project().clone(),
|
// workspace.project().clone(),
|
||||||
workspace.last_active_center_pane.clone(),
|
// workspace.last_active_center_pane.clone(),
|
||||||
)
|
// )
|
||||||
})?;
|
// })?;
|
||||||
|
|
||||||
let mut center_group = None;
|
// // let mut center_group: Option = None;
|
||||||
let mut center_items = None;
|
// // let mut center_items: Option<Vec<Option<Box<dyn ItemHandle>>>> = 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 items_by_project_path = cx.update(|cx| {
|
// // todo!()
|
||||||
center_items
|
// // // Traverse the splits tree and add to things
|
||||||
.unwrap_or_default()
|
// if let Some((group, active_pane, items)) = serialized_workspace
|
||||||
.into_iter()
|
// .center_group
|
||||||
.filter_map(|item| {
|
// .deserialize(&project, serialized_workspace.id, workspace, &mut cx)
|
||||||
let item = item?;
|
// .await
|
||||||
let project_path = item.project_path(cx)?;
|
// {
|
||||||
Some((project_path, item))
|
// center_items = Some(items);
|
||||||
})
|
// center_group = Some((group, active_pane))
|
||||||
.collect::<HashMap<_, _>>()
|
// }
|
||||||
})?;
|
|
||||||
|
|
||||||
let opened_items = paths_to_open
|
// let mut items_by_project_path = cx.update(|_, cx| {
|
||||||
.into_iter()
|
// center_items
|
||||||
.map(|path_to_open| {
|
// .unwrap_or_default()
|
||||||
path_to_open
|
// .into_iter()
|
||||||
.and_then(|path_to_open| items_by_project_path.remove(&path_to_open))
|
// .filter_map(|item| {
|
||||||
})
|
// let item = item?;
|
||||||
.collect::<Vec<_>>();
|
// let project_path = item.project_path(cx)?;
|
||||||
|
// Some((project_path, item))
|
||||||
|
// })
|
||||||
|
// .collect::<HashMap<_, _>>()
|
||||||
|
// })?;
|
||||||
|
|
||||||
// Remove old panes from workspace panes list
|
// let opened_items = paths_to_open
|
||||||
workspace.update(&mut cx, |workspace, cx| {
|
// .into_iter()
|
||||||
if let Some((center_group, active_pane)) = center_group {
|
// .map(|path_to_open| {
|
||||||
workspace.remove_panes(workspace.center.root.clone(), cx);
|
// path_to_open
|
||||||
|
// .and_then(|path_to_open| items_by_project_path.remove(&path_to_open))
|
||||||
|
// })
|
||||||
|
// .collect::<Vec<_>>();
|
||||||
|
|
||||||
// Swap workspace center group
|
// todo!()
|
||||||
workspace.center = PaneGroup::with_root(center_group);
|
// // 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.
|
// // Swap workspace center group
|
||||||
cx.focus_self();
|
// workspace.center = PaneGroup::with_root(center_group);
|
||||||
|
|
||||||
if let Some(active_pane) = active_pane {
|
// // Change the focus to the workspace first so that we retrigger focus in on the pane.
|
||||||
cx.focus(&active_pane);
|
// cx.focus_self();
|
||||||
} 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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let docks = serialized_workspace.docks;
|
// if let Some(active_pane) = active_pane {
|
||||||
workspace.left_dock.update(cx, |dock, cx| {
|
// cx.focus(&active_pane);
|
||||||
dock.set_open(docks.left.visible, cx);
|
// } else {
|
||||||
if let Some(active_panel) = docks.left.active_panel {
|
// cx.focus(workspace.panes.last().unwrap());
|
||||||
if let Some(ix) = dock.panel_index_for_ui_name(&active_panel, cx) {
|
// }
|
||||||
dock.activate_panel(ix, cx);
|
// } else {
|
||||||
}
|
// let old_center_handle = old_center_pane.and_then(|weak| weak.upgrade());
|
||||||
}
|
// if let Some(old_center_handle) = old_center_handle {
|
||||||
dock.active_panel()
|
// cx.focus(&old_center_handle)
|
||||||
.map(|panel| panel.set_zoomed(docks.left.zoom, cx));
|
// } else {
|
||||||
if docks.left.visible && docks.left.zoom {
|
// 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 {
|
// let docks = serialized_workspace.docks;
|
||||||
cx.focus_self()
|
// workspace.left_dock.update(cx, |dock, cx| {
|
||||||
}
|
// dock.set_open(docks.left.visible, cx);
|
||||||
});
|
// if let Some(active_panel) = docks.left.active_panel {
|
||||||
workspace.bottom_dock.update(cx, |dock, cx| {
|
// if let Some(ix) = dock.panel_index_for_ui_name(&active_panel, cx) {
|
||||||
dock.set_open(docks.bottom.visible, cx);
|
// dock.activate_panel(ix, 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()
|
||||||
}
|
// .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()
|
// if docks.right.visible && docks.right.zoom {
|
||||||
.map(|panel| panel.set_zoomed(docks.bottom.zoom, cx));
|
// 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 {
|
// dock.active_panel()
|
||||||
cx.focus_self()
|
// .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
|
// 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(
|
fn open_items(
|
||||||
serialized_workspace: Option<SerializedWorkspace>,
|
_serialized_workspace: Option<SerializedWorkspace>,
|
||||||
mut project_paths_to_open: Vec<(PathBuf, Option<ProjectPath>)>,
|
project_paths_to_open: Vec<(PathBuf, Option<ProjectPath>)>,
|
||||||
app_state: Arc<AppState>,
|
app_state: Arc<AppState>,
|
||||||
mut cx: &mut MainThread<ViewContext<'_, Workspace>>,
|
cx: &mut MainThread<ViewContext<'_, Workspace>>,
|
||||||
) -> Result<Vec<Option<Result<Box<dyn ItemHandle>>>>> {
|
) -> impl Future<Output = 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 {
|
// todo!()
|
||||||
let restored_items = Workspace::load_workspace(
|
// if let Some(serialized_workspace) = serialized_workspace {
|
||||||
serialized_workspace,
|
// let restored_items = Workspace::load_workspace(
|
||||||
project_paths_to_open
|
// serialized_workspace,
|
||||||
.iter()
|
// project_paths_to_open
|
||||||
.map(|(_, project_path)| project_path)
|
// .iter()
|
||||||
.cloned()
|
// .map(|(_, project_path)| project_path)
|
||||||
.collect(),
|
// .cloned()
|
||||||
cx,
|
// .collect(),
|
||||||
)
|
// cx,
|
||||||
.await?;
|
// )
|
||||||
|
// .await?;
|
||||||
|
|
||||||
let restored_project_paths = restored_items
|
// let restored_project_paths = restored_items
|
||||||
.iter()
|
// .iter()
|
||||||
.filter_map(|item| item.as_ref()?.project_path(cx))
|
// .filter_map(|item| item.as_ref()?.project_path(cx))
|
||||||
.collect::<HashSet<_>>();
|
// .collect::<HashSet<_>>();
|
||||||
|
|
||||||
for restored_item in restored_items {
|
// for restored_item in restored_items {
|
||||||
opened_items.push(restored_item.map(Ok));
|
// 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)| {
|
||||||
if let Some(project_path_to_open) = project_path {
|
// if let Some(project_path_to_open) = project_path {
|
||||||
if restored_project_paths.contains(project_path_to_open) {
|
// if restored_project_paths.contains(project_path_to_open) {
|
||||||
*project_path = None;
|
// *project_path = None;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
} else {
|
// } else {
|
||||||
for _ in 0..project_paths_to_open.len() {
|
for _ in 0..project_paths_to_open.len() {
|
||||||
opened_items.push(None);
|
opened_items.push(None);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// }
|
||||||
assert!(opened_items.len() == project_paths_to_open.len());
|
assert!(opened_items.len() == project_paths_to_open.len());
|
||||||
|
|
||||||
let tasks =
|
let tasks =
|
||||||
|
@ -3629,16 +3651,17 @@ async fn open_items(
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
for maybe_opened_path in futures::future::join_all(tasks.into_iter())
|
let tasks = tasks.collect::<Vec<_>>();
|
||||||
.await
|
async move {
|
||||||
.into_iter()
|
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 {
|
if let Some((i, path_open_result)) = maybe_opened_path {
|
||||||
opened_items[i] = Some(path_open_result);
|
opened_items[i] = Some(path_open_result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Ok(opened_items)
|
Ok(opened_items)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn notify_of_new_dock(workspace: &WeakView<Workspace>, cx: &mut AsyncAppContext) {
|
// fn notify_of_new_dock(workspace: &WeakView<Workspace>, cx: &mut AsyncAppContext) {
|
||||||
|
@ -4102,8 +4125,8 @@ pub async fn activate_workspace_for_project(
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let predicate = cx
|
let predicate = workspace
|
||||||
.update_window_root(&workspace, |workspace, cx| {
|
.update(cx, |workspace, cx| {
|
||||||
let project = workspace.project.read(cx);
|
let project = workspace.project.read(cx);
|
||||||
if predicate(project, cx) {
|
if predicate(project, cx) {
|
||||||
cx.activate_window();
|
cx.activate_window();
|
||||||
|
@ -4326,10 +4349,11 @@ pub fn open_paths(
|
||||||
> {
|
> {
|
||||||
let app_state = app_state.clone();
|
let app_state = app_state.clone();
|
||||||
let abs_paths = abs_paths.to_vec();
|
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
|
// Open paths in existing workspace if possible
|
||||||
let existing = activate_workspace_for_project(&mut cx, move |project, cx| {
|
let existing = activate_workspace_for_project(&mut cx, {
|
||||||
project.contains_paths(&abs_paths, cx)
|
let abs_paths = abs_paths.clone();
|
||||||
|
move |project, cx| project.contains_paths(&abs_paths, cx)
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
@ -4343,32 +4367,30 @@ pub fn open_paths(
|
||||||
// ))
|
// ))
|
||||||
todo!()
|
todo!()
|
||||||
} else {
|
} else {
|
||||||
// Ok(cx
|
cx.update(move |cx| {
|
||||||
// .update(|cx| {
|
Workspace::new_local(abs_paths, app_state.clone(), requesting_window, cx)
|
||||||
// Workspace::new_local(abs_paths, app_state.clone(), requesting_window, cx)
|
})?
|
||||||
// })
|
.await
|
||||||
// .await)
|
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_new(
|
pub fn open_new(
|
||||||
app_state: &Arc<AppState>,
|
app_state: &Arc<AppState>,
|
||||||
cx: &mut AppContext,
|
cx: &mut MainThread<AppContext>,
|
||||||
init: impl FnOnce(&mut Workspace, &mut ViewContext<Workspace>) + 'static,
|
init: impl FnOnce(&mut Workspace, &mut ViewContext<Workspace>) + 'static + Send,
|
||||||
) -> Task<()> {
|
) -> Task<()> {
|
||||||
let task = Workspace::new_local(Vec::new(), app_state.clone(), None, cx);
|
let task = Workspace::new_local(Vec::new(), app_state.clone(), None, cx);
|
||||||
cx.spawn(|mut cx| async move {
|
cx.spawn_on_main(|mut cx| async move {
|
||||||
let (workspace, opened_paths) = task.await;
|
if let Some((workspace, opened_paths)) = task.await.log_err() {
|
||||||
|
workspace
|
||||||
workspace
|
.update(&mut cx, |workspace, cx| {
|
||||||
.update(&mut cx, |workspace, cx| {
|
if opened_paths.is_empty() {
|
||||||
if opened_paths.is_empty() {
|
init(workspace, cx)
|
||||||
init(workspace, cx)
|
}
|
||||||
}
|
})
|
||||||
})
|
.log_err();
|
||||||
.log_err();
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ use client2::UserStore;
|
||||||
use db2::kvp::KEY_VALUE_STORE;
|
use db2::kvp::KEY_VALUE_STORE;
|
||||||
use fs2::RealFs;
|
use fs2::RealFs;
|
||||||
use futures::{channel::mpsc, SinkExt, StreamExt};
|
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 isahc::{prelude::Configurable, Request};
|
||||||
use language2::LanguageRegistry;
|
use language2::LanguageRegistry;
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
|
@ -24,7 +24,7 @@ use settings2::{
|
||||||
default_settings, handle_settings_file_changes, watch_config_file, Settings, SettingsStore,
|
default_settings, handle_settings_file_changes, watch_config_file, Settings, SettingsStore,
|
||||||
};
|
};
|
||||||
use simplelog::ConfigBuilder;
|
use simplelog::ConfigBuilder;
|
||||||
use smol::process::Command;
|
use smol::{future::FutureExt, process::Command};
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
ffi::OsStr,
|
ffi::OsStr,
|
||||||
|
@ -40,6 +40,7 @@ use std::{
|
||||||
time::{SystemTime, UNIX_EPOCH},
|
time::{SystemTime, UNIX_EPOCH},
|
||||||
};
|
};
|
||||||
use util::{
|
use util::{
|
||||||
|
async_maybe,
|
||||||
channel::{parse_zed_link, ReleaseChannel, RELEASE_CHANNEL},
|
channel::{parse_zed_link, ReleaseChannel, RELEASE_CHANNEL},
|
||||||
http::{self, HttpClient},
|
http::{self, HttpClient},
|
||||||
paths, ResultExt,
|
paths, ResultExt,
|
||||||
|
@ -242,7 +243,7 @@ fn main() {
|
||||||
// .detach_and_log_err(cx)
|
// .detach_and_log_err(cx)
|
||||||
}
|
}
|
||||||
Ok(None) | Err(_) => cx
|
Ok(None) | Err(_) => cx
|
||||||
.spawn({
|
.spawn_on_main({
|
||||||
let app_state = app_state.clone();
|
let app_state = app_state.clone();
|
||||||
|cx| async move { restore_or_create_workspace(&app_state, cx).await }
|
|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(
|
||||||
if let Some(location) = workspace2::last_opened_workspace_paths().await {
|
app_state: &Arc<AppState>,
|
||||||
cx.update(|cx| workspace2::open_paths(location.paths().as_ref(), app_state, None, cx))?
|
mut cx: MainThread<AsyncAppContext>,
|
||||||
.await
|
) {
|
||||||
.log_err();
|
async_maybe!({
|
||||||
} else if matches!(KEY_VALUE_STORE.read_kvp(FIRST_OPEN), Ok(None)) {
|
if let Some(location) = workspace2::last_opened_workspace_paths().await {
|
||||||
cx.update(|cx| show_welcome_experience(app_state, cx));
|
cx.update(|cx| workspace2::open_paths(location.paths().as_ref(), app_state, None, cx))?
|
||||||
} else {
|
.await
|
||||||
cx.update(|cx| {
|
.log_err();
|
||||||
workspace2::open_new(app_state, cx, |workspace, 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)) {
|
||||||
Editor::new_file(workspace, &Default::default(), cx)
|
// todo!(welcome)
|
||||||
})
|
//} else if matches!(KEY_VALUE_STORE.read_kvp(FIRST_OPEN), Ok(None)) {
|
||||||
.detach();
|
//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() {
|
fn init_paths() {
|
||||||
|
|
|
@ -7,7 +7,7 @@ pub use assets::*;
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use gpui2::{
|
use gpui2::{
|
||||||
point, px, AppContext, AsyncAppContext, AsyncWindowContext, MainThread, Point, Task,
|
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 only_instance::*;
|
||||||
pub use open_listener::*;
|
pub use open_listener::*;
|
||||||
|
@ -165,7 +165,7 @@ pub async fn handle_cli_connection(
|
||||||
if paths.is_empty() {
|
if paths.is_empty() {
|
||||||
let (done_tx, done_rx) = oneshot::channel();
|
let (done_tx, done_rx) = oneshot::channel();
|
||||||
let _subscription =
|
let _subscription =
|
||||||
cx.update_window_root(&workspace, move |_, cx| {
|
workspace.update(&mut cx, move |_, cx| {
|
||||||
cx.on_release(|_, _| {
|
cx.on_release(|_, _| {
|
||||||
let _ = done_tx.send(());
|
let _ = done_tx.send(());
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue