@@ -1,35 +1,36 @@
use crate::{Toast, Workspace};
use collections::HashMap;
-use gpui2::{AnyViewHandle, AppContext, Entity, View, ViewContext, ViewHandle};
+use gpui2::{AnyView, AppContext, Entity, EntityId, EventEmitter, Render, View, ViewContext};
use std::{any::TypeId, ops::DerefMut};
pub fn init(cx: &mut AppContext) {
cx.set_global(NotificationTracker::new());
- simple_message_notification::init(cx);
+ // todo!()
+ // simple_message_notification::init(cx);
}
-pub trait Notification: View {
- fn should_dismiss_notification_on_event(&self, event: &<Self as Entity>::Event) -> bool;
+pub trait Notification: EventEmitter + Render {
+ fn should_dismiss_notification_on_event(&self, event: &Self::Event) -> bool;
}
-pub trait NotificationHandle {
- fn id(&self) -> usize;
- fn as_any(&self) -> &AnyViewHandle;
+pub trait NotificationHandle: Send {
+ fn id(&self) -> EntityId;
+ fn to_any(&self) -> AnyView;
}
-impl<T: Notification> NotificationHandle for ViewHandle<T> {
- fn id(&self) -> usize {
- self.id()
+impl<T: Notification> NotificationHandle for View<T> {
+ fn id(&self) -> EntityId {
+ self.entity_id()
}
- fn as_any(&self) -> &AnyViewHandle {
- self
+ fn to_any(&self) -> AnyView {
+ self.clone().into()
}
}
-impl From<&dyn NotificationHandle> for AnyViewHandle {
+impl From<&dyn NotificationHandle> for AnyView {
fn from(val: &dyn NotificationHandle) -> Self {
- val.as_any().clone()
+ val.to_any()
}
}
@@ -75,14 +76,12 @@ impl Workspace {
&mut self,
id: usize,
cx: &mut ViewContext<Self>,
- build_notification: impl FnOnce(&mut ViewContext<Self>) -> ViewHandle<V>,
+ build_notification: impl FnOnce(&mut ViewContext<Self>) -> View<V>,
) {
if !self.has_shown_notification_once::<V>(id, cx) {
- cx.update_global::<NotificationTracker, _, _>(|tracker, _| {
- let entry = tracker.entry(TypeId::of::<V>()).or_default();
- entry.push(id);
- });
-
+ let tracker = cx.global_mut::<NotificationTracker>();
+ let entry = tracker.entry(TypeId::of::<V>()).or_default();
+ entry.push(id);
self.show_notification::<V>(id, cx, build_notification)
}
}
@@ -91,7 +90,7 @@ impl Workspace {
&mut self,
id: usize,
cx: &mut ViewContext<Self>,
- build_notification: impl FnOnce(&mut ViewContext<Self>) -> ViewHandle<V>,
+ build_notification: impl FnOnce(&mut ViewContext<Self>) -> View<V>,
) {
let type_id = TypeId::of::<V>();
if self
@@ -121,22 +120,24 @@ impl Workspace {
}
pub fn show_toast(&mut self, toast: Toast, cx: &mut ViewContext<Self>) {
- self.dismiss_notification::<simple_message_notification::MessageNotification>(toast.id, cx);
- self.show_notification(toast.id, cx, |cx| {
- cx.add_view(|_cx| match toast.on_click.as_ref() {
- Some((click_msg, on_click)) => {
- let on_click = on_click.clone();
- simple_message_notification::MessageNotification::new(toast.msg.clone())
- .with_click_message(click_msg.clone())
- .on_click(move |cx| on_click(cx))
- }
- None => simple_message_notification::MessageNotification::new(toast.msg.clone()),
- })
- })
+ todo!()
+ // self.dismiss_notification::<simple_message_notification::MessageNotification>(toast.id, cx);
+ // self.show_notification(toast.id, cx, |cx| {
+ // cx.add_view(|_cx| match toast.on_click.as_ref() {
+ // Some((click_msg, on_click)) => {
+ // let on_click = on_click.clone();
+ // simple_message_notification::MessageNotification::new(toast.msg.clone())
+ // .with_click_message(click_msg.clone())
+ // .on_click(move |cx| on_click(cx))
+ // }
+ // None => simple_message_notification::MessageNotification::new(toast.msg.clone()),
+ // })
+ // })
}
pub fn dismiss_toast(&mut self, id: usize, cx: &mut ViewContext<Self>) {
- self.dismiss_notification::<simple_message_notification::MessageNotification>(id, cx);
+ todo!()
+ // self.dismiss_notification::<simple_message_notification::MessageNotification>(id, cx);
}
fn dismiss_notification_internal(
@@ -159,20 +160,12 @@ impl Workspace {
pub mod simple_message_notification {
use super::Notification;
- use crate::Workspace;
- use gpui2::{
- actions,
- elements::{Flex, MouseEventHandler, Padding, ParentElement, Svg, Text},
- fonts::TextStyle,
- impl_actions,
- platform::{CursorStyle, MouseButton},
- AnyElement, AppContext, Element, Entity, View, ViewContext,
- };
- use menu::Cancel;
+ use gpui2::{AnyElement, AppContext, Div, EventEmitter, Render, TextStyle, ViewContext};
use serde::Deserialize;
use std::{borrow::Cow, sync::Arc};
- actions!(message_notifications, [CancelMessageNotification]);
+ // todo!()
+ // actions!(message_notifications, [CancelMessageNotification]);
#[derive(Clone, Default, Deserialize, PartialEq)]
pub struct OsOpen(pub Cow<'static, str>);
@@ -183,16 +176,18 @@ pub mod simple_message_notification {
}
}
- impl_actions!(message_notifications, [OsOpen]);
-
- pub fn init(cx: &mut AppContext) {
- cx.add_action(MessageNotification::dismiss);
- cx.add_action(
- |_workspace: &mut Workspace, open_action: &OsOpen, cx: &mut ViewContext<Workspace>| {
- cx.platform().open_url(open_action.0.as_ref());
- },
- )
- }
+ // todo!()
+ // impl_actions!(message_notifications, [OsOpen]);
+ //
+ // todo!()
+ // pub fn init(cx: &mut AppContext) {
+ // cx.add_action(MessageNotification::dismiss);
+ // cx.add_action(
+ // |_workspace: &mut Workspace, open_action: &OsOpen, cx: &mut ViewContext<Workspace>| {
+ // cx.platform().open_url(open_action.0.as_ref());
+ // },
+ // )
+ // }
enum NotificationMessage {
Text(Cow<'static, str>),
@@ -201,7 +196,7 @@ pub mod simple_message_notification {
pub struct MessageNotification {
message: NotificationMessage,
- on_click: Option<Arc<dyn Fn(&mut ViewContext<Self>)>>,
+ on_click: Option<Arc<dyn Fn(&mut ViewContext<Self>) + Send + Sync>>,
click_message: Option<Cow<'static, str>>,
}
@@ -209,7 +204,7 @@ pub mod simple_message_notification {
Dismiss,
}
- impl Entity for MessageNotification {
+ impl EventEmitter for MessageNotification {
type Event = MessageNotificationEvent;
}
@@ -225,138 +220,147 @@ pub mod simple_message_notification {
}
}
- pub fn new_element(
- message: fn(TextStyle, &AppContext) -> AnyElement<MessageNotification>,
- ) -> MessageNotification {
- Self {
- message: NotificationMessage::Element(message),
- on_click: None,
- click_message: None,
- }
- }
-
- pub fn with_click_message<S>(mut self, message: S) -> Self
- where
- S: Into<Cow<'static, str>>,
- {
- self.click_message = Some(message.into());
- self
- }
-
- pub fn on_click<F>(mut self, on_click: F) -> Self
- where
- F: 'static + Fn(&mut ViewContext<Self>),
- {
- self.on_click = Some(Arc::new(on_click));
- self
- }
-
- pub fn dismiss(&mut self, _: &CancelMessageNotification, cx: &mut ViewContext<Self>) {
- cx.emit(MessageNotificationEvent::Dismiss);
- }
+ // todo!()
+ // pub fn new_element(
+ // message: fn(TextStyle, &AppContext) -> AnyElement<MessageNotification>,
+ // ) -> MessageNotification {
+ // Self {
+ // message: NotificationMessage::Element(message),
+ // on_click: None,
+ // click_message: None,
+ // }
+ // }
+
+ // pub fn with_click_message<S>(mut self, message: S) -> Self
+ // where
+ // S: Into<Cow<'static, str>>,
+ // {
+ // self.click_message = Some(message.into());
+ // self
+ // }
+
+ // pub fn on_click<F>(mut self, on_click: F) -> Self
+ // where
+ // F: 'static + Fn(&mut ViewContext<Self>),
+ // {
+ // self.on_click = Some(Arc::new(on_click));
+ // self
+ // }
+
+ // pub fn dismiss(&mut self, _: &CancelMessageNotification, cx: &mut ViewContext<Self>) {
+ // cx.emit(MessageNotificationEvent::Dismiss);
+ // }
}
- impl View for MessageNotification {
- fn ui_name() -> &'static str {
- "MessageNotification"
- }
-
- fn render(&mut self, cx: &mut gpui2::ViewContext<Self>) -> gpui::AnyElement<Self> {
- let theme = theme2::current(cx).clone();
- let theme = &theme.simple_message_notification;
+ impl Render for MessageNotification {
+ type Element = Div<Self>;
- enum MessageNotificationTag {}
-
- let click_message = self.click_message.clone();
- let message = match &self.message {
- NotificationMessage::Text(text) => {
- Text::new(text.to_owned(), theme.message.text.clone()).into_any()
- }
- NotificationMessage::Element(e) => e(theme.message.text.clone(), cx),
- };
- let on_click = self.on_click.clone();
- let has_click_action = on_click.is_some();
-
- Flex::column()
- .with_child(
- Flex::row()
- .with_child(
- message
- .contained()
- .with_style(theme.message.container)
- .aligned()
- .top()
- .left()
- .flex(1., true),
- )
- .with_child(
- MouseEventHandler::new::<Cancel, _>(0, cx, |state, _| {
- let style = theme.dismiss_button.style_for(state);
- Svg::new("icons/x.svg")
- .with_color(style.color)
- .constrained()
- .with_width(style.icon_width)
- .aligned()
- .contained()
- .with_style(style.container)
- .constrained()
- .with_width(style.button_width)
- .with_height(style.button_width)
- })
- .with_padding(Padding::uniform(5.))
- .on_click(MouseButton::Left, move |_, this, cx| {
- this.dismiss(&Default::default(), cx);
- })
- .with_cursor_style(CursorStyle::PointingHand)
- .aligned()
- .constrained()
- .with_height(cx.font_cache().line_height(theme.message.text.font_size))
- .aligned()
- .top()
- .flex_float(),
- ),
- )
- .with_children({
- click_message
- .map(|click_message| {
- MouseEventHandler::new::<MessageNotificationTag, _>(
- 0,
- cx,
- |state, _| {
- let style = theme.action_message.style_for(state);
-
- Flex::row()
- .with_child(
- Text::new(click_message, style.text.clone())
- .contained()
- .with_style(style.container),
- )
- .contained()
- },
- )
- .on_click(MouseButton::Left, move |_, this, cx| {
- if let Some(on_click) = on_click.as_ref() {
- on_click(cx);
- this.dismiss(&Default::default(), cx);
- }
- })
- // Since we're not using a proper overlay, we have to capture these extra events
- .on_down(MouseButton::Left, |_, _, _| {})
- .on_up(MouseButton::Left, |_, _, _| {})
- .with_cursor_style(if has_click_action {
- CursorStyle::PointingHand
- } else {
- CursorStyle::Arrow
- })
- })
- .into_iter()
- })
- .into_any()
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
+ todo!()
}
}
+ // todo!()
+ // impl View for MessageNotification {
+ // fn ui_name() -> &'static str {
+ // "MessageNotification"
+ // }
+
+ // fn render(&mut self, cx: &mut gpui2::ViewContext<Self>) -> gpui::AnyElement<Self> {
+ // let theme = theme2::current(cx).clone();
+ // let theme = &theme.simple_message_notification;
+
+ // enum MessageNotificationTag {}
+
+ // let click_message = self.click_message.clone();
+ // let message = match &self.message {
+ // NotificationMessage::Text(text) => {
+ // Text::new(text.to_owned(), theme.message.text.clone()).into_any()
+ // }
+ // NotificationMessage::Element(e) => e(theme.message.text.clone(), cx),
+ // };
+ // let on_click = self.on_click.clone();
+ // let has_click_action = on_click.is_some();
+
+ // Flex::column()
+ // .with_child(
+ // Flex::row()
+ // .with_child(
+ // message
+ // .contained()
+ // .with_style(theme.message.container)
+ // .aligned()
+ // .top()
+ // .left()
+ // .flex(1., true),
+ // )
+ // .with_child(
+ // MouseEventHandler::new::<Cancel, _>(0, cx, |state, _| {
+ // let style = theme.dismiss_button.style_for(state);
+ // Svg::new("icons/x.svg")
+ // .with_color(style.color)
+ // .constrained()
+ // .with_width(style.icon_width)
+ // .aligned()
+ // .contained()
+ // .with_style(style.container)
+ // .constrained()
+ // .with_width(style.button_width)
+ // .with_height(style.button_width)
+ // })
+ // .with_padding(Padding::uniform(5.))
+ // .on_click(MouseButton::Left, move |_, this, cx| {
+ // this.dismiss(&Default::default(), cx);
+ // })
+ // .with_cursor_style(CursorStyle::PointingHand)
+ // .aligned()
+ // .constrained()
+ // .with_height(cx.font_cache().line_height(theme.message.text.font_size))
+ // .aligned()
+ // .top()
+ // .flex_float(),
+ // ),
+ // )
+ // .with_children({
+ // click_message
+ // .map(|click_message| {
+ // MouseEventHandler::new::<MessageNotificationTag, _>(
+ // 0,
+ // cx,
+ // |state, _| {
+ // let style = theme.action_message.style_for(state);
+
+ // Flex::row()
+ // .with_child(
+ // Text::new(click_message, style.text.clone())
+ // .contained()
+ // .with_style(style.container),
+ // )
+ // .contained()
+ // },
+ // )
+ // .on_click(MouseButton::Left, move |_, this, cx| {
+ // if let Some(on_click) = on_click.as_ref() {
+ // on_click(cx);
+ // this.dismiss(&Default::default(), cx);
+ // }
+ // })
+ // // Since we're not using a proper overlay, we have to capture these extra events
+ // .on_down(MouseButton::Left, |_, _, _| {})
+ // .on_up(MouseButton::Left, |_, _, _| {})
+ // .with_cursor_style(if has_click_action {
+ // CursorStyle::PointingHand
+ // } else {
+ // CursorStyle::Arrow
+ // })
+ // })
+ // .into_iter()
+ // })
+ // .into_any()
+ // }
+ // }
impl Notification for MessageNotification {
- fn should_dismiss_notification_on_event(&self, event: &<Self as Entity>::Event) -> bool {
+ fn should_dismiss_notification_on_event(&self, event: &Self::Event) -> bool {
match event {
MessageNotificationEvent::Dismiss => true,
}
@@ -384,15 +388,15 @@ where
match self {
Ok(value) => Some(value),
Err(err) => {
- workspace.show_notification(0, cx, |cx| {
- cx.add_view(|_cx| {
- simple_message_notification::MessageNotification::new(format!(
- "Error: {:?}",
- err,
- ))
- })
- });
-
+ log::error!("TODO {err:?}");
+ // todo!()
+ // workspace.show_notification(0, cx, |cx| {
+ // cx.add_view(|_cx| {
+ // simple_message_notification::MessageNotification::new(format!(
+ // "Error: {err:?}",
+ // ))
+ // })
+ // });
None
}
}
@@ -1,6 +1,6 @@
pub mod dock;
pub mod item;
-// pub mod notifications;
+pub mod notifications;
pub mod pane;
pub mod pane_group;
mod persistence;
@@ -10,6 +10,10 @@ mod status_bar;
mod toolbar;
mod workspace_settings;
+use crate::persistence::model::{
+ DockData, DockStructure, SerializedItem, SerializedPane, SerializedPaneGroup,
+ SerializedWorkspace,
+};
use anyhow::{anyhow, Result};
use call2::ActiveCall;
use client2::{
@@ -17,19 +21,22 @@ use client2::{
Client, TypedEnvelope, UserStore,
};
use collections::{HashMap, HashSet};
-use dock::Dock;
+use dock::{Dock, DockPosition, PanelButtons};
use futures::{
channel::{mpsc, oneshot},
- FutureExt,
+ FutureExt, Stream, StreamExt,
};
use gpui2::{
- div, AnyModel, AnyView, AppContext, AsyncAppContext, AsyncWindowContext, Div, Entity,
- EventEmitter, MainThread, Model, ModelContext, Render, Subscription, Task, View, ViewContext,
- VisualContext, WeakView, WindowBounds, WindowContext, WindowHandle, WindowOptions,
+ div, point, size, AnyModel, AnyView, AppContext, AsyncAppContext, AsyncWindowContext, Bounds,
+ 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 lazy_static::lazy_static;
use node_runtime::NodeRuntime;
+use notifications::{simple_message_notification::MessageNotification, NotificationHandle};
pub use pane::*;
pub use pane_group::*;
use persistence::{
@@ -37,8 +44,12 @@ use persistence::{
DB,
};
use project2::{Project, ProjectEntryId, ProjectPath, Worktree};
+use serde::Deserialize;
+use status_bar::StatusBar;
use std::{
any::TypeId,
+ borrow::Cow,
+ env,
path::{Path, PathBuf},
sync::{atomic::AtomicUsize, Arc},
time::Duration,
@@ -47,21 +58,16 @@ pub use toolbar::{ToolbarItemLocation, ToolbarItemView};
use util::ResultExt;
use uuid::Uuid;
-use crate::persistence::model::{
- DockData, DockStructure, SerializedItem, SerializedPane, SerializedPaneGroup,
- SerializedWorkspace,
-};
-
-// lazy_static! {
-// static ref ZED_WINDOW_SIZE: Option<Vector2F> = env::var("ZED_WINDOW_SIZE")
-// .ok()
-// .as_deref()
-// .and_then(parse_pixel_position_env_var);
-// static ref ZED_WINDOW_POSITION: Option<Vector2F> = env::var("ZED_WINDOW_POSITION")
-// .ok()
-// .as_deref()
-// .and_then(parse_pixel_position_env_var);
-// }
+lazy_static! {
+ static ref ZED_WINDOW_SIZE: Option<Size<GlobalPixels>> = env::var("ZED_WINDOW_SIZE")
+ .ok()
+ .as_deref()
+ .and_then(parse_pixel_size_env_var);
+ static ref ZED_WINDOW_POSITION: Option<Point<GlobalPixels>> = env::var("ZED_WINDOW_POSITION")
+ .ok()
+ .as_deref()
+ .and_then(parse_pixel_position_env_var);
+}
// pub trait Modal: View {
// fn has_focus(&self) -> bool;
@@ -151,13 +157,13 @@ use crate::persistence::model::{
// pub save_intent: Option<SaveIntent>,
// }
-// #[derive(Deserialize)]
-// pub struct Toast {
-// id: usize,
-// msg: Cow<'static, str>,
-// #[serde(skip)]
-// on_click: Option<(Cow<'static, str>, Arc<dyn Fn(&mut WindowContext)>)>,
-// }
+#[derive(Deserialize)]
+pub struct Toast {
+ id: usize,
+ msg: Cow<'static, str>,
+ #[serde(skip)]
+ on_click: Option<(Cow<'static, str>, Arc<dyn Fn(&mut WindowContext)>)>,
+}
// impl Toast {
// pub fn new<I: Into<Cow<'static, str>>>(id: usize, msg: I) -> Self {
@@ -336,7 +342,7 @@ pub type WorkspaceId = i64;
// err.notify_err(workspace, cx);
// } else {
// workspace.show_notification(1, cx, |cx| {
-// cx.add_view(|_| {
+// cx.build_view(|_| {
// MessageNotification::new("Successfully installed the `zed` binary")
// })
// });
@@ -418,7 +424,7 @@ pub struct AppState {
pub workspace_store: Model<WorkspaceStore>,
pub fs: Arc<dyn fs2::Fs>,
pub build_window_options:
- fn(Option<WindowBounds>, Option<Uuid>, MainThread<AppContext>) -> WindowOptions,
+ fn(Option<WindowBounds>, Option<Uuid>, &mut MainThread<AppContext>) -> WindowOptions,
pub initialize_workspace: fn(
WeakView<Workspace>,
bool,
@@ -539,24 +545,24 @@ pub struct Workspace {
right_dock: View<Dock>,
panes: Vec<View<Pane>>,
panes_by_item: HashMap<usize, WeakView<Pane>>,
- // active_pane: View<Pane>,
+ active_pane: View<Pane>,
last_active_center_pane: Option<WeakView<Pane>>,
// last_active_view_id: Option<proto::ViewId>,
// status_bar: View<StatusBar>,
// titlebar_item: Option<AnyViewHandle>,
- // notifications: Vec<(TypeId, usize, Box<dyn NotificationHandle>)>,
+ notifications: Vec<(TypeId, usize, Box<dyn NotificationHandle>)>,
project: Model<Project>,
follower_states: HashMap<View<Pane>, FollowerState>,
last_leaders_by_pane: HashMap<WeakView<Pane>, PeerId>,
- // window_edited: bool,
+ window_edited: bool,
active_call: Option<(Model<ActiveCall>, Vec<Subscription>)>,
leader_updates_tx: mpsc::UnboundedSender<(PeerId, proto::UpdateFollowers)>,
database_id: WorkspaceId,
app_state: Arc<AppState>,
- // subscriptions: Vec<Subscription>,
- // _apply_leader_updates: Task<Result<()>>,
- // _observe_current_user: Task<Result<()>>,
- // _schedule_serialize: Option<Task<()>>,
+ subscriptions: Vec<Subscription>,
+ _apply_leader_updates: Task<Result<()>>,
+ _observe_current_user: Task<Result<()>>,
+ _schedule_serialize: Option<Task<()>>,
pane_history_timestamp: Arc<AtomicUsize>,
}
@@ -581,200 +587,205 @@ struct FollowerState {
enum WorkspaceBounds {}
impl Workspace {
- // pub fn new(
- // workspace_id: WorkspaceId,
- // project: ModelHandle<Project>,
- // app_state: Arc<AppState>,
- // cx: &mut ViewContext<Self>,
- // ) -> Self {
- // cx.observe(&project, |_, _, cx| cx.notify()).detach();
- // cx.subscribe(&project, move |this, _, event, cx| {
- // match event {
- // project::Event::RemoteIdChanged(_) => {
- // this.update_window_title(cx);
- // }
+ pub fn new(
+ workspace_id: WorkspaceId,
+ project: Model<Project>,
+ app_state: Arc<AppState>,
+ cx: &mut ViewContext<Self>,
+ ) -> Self {
+ cx.observe(&project, |_, _, cx| cx.notify()).detach();
+ cx.subscribe(&project, move |this, _, event, cx| {
+ match event {
+ project2::Event::RemoteIdChanged(_) => {
+ this.update_window_title(cx);
+ }
- // project::Event::CollaboratorLeft(peer_id) => {
- // this.collaborator_left(*peer_id, cx);
- // }
+ project2::Event::CollaboratorLeft(peer_id) => {
+ this.collaborator_left(*peer_id, cx);
+ }
- // project::Event::WorktreeRemoved(_) | project::Event::WorktreeAdded => {
- // this.update_window_title(cx);
- // this.serialize_workspace(cx);
- // }
+ project2::Event::WorktreeRemoved(_) | project2::Event::WorktreeAdded => {
+ this.update_window_title(cx);
+ this.serialize_workspace(cx);
+ }
- // project::Event::DisconnectedFromHost => {
- // this.update_window_edited(cx);
- // cx.blur();
- // }
+ project2::Event::DisconnectedFromHost => {
+ this.update_window_edited(cx);
+ cx.blur();
+ }
- // project::Event::Closed => {
- // cx.remove_window();
- // }
+ project2::Event::Closed => {
+ // todo!()
+ // cx.remove_window();
+ }
- // project::Event::DeletedEntry(entry_id) => {
- // for pane in this.panes.iter() {
- // pane.update(cx, |pane, cx| {
- // pane.handle_deleted_project_item(*entry_id, cx)
- // });
- // }
- // }
+ project2::Event::DeletedEntry(entry_id) => {
+ for pane in this.panes.iter() {
+ pane.update(cx, |pane, cx| {
+ pane.handle_deleted_project_item(*entry_id, cx)
+ });
+ }
+ }
- // project::Event::Notification(message) => this.show_notification(0, cx, |cx| {
- // cx.add_view(|_| MessageNotification::new(message.clone()))
- // }),
+ project2::Event::Notification(message) => this.show_notification(0, cx, |cx| {
+ cx.build_view(|_| MessageNotification::new(message.clone()))
+ }),
- // _ => {}
- // }
- // cx.notify()
- // })
- // .detach();
+ _ => {}
+ }
+ cx.notify()
+ })
+ .detach();
- // let weak_handle = cx.weak_handle();
- // let pane_history_timestamp = Arc::new(AtomicUsize::new(0));
+ let weak_handle = cx.view().downgrade();
+ let pane_history_timestamp = Arc::new(AtomicUsize::new(0));
- // let center_pane = cx.add_view(|cx| {
- // Pane::new(
- // weak_handle.clone(),
- // project.clone(),
- // pane_history_timestamp.clone(),
- // cx,
- // )
- // });
- // cx.subscribe(¢er_pane, Self::handle_pane_event).detach();
- // cx.focus(¢er_pane);
- // cx.emit(Event::PaneAdded(center_pane.clone()));
+ let center_pane = cx.build_view(|cx| {
+ Pane::new(
+ weak_handle.clone(),
+ project.clone(),
+ pane_history_timestamp.clone(),
+ cx,
+ )
+ });
+ cx.subscribe(¢er_pane, Self::handle_pane_event).detach();
+ // todo!()
+ // cx.focus(¢er_pane);
+ cx.emit(Event::PaneAdded(center_pane.clone()));
- // app_state.workspace_store.update(cx, |store, _| {
- // store.workspaces.insert(weak_handle.clone());
- // });
+ let window_handle = cx.window_handle().downcast::<Workspace>().unwrap();
+ app_state.workspace_store.update(cx, |store, _| {
+ store.workspaces.insert(window_handle);
+ });
- // let mut current_user = app_state.user_store.read(cx).watch_current_user();
- // let mut connection_status = app_state.client.status();
- // let _observe_current_user = cx.spawn(|this, mut cx| async move {
- // current_user.recv().await;
- // connection_status.recv().await;
- // let mut stream =
- // Stream::map(current_user, drop).merge(Stream::map(connection_status, drop));
+ let mut current_user = app_state.user_store.read(cx).watch_current_user();
+ let mut connection_status = app_state.client.status();
+ let _observe_current_user = cx.spawn(|this, mut cx| async move {
+ current_user.next().await;
+ connection_status.next().await;
+ let mut stream =
+ Stream::map(current_user, drop).merge(Stream::map(connection_status, drop));
- // while stream.recv().await.is_some() {
- // this.update(&mut cx, |_, cx| cx.notify())?;
- // }
- // anyhow::Ok(())
- // });
+ while stream.recv().await.is_some() {
+ this.update(&mut cx, |_, cx| cx.notify())?;
+ }
+ anyhow::Ok(())
+ });
- // // All leader updates are enqueued and then processed in a single task, so
- // // that each asynchronous operation can be run in order.
- // let (leader_updates_tx, mut leader_updates_rx) =
- // mpsc::unbounded::<(PeerId, proto::UpdateFollowers)>();
- // let _apply_leader_updates = cx.spawn(|this, mut cx| async move {
- // while let Some((leader_id, update)) = leader_updates_rx.next().await {
- // Self::process_leader_update(&this, leader_id, update, &mut cx)
- // .await
- // .log_err();
- // }
+ // All leader updates are enqueued and then processed in a single task, so
+ // that each asynchronous operation can be run in order.
+ let (leader_updates_tx, mut leader_updates_rx) =
+ mpsc::unbounded::<(PeerId, proto::UpdateFollowers)>();
+ let _apply_leader_updates = cx.spawn(|this, mut cx| async move {
+ while let Some((leader_id, update)) = leader_updates_rx.next().await {
+ Self::process_leader_update(&this, leader_id, update, &mut cx)
+ .await
+ .log_err();
+ }
- // Ok(())
- // });
+ Ok(())
+ });
- // cx.emit_global(WorkspaceCreated(weak_handle.clone()));
-
- // let left_dock = cx.add_view(|_| Dock::new(DockPosition::Left));
- // let bottom_dock = cx.add_view(|_| Dock::new(DockPosition::Bottom));
- // let right_dock = cx.add_view(|_| Dock::new(DockPosition::Right));
- // let left_dock_buttons =
- // cx.add_view(|cx| PanelButtons::new(left_dock.clone(), weak_handle.clone(), cx));
- // let bottom_dock_buttons =
- // cx.add_view(|cx| PanelButtons::new(bottom_dock.clone(), weak_handle.clone(), cx));
- // let right_dock_buttons =
- // cx.add_view(|cx| PanelButtons::new(right_dock.clone(), weak_handle.clone(), cx));
- // let status_bar = cx.add_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);
- // status_bar.add_right_item(bottom_dock_buttons, cx);
- // status_bar
- // });
+ // todo!("replace with a different mechanism")
+ // cx.emit_global(WorkspaceCreated(weak_handle.clone()));
+
+ let left_dock = cx.build_view(|_| Dock::new(DockPosition::Left));
+ let bottom_dock = cx.build_view(|_| Dock::new(DockPosition::Bottom));
+ let right_dock = cx.build_view(|_| Dock::new(DockPosition::Right));
+ let left_dock_buttons =
+ cx.build_view(|cx| PanelButtons::new(left_dock.clone(), weak_handle.clone(), cx));
+ let bottom_dock_buttons =
+ 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 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);
+ status_bar.add_right_item(bottom_dock_buttons, cx);
+ status_bar
+ });
- // cx.update_default_global::<DragAndDrop<Workspace>, _, _>(|drag_and_drop, _| {
- // drag_and_drop.register_container(weak_handle.clone());
- // });
+ // todo!()
+ // cx.update_default_global::<DragAndDrop<Workspace>, _, _>(|drag_and_drop, _| {
+ // drag_and_drop.register_container(weak_handle.clone());
+ // });
- // let mut active_call = None;
- // if cx.has_global::<ModelHandle<ActiveCall>>() {
- // let call = cx.global::<ModelHandle<ActiveCall>>().clone();
- // let mut subscriptions = Vec::new();
- // subscriptions.push(cx.subscribe(&call, Self::on_active_call_event));
- // active_call = Some((call, subscriptions));
- // }
+ let mut active_call = None;
+ if cx.has_global::<Model<ActiveCall>>() {
+ let call = cx.global::<Model<ActiveCall>>().clone();
+ let mut subscriptions = Vec::new();
+ subscriptions.push(cx.subscribe(&call, Self::on_active_call_event));
+ active_call = Some((call, subscriptions));
+ }
- // let subscriptions = vec![
- // cx.observe_fullscreen(|_, _, cx| cx.notify()),
- // cx.observe_window_activation(Self::on_window_activation_changed),
- // cx.observe_window_bounds(move |_, mut bounds, display, cx| {
- // // Transform fixed bounds to be stored in terms of the containing display
- // if let WindowBounds::Fixed(mut window_bounds) = bounds {
- // if let Some(screen) = cx.platform().screen_by_id(display) {
- // let screen_bounds = screen.bounds();
- // window_bounds
- // .set_origin_x(window_bounds.origin_x() - screen_bounds.origin_x());
- // window_bounds
- // .set_origin_y(window_bounds.origin_y() - screen_bounds.origin_y());
- // bounds = WindowBounds::Fixed(window_bounds);
- // }
- // }
+ let subscriptions = vec![
+ cx.observe_fullscreen(|_, _, cx| cx.notify()),
+ cx.observe_window_activation(Self::on_window_activation_changed),
+ cx.observe_window_bounds(move |_, mut bounds, display, cx| {
+ // Transform fixed bounds to be stored in terms of the containing display
+ if let WindowBounds::Fixed(mut window_bounds) = bounds {
+ if let Some(screen) = cx.platform().screen_by_id(display) {
+ let screen_bounds = screen.bounds();
+ window_bounds
+ .set_origin_x(window_bounds.origin_x() - screen_bounds.origin_x());
+ window_bounds
+ .set_origin_y(window_bounds.origin_y() - screen_bounds.origin_y());
+ bounds = WindowBounds::Fixed(window_bounds);
+ }
+ }
- // cx.background()
- // .spawn(DB.set_window_bounds(workspace_id, bounds, display))
- // .detach_and_log_err(cx);
- // }),
- // cx.observe(&left_dock, |this, _, cx| {
- // this.serialize_workspace(cx);
- // cx.notify();
- // }),
- // cx.observe(&bottom_dock, |this, _, cx| {
- // this.serialize_workspace(cx);
- // cx.notify();
- // }),
- // cx.observe(&right_dock, |this, _, cx| {
- // this.serialize_workspace(cx);
- // cx.notify();
- // }),
- // ];
-
- // cx.defer(|this, cx| this.update_window_title(cx));
- // Workspace {
- // weak_self: weak_handle.clone(),
- // modal: None,
- // zoomed: None,
- // zoomed_position: None,
- // center: PaneGroup::new(center_pane.clone()),
- // panes: vec![center_pane.clone()],
- // panes_by_item: Default::default(),
- // active_pane: center_pane.clone(),
- // last_active_center_pane: Some(center_pane.downgrade()),
- // last_active_view_id: None,
- // status_bar,
- // titlebar_item: None,
- // notifications: Default::default(),
- // left_dock,
- // bottom_dock,
- // right_dock,
- // project: project.clone(),
- // follower_states: Default::default(),
- // last_leaders_by_pane: Default::default(),
- // window_edited: false,
- // active_call,
- // database_id: workspace_id,
- // app_state,
- // _observe_current_user,
- // _apply_leader_updates,
- // _schedule_serialize: None,
- // leader_updates_tx,
- // subscriptions,
- // pane_history_timestamp,
- // }
- // }
+ cx.background()
+ .spawn(DB.set_window_bounds(workspace_id, bounds, display))
+ .detach_and_log_err(cx);
+ }),
+ cx.observe(&left_dock, |this, _, cx| {
+ this.serialize_workspace(cx);
+ cx.notify();
+ }),
+ cx.observe(&bottom_dock, |this, _, cx| {
+ this.serialize_workspace(cx);
+ cx.notify();
+ }),
+ cx.observe(&right_dock, |this, _, cx| {
+ this.serialize_workspace(cx);
+ cx.notify();
+ }),
+ ];
+
+ cx.defer(|this, cx| this.update_window_title(cx));
+ Workspace {
+ weak_self: weak_handle.clone(),
+ // modal: None,
+ // zoomed: None,
+ // zoomed_position: None,
+ center: PaneGroup::new(center_pane.clone()),
+ panes: vec![center_pane.clone()],
+ panes_by_item: Default::default(),
+ active_pane: center_pane.clone(),
+ last_active_center_pane: Some(center_pane.downgrade()),
+ // last_active_view_id: None,
+ // status_bar,
+ // titlebar_item: None,
+ notifications: Default::default(),
+ left_dock,
+ bottom_dock,
+ right_dock,
+ project: project.clone(),
+ follower_states: Default::default(),
+ last_leaders_by_pane: Default::default(),
+ window_edited: false,
+ active_call,
+ database_id: workspace_id,
+ app_state,
+ _observe_current_user,
+ _apply_leader_updates,
+ _schedule_serialize: None,
+ leader_updates_tx,
+ subscriptions,
+ pane_history_timestamp,
+ }
+ }
fn new_local(
abs_paths: Vec<PathBuf>,
@@ -832,54 +843,39 @@ impl Workspace {
});
window
} else {
- {
- let window_bounds_override = window_bounds_env_override(&cx);
- let (bounds, display) = if let Some(bounds) = window_bounds_override {
- (Some(bounds), None)
- } else {
- serialized_workspace
- .as_ref()
- .and_then(|serialized_workspace| {
- let display = serialized_workspace.display?;
- let mut bounds = serialized_workspace.bounds?;
-
- // Stored bounds are relative to the containing display.
- // So convert back to global coordinates if that screen still exists
- if let WindowBounds::Fixed(mut window_bounds) = bounds {
- if let Some(screen) = cx.platform().screen_by_id(display) {
- let screen_bounds = screen.bounds();
- window_bounds.origin.x += screen_bounds.origin.x;
- window_bounds.origin.y += screen_bounds.origin.y;
- bounds = WindowBounds::Fixed(window_bounds);
- } else {
- // Screen no longer exists. Return none here.
- return None;
- }
- }
-
- Some((bounds, display))
- })
- .unzip()
- };
-
- // Use the serialized workspace to construct the new window
- cx.open_window(
- (app_state.build_window_options)(bounds, display, cx.platform().as_ref()),
- |cx| {
- Workspace::new(
- workspace_id,
- project_handle.clone(),
- app_state.clone(),
- cx,
- )
- },
- )
- }
- };
+ let window_bounds_override = window_bounds_env_override(&cx);
+ let (bounds, display) = if let Some(bounds) = window_bounds_override {
+ (Some(bounds), None)
+ } else {
+ serialized_workspace
+ .as_ref()
+ .and_then(|serialized_workspace| {
+ let display = serialized_workspace.display?;
+ let mut bounds = serialized_workspace.bounds?;
+
+ // Stored bounds are relative to the containing display.
+ // So convert back to global coordinates if that screen still exists
+ if let WindowBounds::Fixed(mut window_bounds) = bounds {
+ let screen =
+ cx.update(|cx| cx.display_for_uuid(display)).ok()??;
+ let screen_bounds = screen.bounds();
+ window_bounds.origin.x += screen_bounds.origin.x;
+ window_bounds.origin.y += screen_bounds.origin.y;
+ bounds = WindowBounds::Fixed(window_bounds);
+ }
- // We haven't yielded the main thread since obtaining the window handle,
- // so the window exists.
- let workspace = window.root(&cx).unwrap();
+ Some((bounds, display))
+ })
+ .unzip()
+ };
+
+ // 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| {
+ Workspace::new(workspace_id, project_handle.clone(), app_state.clone(), cx)
+ })?
+ };
(app_state.initialize_workspace)(
workspace.downgrade(),
@@ -1594,7 +1590,7 @@ impl Workspace {
// pub fn toggle_modal<V, F>(
// &mut self,
// cx: &mut ViewContext<Self>,
- // add_view: F,
+ // build_view: F,
// ) -> Option<View<V>>
// where
// V: 'static + Modal,
@@ -1610,7 +1606,7 @@ impl Workspace {
// cx.focus_self();
// Some(already_open_modal)
// } else {
- // let modal = add_view(self, cx);
+ // let modal = build_view(self, cx);
// cx.subscribe(&modal, |this, _, event, cx| {
// if V::dismiss_on_event(event) {
// this.dismiss_modal(cx);
@@ -1647,12 +1643,12 @@ impl Workspace {
// }
// }
- // pub fn items<'a>(
- // &'a self,
- // cx: &'a AppContext,
- // ) -> impl 'a + Iterator<Item = &Box<dyn ItemHandle>> {
- // self.panes.iter().flat_map(|pane| pane.read(cx).items())
- // }
+ pub fn items<'a>(
+ &'a self,
+ cx: &'a AppContext,
+ ) -> impl 'a + Iterator<Item = &Box<dyn ItemHandle>> {
+ self.panes.iter().flat_map(|pane| pane.read(cx).items())
+ }
// pub fn item_of_type<T: Item>(&self, cx: &AppContext) -> Option<View<T>> {
// self.items_of_type(cx).max_by_key(|item| item.id())
@@ -1667,9 +1663,9 @@ impl Workspace {
// .flat_map(|pane| pane.read(cx).items_of_type())
// }
- // pub fn active_item(&self, cx: &AppContext) -> Option<Box<dyn ItemHandle>> {
- // self.active_pane().read(cx).active_item()
- // }
+ pub fn active_item(&self, cx: &AppContext) -> Option<Box<dyn ItemHandle>> {
+ self.active_pane().read(cx).active_item()
+ }
// fn active_project_path(&self, cx: &ViewContext<Self>) -> Option<ProjectPath> {
// self.active_item(cx).and_then(|item| item.project_path(cx))
@@ -2133,7 +2129,7 @@ impl Workspace {
// return item;
// }
- // let item = cx.add_view(|cx| T::for_project_item(self.project().clone(), project_item, cx));
+ // let item = cx.build_view(|cx| T::for_project_item(self.project().clone(), project_item, cx));
// self.add_item(Box::new(item.clone()), cx);
// item
// }
@@ -2157,7 +2153,7 @@ impl Workspace {
// return item;
// }
- // let item = cx.add_view(|cx| T::for_project_item(self.project().clone(), project_item, cx));
+ // let item = cx.build_view(|cx| T::for_project_item(self.project().clone(), project_item, cx));
// self.split_item(SplitDirection::Right, Box::new(item.clone()), cx);
// item
// }
@@ -2282,64 +2278,65 @@ impl Workspace {
// cx.notify();
// }
- // fn handle_pane_event(
- // &mut self,
- // pane: View<Pane>,
- // event: &pane::Event,
- // cx: &mut ViewContext<Self>,
- // ) {
- // match event {
- // pane::Event::AddItem { item } => item.added_to_pane(self, pane, cx),
- // pane::Event::Split(direction) => {
- // self.split_and_clone(pane, *direction, cx);
- // }
- // pane::Event::Remove => self.remove_pane(pane, cx),
- // pane::Event::ActivateItem { local } => {
- // if *local {
- // self.unfollow(&pane, cx);
- // }
- // if &pane == self.active_pane() {
- // self.active_item_path_changed(cx);
- // }
- // }
- // pane::Event::ChangeItemTitle => {
- // if pane == self.active_pane {
- // self.active_item_path_changed(cx);
- // }
- // self.update_window_edited(cx);
- // }
- // pane::Event::RemoveItem { item_id } => {
- // self.update_window_edited(cx);
- // if let hash_map::Entry::Occupied(entry) = self.panes_by_item.entry(*item_id) {
- // if entry.get().id() == pane.id() {
- // entry.remove();
- // }
- // }
- // }
- // pane::Event::Focus => {
- // self.handle_pane_focused(pane.clone(), cx);
- // }
- // pane::Event::ZoomIn => {
- // if pane == self.active_pane {
- // pane.update(cx, |pane, cx| pane.set_zoomed(true, cx));
- // if pane.read(cx).has_focus() {
- // self.zoomed = Some(pane.downgrade().into_any());
- // self.zoomed_position = None;
- // }
- // cx.notify();
- // }
- // }
- // pane::Event::ZoomOut => {
- // pane.update(cx, |pane, cx| pane.set_zoomed(false, cx));
- // if self.zoomed_position.is_none() {
- // self.zoomed = None;
- // }
- // cx.notify();
- // }
- // }
+ fn handle_pane_event(
+ &mut self,
+ pane: View<Pane>,
+ event: &pane::Event,
+ cx: &mut ViewContext<Self>,
+ ) {
+ todo!()
+ // match event {
+ // pane::Event::AddItem { item } => item.added_to_pane(self, pane, cx),
+ // pane::Event::Split(direction) => {
+ // self.split_and_clone(pane, *direction, cx);
+ // }
+ // pane::Event::Remove => self.remove_pane(pane, cx),
+ // pane::Event::ActivateItem { local } => {
+ // if *local {
+ // self.unfollow(&pane, cx);
+ // }
+ // if &pane == self.active_pane() {
+ // self.active_item_path_changed(cx);
+ // }
+ // }
+ // pane::Event::ChangeItemTitle => {
+ // if pane == self.active_pane {
+ // self.active_item_path_changed(cx);
+ // }
+ // self.update_window_edited(cx);
+ // }
+ // pane::Event::RemoveItem { item_id } => {
+ // self.update_window_edited(cx);
+ // if let hash_map::Entry::Occupied(entry) = self.panes_by_item.entry(*item_id) {
+ // if entry.get().id() == pane.id() {
+ // entry.remove();
+ // }
+ // }
+ // }
+ // pane::Event::Focus => {
+ // self.handle_pane_focused(pane.clone(), cx);
+ // }
+ // pane::Event::ZoomIn => {
+ // if pane == self.active_pane {
+ // pane.update(cx, |pane, cx| pane.set_zoomed(true, cx));
+ // if pane.read(cx).has_focus() {
+ // self.zoomed = Some(pane.downgrade().into_any());
+ // self.zoomed_position = None;
+ // }
+ // cx.notify();
+ // }
+ // }
+ // pane::Event::ZoomOut => {
+ // pane.update(cx, |pane, cx| pane.set_zoomed(false, cx));
+ // if self.zoomed_position.is_none() {
+ // self.zoomed = None;
+ // }
+ // cx.notify();
+ // }
+ // }
- // self.serialize_workspace(cx);
- // }
+ // self.serialize_workspace(cx);
+ }
// pub fn split_pane(
// &mut self,
@@ -2468,27 +2465,27 @@ impl Workspace {
// }
// }
- // pub fn panes(&self) -> &[View<Pane>] {
- // &self.panes
- // }
+ pub fn panes(&self) -> &[View<Pane>] {
+ &self.panes
+ }
- // pub fn active_pane(&self) -> &View<Pane> {
- // &self.active_pane
- // }
+ pub fn active_pane(&self) -> &View<Pane> {
+ &self.active_pane
+ }
- // fn collaborator_left(&mut self, peer_id: PeerId, cx: &mut ViewContext<Self>) {
- // self.follower_states.retain(|_, state| {
- // if state.leader_id == peer_id {
- // for item in state.items_by_leader_view_id.values() {
- // item.set_leader_peer_id(None, cx);
- // }
- // false
- // } else {
- // true
- // }
- // });
- // cx.notify();
- // }
+ fn collaborator_left(&mut self, peer_id: PeerId, cx: &mut ViewContext<Self>) {
+ self.follower_states.retain(|_, state| {
+ if state.leader_id == peer_id {
+ for item in state.items_by_leader_view_id.values() {
+ item.set_leader_peer_id(None, cx);
+ }
+ false
+ } else {
+ true
+ }
+ });
+ cx.notify();
+ }
// fn start_following(
// &mut self,
@@ -2703,60 +2700,62 @@ impl Workspace {
// self.update_window_title(cx);
// }
- // fn update_window_title(&mut self, cx: &mut ViewContext<Self>) {
- // let project = self.project().read(cx);
- // let mut title = String::new();
-
- // if let Some(path) = self.active_item(cx).and_then(|item| item.project_path(cx)) {
- // let filename = path
- // .path
- // .file_name()
- // .map(|s| s.to_string_lossy())
- // .or_else(|| {
- // Some(Cow::Borrowed(
- // project
- // .worktree_for_id(path.worktree_id, cx)?
- // .read(cx)
- // .root_name(),
- // ))
- // });
+ fn update_window_title(&mut self, cx: &mut ViewContext<Self>) {
+ let project = self.project().read(cx);
+ let mut title = String::new();
+
+ if let Some(path) = self.active_item(cx).and_then(|item| item.project_path(cx)) {
+ let filename = path
+ .path
+ .file_name()
+ .map(|s| s.to_string_lossy())
+ .or_else(|| {
+ Some(Cow::Borrowed(
+ project
+ .worktree_for_id(path.worktree_id, cx)?
+ .read(cx)
+ .root_name(),
+ ))
+ });
- // if let Some(filename) = filename {
- // title.push_str(filename.as_ref());
- // title.push_str(" — ");
- // }
- // }
+ if let Some(filename) = filename {
+ title.push_str(filename.as_ref());
+ title.push_str(" — ");
+ }
+ }
- // for (i, name) in project.worktree_root_names(cx).enumerate() {
- // if i > 0 {
- // title.push_str(", ");
- // }
- // title.push_str(name);
- // }
+ for (i, name) in project.worktree_root_names(cx).enumerate() {
+ if i > 0 {
+ title.push_str(", ");
+ }
+ title.push_str(name);
+ }
- // if title.is_empty() {
- // title = "empty project".to_string();
- // }
+ if title.is_empty() {
+ title = "empty project".to_string();
+ }
- // if project.is_remote() {
- // title.push_str(" ↙");
- // } else if project.is_shared() {
- // title.push_str(" ↗");
- // }
+ if project.is_remote() {
+ title.push_str(" ↙");
+ } else if project.is_shared() {
+ title.push_str(" ↗");
+ }
- // cx.set_window_title(&title);
- // }
+ todo!()
+ // cx.set_window_title(&title);
+ }
- // fn update_window_edited(&mut self, cx: &mut ViewContext<Self>) {
- // let is_edited = !self.project.read(cx).is_read_only()
- // && self
- // .items(cx)
- // .any(|item| item.has_conflict(cx) || item.is_dirty(cx));
- // if is_edited != self.window_edited {
- // self.window_edited = is_edited;
- // cx.set_window_edited(self.window_edited)
- // }
- // }
+ fn update_window_edited(&mut self, cx: &mut ViewContext<Self>) {
+ let is_edited = !self.project.read(cx).is_read_only()
+ && self
+ .items(cx)
+ .any(|item| item.has_conflict(cx) || item.is_dirty(cx));
+ if is_edited != self.window_edited {
+ self.window_edited = is_edited;
+ todo!()
+ // cx.set_window_edited(self.window_edited)
+ }
+ }
// fn render_disconnected_overlay(
// &self,
@@ -2875,64 +2874,64 @@ impl Workspace {
.ok();
}
- // async fn process_leader_update(
- // this: &WeakView<Self>,
- // leader_id: PeerId,
- // update: proto::UpdateFollowers,
- // cx: &mut AsyncAppContext,
- // ) -> Result<()> {
- // match update.variant.ok_or_else(|| anyhow!("invalid update"))? {
- // proto::update_followers::Variant::UpdateActiveView(update_active_view) => {
- // this.update(cx, |this, _| {
- // for (_, state) in &mut this.follower_states {
- // if state.leader_id == leader_id {
- // state.active_view_id =
- // if let Some(active_view_id) = update_active_view.id.clone() {
- // Some(ViewId::from_proto(active_view_id)?)
- // } else {
- // None
- // };
- // }
- // }
- // anyhow::Ok(())
- // })??;
- // }
- // proto::update_followers::Variant::UpdateView(update_view) => {
- // let variant = update_view
- // .variant
- // .ok_or_else(|| anyhow!("missing update view variant"))?;
- // let id = update_view
- // .id
- // .ok_or_else(|| anyhow!("missing update view id"))?;
- // let mut tasks = Vec::new();
- // this.update(cx, |this, cx| {
- // let project = this.project.clone();
- // for (_, state) in &mut this.follower_states {
- // if state.leader_id == leader_id {
- // let view_id = ViewId::from_proto(id.clone())?;
- // if let Some(item) = state.items_by_leader_view_id.get(&view_id) {
- // tasks.push(item.apply_update_proto(&project, variant.clone(), cx));
- // }
- // }
- // }
- // anyhow::Ok(())
- // })??;
- // try_join_all(tasks).await.log_err();
- // }
- // proto::update_followers::Variant::CreateView(view) => {
- // let panes = this.read_with(cx, |this, _| {
- // this.follower_states
- // .iter()
- // .filter_map(|(pane, state)| (state.leader_id == leader_id).then_some(pane))
- // .cloned()
- // .collect()
- // })?;
- // Self::add_views_from_leader(this.clone(), leader_id, panes, vec![view], cx).await?;
- // }
- // }
- // this.update(cx, |this, cx| this.leader_updated(leader_id, cx))?;
- // Ok(())
- // }
+ async fn process_leader_update(
+ this: &WeakView<Self>,
+ leader_id: PeerId,
+ update: proto::UpdateFollowers,
+ cx: &mut AsyncAppContext,
+ ) -> Result<()> {
+ match update.variant.ok_or_else(|| anyhow!("invalid update"))? {
+ proto::update_followers::Variant::UpdateActiveView(update_active_view) => {
+ this.update(cx, |this, _| {
+ for (_, state) in &mut this.follower_states {
+ if state.leader_id == leader_id {
+ state.active_view_id =
+ if let Some(active_view_id) = update_active_view.id.clone() {
+ Some(ViewId::from_proto(active_view_id)?)
+ } else {
+ None
+ };
+ }
+ }
+ anyhow::Ok(())
+ })??;
+ }
+ proto::update_followers::Variant::UpdateView(update_view) => {
+ let variant = update_view
+ .variant
+ .ok_or_else(|| anyhow!("missing update view variant"))?;
+ let id = update_view
+ .id
+ .ok_or_else(|| anyhow!("missing update view id"))?;
+ let mut tasks = Vec::new();
+ this.update(cx, |this, cx| {
+ let project = this.project.clone();
+ for (_, state) in &mut this.follower_states {
+ if state.leader_id == leader_id {
+ let view_id = ViewId::from_proto(id.clone())?;
+ if let Some(item) = state.items_by_leader_view_id.get(&view_id) {
+ tasks.push(item.apply_update_proto(&project, variant.clone(), cx));
+ }
+ }
+ }
+ anyhow::Ok(())
+ })??;
+ try_join_all(tasks).await.log_err();
+ }
+ proto::update_followers::Variant::CreateView(view) => {
+ let panes = this.read_with(cx, |this, _| {
+ this.follower_states
+ .iter()
+ .filter_map(|(pane, state)| (state.leader_id == leader_id).then_some(pane))
+ .cloned()
+ .collect()
+ })?;
+ Self::add_views_from_leader(this.clone(), leader_id, panes, vec![view], cx).await?;
+ }
+ }
+ this.update(cx, |this, cx| this.leader_updated(leader_id, cx))?;
+ Ok(())
+ }
// async fn add_views_from_leader(
// this: WeakView<Self>,