Introduce a ViewId message, identifying views across calls
This commit is contained in:
parent
43b7e16c89
commit
70efd2bebe
6 changed files with 134 additions and 38 deletions
|
@ -84,7 +84,7 @@ use std::{
|
||||||
pub use sum_tree::Bias;
|
pub use sum_tree::Bias;
|
||||||
use theme::{DiagnosticStyle, Theme};
|
use theme::{DiagnosticStyle, Theme};
|
||||||
use util::{post_inc, ResultExt, TryFutureExt};
|
use util::{post_inc, ResultExt, TryFutureExt};
|
||||||
use workspace::{ItemNavHistory, Workspace, WorkspaceId};
|
use workspace::{ItemNavHistory, ViewId, Workspace, WorkspaceId};
|
||||||
|
|
||||||
use crate::git::diff_hunk_to_display;
|
use crate::git::diff_hunk_to_display;
|
||||||
|
|
||||||
|
@ -467,6 +467,7 @@ pub struct Editor {
|
||||||
keymap_context_layers: BTreeMap<TypeId, gpui::keymap::Context>,
|
keymap_context_layers: BTreeMap<TypeId, gpui::keymap::Context>,
|
||||||
input_enabled: bool,
|
input_enabled: bool,
|
||||||
leader_replica_id: Option<u16>,
|
leader_replica_id: Option<u16>,
|
||||||
|
remote_id: Option<ViewId>,
|
||||||
hover_state: HoverState,
|
hover_state: HoverState,
|
||||||
link_go_to_definition_state: LinkGoToDefinitionState,
|
link_go_to_definition_state: LinkGoToDefinitionState,
|
||||||
_subscriptions: Vec<Subscription>,
|
_subscriptions: Vec<Subscription>,
|
||||||
|
@ -1108,6 +1109,7 @@ impl Editor {
|
||||||
keymap_context_layers: Default::default(),
|
keymap_context_layers: Default::default(),
|
||||||
input_enabled: true,
|
input_enabled: true,
|
||||||
leader_replica_id: None,
|
leader_replica_id: None,
|
||||||
|
remote_id: None,
|
||||||
hover_state: Default::default(),
|
hover_state: Default::default(),
|
||||||
link_go_to_definition_state: Default::default(),
|
link_go_to_definition_state: Default::default(),
|
||||||
_subscriptions: vec![
|
_subscriptions: vec![
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::{cell::RefCell, rc::Rc, time::Instant};
|
||||||
use drag_and_drop::DragAndDrop;
|
use drag_and_drop::DragAndDrop;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
|
use rpc::PeerId;
|
||||||
use unindent::Unindent;
|
use unindent::Unindent;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -24,7 +25,7 @@ use util::{
|
||||||
};
|
};
|
||||||
use workspace::{
|
use workspace::{
|
||||||
item::{FollowableItem, ItemHandle},
|
item::{FollowableItem, ItemHandle},
|
||||||
NavigationEntry, Pane,
|
NavigationEntry, Pane, ViewId,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
|
@ -5123,7 +5124,16 @@ async fn test_following_with_multiple_excerpts(cx: &mut gpui::TestAppContext) {
|
||||||
let mut state_message = leader.update(cx, |leader, cx| leader.to_state_proto(cx));
|
let mut state_message = leader.update(cx, |leader, cx| leader.to_state_proto(cx));
|
||||||
let follower_1 = cx
|
let follower_1 = cx
|
||||||
.update(|cx| {
|
.update(|cx| {
|
||||||
Editor::from_state_proto(pane.clone(), project.clone(), &mut state_message, cx)
|
Editor::from_state_proto(
|
||||||
|
pane.clone(),
|
||||||
|
project.clone(),
|
||||||
|
ViewId {
|
||||||
|
creator: PeerId(0),
|
||||||
|
id: 0,
|
||||||
|
},
|
||||||
|
&mut state_message,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.await
|
.await
|
||||||
|
@ -5209,7 +5219,16 @@ async fn test_following_with_multiple_excerpts(cx: &mut gpui::TestAppContext) {
|
||||||
let mut state_message = leader.update(cx, |leader, cx| leader.to_state_proto(cx));
|
let mut state_message = leader.update(cx, |leader, cx| leader.to_state_proto(cx));
|
||||||
let follower_2 = cx
|
let follower_2 = cx
|
||||||
.update(|cx| {
|
.update(|cx| {
|
||||||
Editor::from_state_proto(pane.clone(), project.clone(), &mut state_message, cx)
|
Editor::from_state_proto(
|
||||||
|
pane.clone(),
|
||||||
|
project.clone(),
|
||||||
|
ViewId {
|
||||||
|
creator: PeerId(0),
|
||||||
|
id: 0,
|
||||||
|
},
|
||||||
|
&mut state_message,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -28,24 +28,32 @@ use std::{
|
||||||
};
|
};
|
||||||
use text::Selection;
|
use text::Selection;
|
||||||
use util::{ResultExt, TryFutureExt};
|
use util::{ResultExt, TryFutureExt};
|
||||||
|
use workspace::item::FollowableItemHandle;
|
||||||
use workspace::{
|
use workspace::{
|
||||||
item::{FollowableItem, Item, ItemEvent, ItemHandle, ProjectItem},
|
item::{FollowableItem, Item, ItemEvent, ItemHandle, ProjectItem},
|
||||||
searchable::{Direction, SearchEvent, SearchableItem, SearchableItemHandle},
|
searchable::{Direction, SearchEvent, SearchableItem, SearchableItemHandle},
|
||||||
ItemId, ItemNavHistory, Pane, StatusItemView, ToolbarItemLocation, Workspace, WorkspaceId,
|
ItemId, ItemNavHistory, Pane, StatusItemView, ToolbarItemLocation, ViewId, Workspace,
|
||||||
|
WorkspaceId,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const MAX_TAB_TITLE_LEN: usize = 24;
|
pub const MAX_TAB_TITLE_LEN: usize = 24;
|
||||||
|
|
||||||
impl FollowableItem for Editor {
|
impl FollowableItem for Editor {
|
||||||
|
fn remote_id(&self) -> Option<ViewId> {
|
||||||
|
self.remote_id
|
||||||
|
}
|
||||||
|
|
||||||
fn from_state_proto(
|
fn from_state_proto(
|
||||||
pane: ViewHandle<workspace::Pane>,
|
pane: ViewHandle<workspace::Pane>,
|
||||||
project: ModelHandle<Project>,
|
project: ModelHandle<Project>,
|
||||||
|
remote_id: ViewId,
|
||||||
state: &mut Option<proto::view::Variant>,
|
state: &mut Option<proto::view::Variant>,
|
||||||
cx: &mut MutableAppContext,
|
cx: &mut MutableAppContext,
|
||||||
) -> Option<Task<Result<ViewHandle<Self>>>> {
|
) -> Option<Task<Result<ViewHandle<Self>>>> {
|
||||||
let Some(proto::view::Variant::Editor(_)) = state else { return None };
|
let Some(proto::view::Variant::Editor(_)) = state else { return None };
|
||||||
let Some(proto::view::Variant::Editor(state)) = state.take() else { unreachable!() };
|
let Some(proto::view::Variant::Editor(state)) = state.take() else { unreachable!() };
|
||||||
|
|
||||||
|
let client = project.read(cx).client();
|
||||||
let replica_id = project.read(cx).replica_id();
|
let replica_id = project.read(cx).replica_id();
|
||||||
let buffer_ids = state
|
let buffer_ids = state
|
||||||
.excerpts
|
.excerpts
|
||||||
|
@ -63,13 +71,13 @@ impl FollowableItem for Editor {
|
||||||
let mut buffers = futures::future::try_join_all(buffers).await?;
|
let mut buffers = futures::future::try_join_all(buffers).await?;
|
||||||
let editor = pane.read_with(&cx, |pane, cx| {
|
let editor = pane.read_with(&cx, |pane, cx| {
|
||||||
let mut editors = pane.items_of_type::<Self>();
|
let mut editors = pane.items_of_type::<Self>();
|
||||||
if state.singleton && buffers.len() == 1 {
|
editors.find(|editor| {
|
||||||
editors.find(|editor| {
|
editor.remote_id(&client, cx) == Some(remote_id)
|
||||||
editor.read(cx).buffer.read(cx).as_singleton().as_ref() == Some(&buffers[0])
|
|| state.singleton
|
||||||
})
|
&& buffers.len() == 1
|
||||||
} else {
|
&& editor.read(cx).buffer.read(cx).as_singleton().as_ref()
|
||||||
None
|
== Some(&buffers[0])
|
||||||
}
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let editor = editor.unwrap_or_else(|| {
|
let editor = editor.unwrap_or_else(|| {
|
||||||
|
@ -112,6 +120,7 @@ impl FollowableItem for Editor {
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.update(&mut cx, |editor, cx| {
|
editor.update(&mut cx, |editor, cx| {
|
||||||
|
editor.remote_id = Some(remote_id);
|
||||||
let buffer = editor.buffer.read(cx).read(cx);
|
let buffer = editor.buffer.read(cx).read(cx);
|
||||||
let selections = state
|
let selections = state
|
||||||
.selections
|
.selections
|
||||||
|
|
|
@ -796,7 +796,7 @@ message Follow {
|
||||||
}
|
}
|
||||||
|
|
||||||
message FollowResponse {
|
message FollowResponse {
|
||||||
optional uint64 active_view_id = 1;
|
optional ViewId active_view_id = 1;
|
||||||
repeated View views = 2;
|
repeated View views = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -824,13 +824,18 @@ message GetPrivateUserInfoResponse {
|
||||||
|
|
||||||
// Entities
|
// Entities
|
||||||
|
|
||||||
|
message ViewId {
|
||||||
|
uint32 creator = 1;
|
||||||
|
uint64 id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message UpdateActiveView {
|
message UpdateActiveView {
|
||||||
optional uint64 id = 1;
|
optional ViewId id = 1;
|
||||||
optional uint32 leader_id = 2;
|
optional uint32 leader_id = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message UpdateView {
|
message UpdateView {
|
||||||
uint64 id = 1;
|
ViewId id = 1;
|
||||||
optional uint32 leader_id = 2;
|
optional uint32 leader_id = 2;
|
||||||
|
|
||||||
oneof variant {
|
oneof variant {
|
||||||
|
@ -848,7 +853,7 @@ message UpdateView {
|
||||||
}
|
}
|
||||||
|
|
||||||
message View {
|
message View {
|
||||||
uint64 id = 1;
|
ViewId id = 1;
|
||||||
optional uint32 leader_id = 2;
|
optional uint32 leader_id = 2;
|
||||||
|
|
||||||
oneof variant {
|
oneof variant {
|
||||||
|
|
|
@ -5,12 +5,15 @@ use std::{
|
||||||
fmt,
|
fmt,
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
sync::atomic::{AtomicBool, Ordering},
|
sync::{
|
||||||
|
atomic::{AtomicBool, Ordering},
|
||||||
|
Arc,
|
||||||
|
},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use client::proto;
|
use client::{proto, Client};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
AnyViewHandle, AppContext, ElementBox, ModelHandle, MutableAppContext, Task, View, ViewContext,
|
AnyViewHandle, AppContext, ElementBox, ModelHandle, MutableAppContext, Task, View, ViewContext,
|
||||||
ViewHandle, WeakViewHandle,
|
ViewHandle, WeakViewHandle,
|
||||||
|
@ -23,7 +26,8 @@ use util::ResultExt;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
pane, persistence::model::ItemId, searchable::SearchableItemHandle, DelayedDebouncedEditAction,
|
pane, persistence::model::ItemId, searchable::SearchableItemHandle, DelayedDebouncedEditAction,
|
||||||
FollowableItemBuilders, ItemNavHistory, Pane, ToolbarItemLocation, Workspace, WorkspaceId,
|
FollowableItemBuilders, ItemNavHistory, Pane, ToolbarItemLocation, ViewId, Workspace,
|
||||||
|
WorkspaceId,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Hash)]
|
#[derive(Eq, PartialEq, Hash)]
|
||||||
|
@ -278,7 +282,9 @@ impl<T: Item> ItemHandle for ViewHandle<T> {
|
||||||
if let Some(message) = followed_item.to_state_proto(cx) {
|
if let Some(message) = followed_item.to_state_proto(cx) {
|
||||||
workspace.update_followers(
|
workspace.update_followers(
|
||||||
proto::update_followers::Variant::CreateView(proto::View {
|
proto::update_followers::Variant::CreateView(proto::View {
|
||||||
id: followed_item.id() as u64,
|
id: followed_item
|
||||||
|
.remote_id(&workspace.client, cx)
|
||||||
|
.map(|id| id.to_proto()),
|
||||||
variant: Some(message),
|
variant: Some(message),
|
||||||
leader_id: workspace.leader_for_pane(&pane).map(|id| id.0),
|
leader_id: workspace.leader_for_pane(&pane).map(|id| id.0),
|
||||||
}),
|
}),
|
||||||
|
@ -332,7 +338,9 @@ impl<T: Item> ItemHandle for ViewHandle<T> {
|
||||||
this.update_followers(
|
this.update_followers(
|
||||||
proto::update_followers::Variant::UpdateView(
|
proto::update_followers::Variant::UpdateView(
|
||||||
proto::UpdateView {
|
proto::UpdateView {
|
||||||
id: item.id() as u64,
|
id: item
|
||||||
|
.remote_id(&this.client, cx)
|
||||||
|
.map(|id| id.to_proto()),
|
||||||
variant: pending_update.borrow_mut().take(),
|
variant: pending_update.borrow_mut().take(),
|
||||||
leader_id: leader_id.map(|id| id.0),
|
leader_id: leader_id.map(|id| id.0),
|
||||||
},
|
},
|
||||||
|
@ -584,10 +592,12 @@ pub trait ProjectItem: Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FollowableItem: Item {
|
pub trait FollowableItem: Item {
|
||||||
|
fn remote_id(&self) -> Option<ViewId>;
|
||||||
fn to_state_proto(&self, cx: &AppContext) -> Option<proto::view::Variant>;
|
fn to_state_proto(&self, cx: &AppContext) -> Option<proto::view::Variant>;
|
||||||
fn from_state_proto(
|
fn from_state_proto(
|
||||||
pane: ViewHandle<Pane>,
|
pane: ViewHandle<Pane>,
|
||||||
project: ModelHandle<Project>,
|
project: ModelHandle<Project>,
|
||||||
|
id: ViewId,
|
||||||
state: &mut Option<proto::view::Variant>,
|
state: &mut Option<proto::view::Variant>,
|
||||||
cx: &mut MutableAppContext,
|
cx: &mut MutableAppContext,
|
||||||
) -> Option<Task<Result<ViewHandle<Self>>>>;
|
) -> Option<Task<Result<ViewHandle<Self>>>>;
|
||||||
|
@ -609,6 +619,7 @@ pub trait FollowableItem: Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FollowableItemHandle: ItemHandle {
|
pub trait FollowableItemHandle: ItemHandle {
|
||||||
|
fn remote_id(&self, client: &Arc<Client>, cx: &AppContext) -> Option<ViewId>;
|
||||||
fn set_leader_replica_id(&self, leader_replica_id: Option<u16>, cx: &mut MutableAppContext);
|
fn set_leader_replica_id(&self, leader_replica_id: Option<u16>, cx: &mut MutableAppContext);
|
||||||
fn to_state_proto(&self, cx: &AppContext) -> Option<proto::view::Variant>;
|
fn to_state_proto(&self, cx: &AppContext) -> Option<proto::view::Variant>;
|
||||||
fn add_event_to_update_proto(
|
fn add_event_to_update_proto(
|
||||||
|
@ -627,6 +638,15 @@ pub trait FollowableItemHandle: ItemHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: FollowableItem> FollowableItemHandle for ViewHandle<T> {
|
impl<T: FollowableItem> FollowableItemHandle for ViewHandle<T> {
|
||||||
|
fn remote_id(&self, client: &Arc<Client>, cx: &AppContext) -> Option<ViewId> {
|
||||||
|
self.read(cx).remote_id().or_else(|| {
|
||||||
|
client.peer_id().map(|creator| ViewId {
|
||||||
|
creator,
|
||||||
|
id: self.id() as u64,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn set_leader_replica_id(&self, leader_replica_id: Option<u16>, cx: &mut MutableAppContext) {
|
fn set_leader_replica_id(&self, leader_replica_id: Option<u16>, cx: &mut MutableAppContext) {
|
||||||
self.update(cx, |this, cx| {
|
self.update(cx, |this, cx| {
|
||||||
this.set_leader_replica_id(leader_replica_id, cx)
|
this.set_leader_replica_id(leader_replica_id, cx)
|
||||||
|
|
|
@ -318,6 +318,7 @@ pub fn register_project_item<I: ProjectItem>(cx: &mut MutableAppContext) {
|
||||||
type FollowableItemBuilder = fn(
|
type FollowableItemBuilder = fn(
|
||||||
ViewHandle<Pane>,
|
ViewHandle<Pane>,
|
||||||
ModelHandle<Project>,
|
ModelHandle<Project>,
|
||||||
|
ViewId,
|
||||||
&mut Option<proto::view::Variant>,
|
&mut Option<proto::view::Variant>,
|
||||||
&mut MutableAppContext,
|
&mut MutableAppContext,
|
||||||
) -> Option<Task<Result<Box<dyn FollowableItemHandle>>>>;
|
) -> Option<Task<Result<Box<dyn FollowableItemHandle>>>>;
|
||||||
|
@ -333,8 +334,8 @@ pub fn register_followable_item<I: FollowableItem>(cx: &mut MutableAppContext) {
|
||||||
builders.insert(
|
builders.insert(
|
||||||
TypeId::of::<I>(),
|
TypeId::of::<I>(),
|
||||||
(
|
(
|
||||||
|pane, project, state, cx| {
|
|pane, project, id, state, cx| {
|
||||||
I::from_state_proto(pane, project, state, cx).map(|task| {
|
I::from_state_proto(pane, project, id, state, cx).map(|task| {
|
||||||
cx.foreground()
|
cx.foreground()
|
||||||
.spawn(async move { Ok(Box::new(task.await?) as Box<_>) })
|
.spawn(async move { Ok(Box::new(task.await?) as Box<_>) })
|
||||||
})
|
})
|
||||||
|
@ -496,6 +497,12 @@ pub struct Workspace {
|
||||||
_observe_current_user: Task<()>,
|
_observe_current_user: Task<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub struct ViewId {
|
||||||
|
pub creator: PeerId,
|
||||||
|
pub id: u64,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct LeaderState {
|
struct LeaderState {
|
||||||
followers: HashSet<PeerId>,
|
followers: HashSet<PeerId>,
|
||||||
|
@ -505,8 +512,8 @@ type FollowerStatesByLeader = HashMap<PeerId, HashMap<ViewHandle<Pane>, Follower
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct FollowerState {
|
struct FollowerState {
|
||||||
active_view_id: Option<u64>,
|
active_view_id: Option<ViewId>,
|
||||||
items_by_leader_view_id: HashMap<u64, Box<dyn FollowableItemHandle>>,
|
items_by_leader_view_id: HashMap<ViewId, Box<dyn FollowableItemHandle>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Workspace {
|
impl Workspace {
|
||||||
|
@ -1454,7 +1461,11 @@ impl Workspace {
|
||||||
|
|
||||||
self.update_followers(
|
self.update_followers(
|
||||||
proto::update_followers::Variant::UpdateActiveView(proto::UpdateActiveView {
|
proto::update_followers::Variant::UpdateActiveView(proto::UpdateActiveView {
|
||||||
id: self.active_item(cx).map(|item| item.id() as u64),
|
id: self.active_item(cx).and_then(|item| {
|
||||||
|
item.to_followable_item_handle(cx)?
|
||||||
|
.remote_id(&self.client, cx)
|
||||||
|
.map(|id| id.to_proto())
|
||||||
|
}),
|
||||||
leader_id: self.leader_for_pane(&pane).map(|id| id.0),
|
leader_id: self.leader_for_pane(&pane).map(|id| id.0),
|
||||||
}),
|
}),
|
||||||
cx,
|
cx,
|
||||||
|
@ -1643,7 +1654,7 @@ impl Workspace {
|
||||||
.get_mut(&leader_id)
|
.get_mut(&leader_id)
|
||||||
.and_then(|states_by_pane| states_by_pane.get_mut(&pane))
|
.and_then(|states_by_pane| states_by_pane.get_mut(&pane))
|
||||||
.ok_or_else(|| anyhow!("following interrupted"))?;
|
.ok_or_else(|| anyhow!("following interrupted"))?;
|
||||||
state.active_view_id = response.active_view_id;
|
state.active_view_id = response.active_view_id.map(ViewId::from_proto);
|
||||||
Ok::<_, anyhow::Error>(())
|
Ok::<_, anyhow::Error>(())
|
||||||
})?;
|
})?;
|
||||||
Self::add_views_from_leader(
|
Self::add_views_from_leader(
|
||||||
|
@ -1891,14 +1902,18 @@ impl Workspace {
|
||||||
mut cx: AsyncAppContext,
|
mut cx: AsyncAppContext,
|
||||||
) -> Result<proto::FollowResponse> {
|
) -> Result<proto::FollowResponse> {
|
||||||
this.update(&mut cx, |this, cx| {
|
this.update(&mut cx, |this, cx| {
|
||||||
|
let client = &this.client;
|
||||||
this.leader_state
|
this.leader_state
|
||||||
.followers
|
.followers
|
||||||
.insert(envelope.original_sender_id()?);
|
.insert(envelope.original_sender_id()?);
|
||||||
|
|
||||||
let active_view_id = this
|
let active_view_id = this.active_item(cx).and_then(|i| {
|
||||||
.active_item(cx)
|
Some(
|
||||||
.and_then(|i| i.to_followable_item_handle(cx))
|
i.to_followable_item_handle(cx)?
|
||||||
.map(|i| i.id() as u64);
|
.remote_id(client, cx)?
|
||||||
|
.to_proto(),
|
||||||
|
)
|
||||||
|
});
|
||||||
Ok(proto::FollowResponse {
|
Ok(proto::FollowResponse {
|
||||||
active_view_id,
|
active_view_id,
|
||||||
views: this
|
views: this
|
||||||
|
@ -1909,11 +1924,11 @@ impl Workspace {
|
||||||
pane.read(cx).items().filter_map({
|
pane.read(cx).items().filter_map({
|
||||||
let cx = &cx;
|
let cx = &cx;
|
||||||
move |item| {
|
move |item| {
|
||||||
let id = item.id() as u64;
|
|
||||||
let item = item.to_followable_item_handle(cx)?;
|
let item = item.to_followable_item_handle(cx)?;
|
||||||
|
let id = item.remote_id(client, cx)?.to_proto();
|
||||||
let variant = item.to_state_proto(cx)?;
|
let variant = item.to_state_proto(cx)?;
|
||||||
Some(proto::View {
|
Some(proto::View {
|
||||||
id,
|
id: Some(id),
|
||||||
leader_id,
|
leader_id,
|
||||||
variant: Some(variant),
|
variant: Some(variant),
|
||||||
})
|
})
|
||||||
|
@ -1964,7 +1979,8 @@ impl Workspace {
|
||||||
this.update(cx, |this, _| {
|
this.update(cx, |this, _| {
|
||||||
if let Some(state) = this.follower_states_by_leader.get_mut(&leader_id) {
|
if let Some(state) = this.follower_states_by_leader.get_mut(&leader_id) {
|
||||||
for state in state.values_mut() {
|
for state in state.values_mut() {
|
||||||
state.active_view_id = update_active_view.id;
|
state.active_view_id =
|
||||||
|
update_active_view.id.clone().map(ViewId::from_proto);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1973,12 +1989,18 @@ impl Workspace {
|
||||||
let variant = update_view
|
let variant = update_view
|
||||||
.variant
|
.variant
|
||||||
.ok_or_else(|| anyhow!("missing 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();
|
let mut tasks = Vec::new();
|
||||||
this.update(cx, |this, cx| {
|
this.update(cx, |this, cx| {
|
||||||
let project = this.project.clone();
|
let project = this.project.clone();
|
||||||
if let Some(state) = this.follower_states_by_leader.get_mut(&leader_id) {
|
if let Some(state) = this.follower_states_by_leader.get_mut(&leader_id) {
|
||||||
for state in state.values_mut() {
|
for state in state.values_mut() {
|
||||||
if let Some(item) = state.items_by_leader_view_id.get(&update_view.id) {
|
if let Some(item) = state
|
||||||
|
.items_by_leader_view_id
|
||||||
|
.get(&ViewId::from_proto(id.clone()))
|
||||||
|
{
|
||||||
tasks.push(item.apply_update_proto(&project, variant.clone(), cx));
|
tasks.push(item.apply_update_proto(&project, variant.clone(), cx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2031,16 +2053,19 @@ impl Workspace {
|
||||||
let mut item_tasks = Vec::new();
|
let mut item_tasks = Vec::new();
|
||||||
let mut leader_view_ids = Vec::new();
|
let mut leader_view_ids = Vec::new();
|
||||||
for view in &views {
|
for view in &views {
|
||||||
|
let Some(id) = &view.id else { continue };
|
||||||
|
let id = ViewId::from_proto(id.clone());
|
||||||
let mut variant = view.variant.clone();
|
let mut variant = view.variant.clone();
|
||||||
if variant.is_none() {
|
if variant.is_none() {
|
||||||
Err(anyhow!("missing variant"))?;
|
Err(anyhow!("missing variant"))?;
|
||||||
}
|
}
|
||||||
for build_item in &item_builders {
|
for build_item in &item_builders {
|
||||||
let task =
|
let task = cx.update(|cx| {
|
||||||
cx.update(|cx| build_item(pane.clone(), project.clone(), &mut variant, cx));
|
build_item(pane.clone(), project.clone(), id, &mut variant, cx)
|
||||||
|
});
|
||||||
if let Some(task) = task {
|
if let Some(task) = task {
|
||||||
item_tasks.push(task);
|
item_tasks.push(task);
|
||||||
leader_view_ids.push(view.id);
|
leader_view_ids.push(id);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
assert!(variant.is_some());
|
assert!(variant.is_some());
|
||||||
|
@ -2561,6 +2586,22 @@ impl View for Workspace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ViewId {
|
||||||
|
pub(crate) fn from_proto(message: proto::ViewId) -> Self {
|
||||||
|
Self {
|
||||||
|
creator: PeerId(message.creator),
|
||||||
|
id: message.id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn to_proto(&self) -> proto::ViewId {
|
||||||
|
proto::ViewId {
|
||||||
|
creator: self.creator.0,
|
||||||
|
id: self.id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait WorkspaceHandle {
|
pub trait WorkspaceHandle {
|
||||||
fn file_project_paths(&self, cx: &AppContext) -> Vec<ProjectPath>;
|
fn file_project_paths(&self, cx: &AppContext) -> Vec<ProjectPath>;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue