mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-26 02:37:05 +00:00
WIP
This commit is contained in:
parent
eda06ee408
commit
0fdaa1d715
10 changed files with 245 additions and 58 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1629,6 +1629,7 @@ dependencies = [
|
|||
"postage",
|
||||
"project",
|
||||
"rand 0.8.3",
|
||||
"rpc",
|
||||
"serde",
|
||||
"smallvec",
|
||||
"smol",
|
||||
|
|
|
@ -181,7 +181,7 @@ impl Entity for Channel {
|
|||
|
||||
impl Channel {
|
||||
pub fn init(rpc: &Arc<Client>) {
|
||||
rpc.add_entity_message_handler(Self::handle_message_sent);
|
||||
rpc.add_model_message_handler(Self::handle_message_sent);
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
|
|
|
@ -13,8 +13,8 @@ use async_tungstenite::tungstenite::{
|
|||
};
|
||||
use futures::{future::LocalBoxFuture, FutureExt, StreamExt};
|
||||
use gpui::{
|
||||
action, AnyModelHandle, AnyWeakModelHandle, AsyncAppContext, Entity, ModelContext, ModelHandle,
|
||||
MutableAppContext, Task,
|
||||
action, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AnyWeakViewHandle, AsyncAppContext,
|
||||
Entity, ModelContext, ModelHandle, MutableAppContext, Task, View, ViewContext, ViewHandle,
|
||||
};
|
||||
use http::HttpClient;
|
||||
use lazy_static::lazy_static;
|
||||
|
@ -139,16 +139,16 @@ struct ClientState {
|
|||
entity_id_extractors: HashMap<TypeId, Box<dyn Send + Sync + Fn(&dyn AnyTypedEnvelope) -> u64>>,
|
||||
_reconnect_task: Option<Task<()>>,
|
||||
reconnect_interval: Duration,
|
||||
models_by_entity_type_and_remote_id: HashMap<(TypeId, u64), AnyWeakModelHandle>,
|
||||
entities_by_type_and_remote_id: HashMap<(TypeId, u64), AnyWeakEntityHandle>,
|
||||
models_by_message_type: HashMap<TypeId, AnyWeakModelHandle>,
|
||||
model_types_by_message_type: HashMap<TypeId, TypeId>,
|
||||
entity_types_by_message_type: HashMap<TypeId, TypeId>,
|
||||
message_handlers: HashMap<
|
||||
TypeId,
|
||||
Arc<
|
||||
dyn Send
|
||||
+ Sync
|
||||
+ Fn(
|
||||
AnyModelHandle,
|
||||
AnyEntityHandle,
|
||||
Box<dyn AnyTypedEnvelope>,
|
||||
AsyncAppContext,
|
||||
) -> LocalBoxFuture<'static, Result<()>>,
|
||||
|
@ -156,6 +156,16 @@ struct ClientState {
|
|||
>,
|
||||
}
|
||||
|
||||
enum AnyWeakEntityHandle {
|
||||
Model(AnyWeakModelHandle),
|
||||
View(AnyWeakViewHandle),
|
||||
}
|
||||
|
||||
enum AnyEntityHandle {
|
||||
Model(AnyModelHandle),
|
||||
View(AnyViewHandle),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Credentials {
|
||||
pub user_id: u64,
|
||||
|
@ -171,8 +181,8 @@ impl Default for ClientState {
|
|||
_reconnect_task: None,
|
||||
reconnect_interval: Duration::from_secs(5),
|
||||
models_by_message_type: Default::default(),
|
||||
models_by_entity_type_and_remote_id: Default::default(),
|
||||
model_types_by_message_type: Default::default(),
|
||||
entities_by_type_and_remote_id: Default::default(),
|
||||
entity_types_by_message_type: Default::default(),
|
||||
message_handlers: Default::default(),
|
||||
}
|
||||
}
|
||||
|
@ -195,13 +205,13 @@ impl Drop for Subscription {
|
|||
Subscription::Entity { client, id } => {
|
||||
if let Some(client) = client.upgrade() {
|
||||
let mut state = client.state.write();
|
||||
let _ = state.models_by_entity_type_and_remote_id.remove(id);
|
||||
let _ = state.entities_by_type_and_remote_id.remove(id);
|
||||
}
|
||||
}
|
||||
Subscription::Message { client, id } => {
|
||||
if let Some(client) = client.upgrade() {
|
||||
let mut state = client.state.write();
|
||||
let _ = state.model_types_by_message_type.remove(id);
|
||||
let _ = state.entity_types_by_message_type.remove(id);
|
||||
let _ = state.message_handlers.remove(id);
|
||||
}
|
||||
}
|
||||
|
@ -239,7 +249,7 @@ impl Client {
|
|||
state._reconnect_task.take();
|
||||
state.message_handlers.clear();
|
||||
state.models_by_message_type.clear();
|
||||
state.models_by_entity_type_and_remote_id.clear();
|
||||
state.entities_by_type_and_remote_id.clear();
|
||||
state.entity_id_extractors.clear();
|
||||
self.peer.reset();
|
||||
}
|
||||
|
@ -313,6 +323,23 @@ impl Client {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn add_view_for_remote_entity<T: View>(
|
||||
self: &Arc<Self>,
|
||||
remote_id: u64,
|
||||
cx: &mut ViewContext<T>,
|
||||
) -> Subscription {
|
||||
let handle = AnyViewHandle::from(cx.handle());
|
||||
let mut state = self.state.write();
|
||||
let id = (TypeId::of::<T>(), remote_id);
|
||||
state
|
||||
.entities_by_type_and_remote_id
|
||||
.insert(id, AnyWeakEntityHandle::View(handle.downgrade()));
|
||||
Subscription::Entity {
|
||||
client: Arc::downgrade(self),
|
||||
id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_model_for_remote_entity<T: Entity>(
|
||||
self: &Arc<Self>,
|
||||
remote_id: u64,
|
||||
|
@ -322,8 +349,8 @@ impl Client {
|
|||
let mut state = self.state.write();
|
||||
let id = (TypeId::of::<T>(), remote_id);
|
||||
state
|
||||
.models_by_entity_type_and_remote_id
|
||||
.insert(id, handle.downgrade());
|
||||
.entities_by_type_and_remote_id
|
||||
.insert(id, AnyWeakEntityHandle::Model(handle.downgrade()));
|
||||
Subscription::Entity {
|
||||
client: Arc::downgrade(self),
|
||||
id,
|
||||
|
@ -355,6 +382,11 @@ impl Client {
|
|||
let prev_handler = state.message_handlers.insert(
|
||||
message_type_id,
|
||||
Arc::new(move |handle, envelope, cx| {
|
||||
let handle = if let AnyEntityHandle::Model(handle) = handle {
|
||||
handle
|
||||
} else {
|
||||
unreachable!();
|
||||
};
|
||||
let model = handle.downcast::<E>().unwrap();
|
||||
let envelope = envelope.into_any().downcast::<TypedEnvelope<M>>().unwrap();
|
||||
if let Some(client) = client.upgrade() {
|
||||
|
@ -374,7 +406,60 @@ impl Client {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn add_entity_message_handler<M, E, H, F>(self: &Arc<Self>, handler: H)
|
||||
pub fn add_view_message_handler<M, E, H, F>(self: &Arc<Self>, handler: H)
|
||||
where
|
||||
M: EntityMessage,
|
||||
E: View,
|
||||
H: 'static
|
||||
+ Send
|
||||
+ Sync
|
||||
+ Fn(ViewHandle<E>, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
|
||||
F: 'static + Future<Output = Result<()>>,
|
||||
{
|
||||
let entity_type_id = TypeId::of::<E>();
|
||||
let message_type_id = TypeId::of::<M>();
|
||||
|
||||
let client = Arc::downgrade(self);
|
||||
let mut state = self.state.write();
|
||||
state
|
||||
.entity_types_by_message_type
|
||||
.insert(message_type_id, entity_type_id);
|
||||
state
|
||||
.entity_id_extractors
|
||||
.entry(message_type_id)
|
||||
.or_insert_with(|| {
|
||||
Box::new(|envelope| {
|
||||
let envelope = envelope
|
||||
.as_any()
|
||||
.downcast_ref::<TypedEnvelope<M>>()
|
||||
.unwrap();
|
||||
envelope.payload.remote_entity_id()
|
||||
})
|
||||
});
|
||||
|
||||
let prev_handler = state.message_handlers.insert(
|
||||
message_type_id,
|
||||
Arc::new(move |handle, envelope, cx| {
|
||||
let handle = if let AnyEntityHandle::View(handle) = handle {
|
||||
handle
|
||||
} else {
|
||||
unreachable!();
|
||||
};
|
||||
let model = handle.downcast::<E>().unwrap();
|
||||
let envelope = envelope.into_any().downcast::<TypedEnvelope<M>>().unwrap();
|
||||
if let Some(client) = client.upgrade() {
|
||||
handler(model, *envelope, client.clone(), cx).boxed_local()
|
||||
} else {
|
||||
async move { Ok(()) }.boxed_local()
|
||||
}
|
||||
}),
|
||||
);
|
||||
if prev_handler.is_some() {
|
||||
panic!("registered handler for the same message twice");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_model_message_handler<M, E, H, F>(self: &Arc<Self>, handler: H)
|
||||
where
|
||||
M: EntityMessage,
|
||||
E: Entity,
|
||||
|
@ -390,7 +475,7 @@ impl Client {
|
|||
let client = Arc::downgrade(self);
|
||||
let mut state = self.state.write();
|
||||
state
|
||||
.model_types_by_message_type
|
||||
.entity_types_by_message_type
|
||||
.insert(message_type_id, model_type_id);
|
||||
state
|
||||
.entity_id_extractors
|
||||
|
@ -408,9 +493,15 @@ impl Client {
|
|||
let prev_handler = state.message_handlers.insert(
|
||||
message_type_id,
|
||||
Arc::new(move |handle, envelope, cx| {
|
||||
let model = handle.downcast::<E>().unwrap();
|
||||
let envelope = envelope.into_any().downcast::<TypedEnvelope<M>>().unwrap();
|
||||
if let Some(client) = client.upgrade() {
|
||||
let model = handle.downcast::<E>().unwrap();
|
||||
let envelope = envelope.into_any().downcast::<TypedEnvelope<M>>().unwrap();
|
||||
let handle = if let AnyEntityHandle::Model(handle) = handle {
|
||||
handle
|
||||
} else {
|
||||
unreachable!();
|
||||
};
|
||||
|
||||
handler(model, *envelope, client.clone(), cx).boxed_local()
|
||||
} else {
|
||||
async move { Ok(()) }.boxed_local()
|
||||
|
@ -432,7 +523,7 @@ impl Client {
|
|||
+ Fn(ModelHandle<E>, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
|
||||
F: 'static + Future<Output = Result<M::Response>>,
|
||||
{
|
||||
self.add_entity_message_handler(move |model, envelope, client, cx| {
|
||||
self.add_model_message_handler(move |model, envelope, client, cx| {
|
||||
let receipt = envelope.receipt();
|
||||
let response = handler(model, envelope, client.clone(), cx);
|
||||
async move {
|
||||
|
@ -561,24 +652,26 @@ impl Client {
|
|||
.models_by_message_type
|
||||
.get(&payload_type_id)
|
||||
.and_then(|model| model.upgrade(&cx))
|
||||
.map(AnyEntityHandle::Model)
|
||||
.or_else(|| {
|
||||
let model_type_id =
|
||||
*state.model_types_by_message_type.get(&payload_type_id)?;
|
||||
let entity_type_id =
|
||||
*state.entity_types_by_message_type.get(&payload_type_id)?;
|
||||
let entity_id = state
|
||||
.entity_id_extractors
|
||||
.get(&message.payload_type_id())
|
||||
.map(|extract_entity_id| {
|
||||
(extract_entity_id)(message.as_ref())
|
||||
})?;
|
||||
let model = state
|
||||
.models_by_entity_type_and_remote_id
|
||||
.get(&(model_type_id, entity_id))?;
|
||||
if let Some(model) = model.upgrade(&cx) {
|
||||
Some(model)
|
||||
|
||||
let entity = state
|
||||
.entities_by_type_and_remote_id
|
||||
.get(&(entity_type_id, entity_id))?;
|
||||
if let Some(entity) = entity.upgrade(&cx) {
|
||||
Some(entity)
|
||||
} else {
|
||||
state
|
||||
.models_by_entity_type_and_remote_id
|
||||
.remove(&(model_type_id, entity_id));
|
||||
.entities_by_type_and_remote_id
|
||||
.remove(&(entity_type_id, entity_id));
|
||||
None
|
||||
}
|
||||
});
|
||||
|
@ -891,6 +984,15 @@ impl Client {
|
|||
}
|
||||
}
|
||||
|
||||
impl AnyWeakEntityHandle {
|
||||
fn upgrade(&self, cx: &AsyncAppContext) -> Option<AnyEntityHandle> {
|
||||
match self {
|
||||
AnyWeakEntityHandle::Model(handle) => handle.upgrade(cx).map(AnyEntityHandle::Model),
|
||||
AnyWeakEntityHandle::View(handle) => handle.upgrade(cx).map(AnyEntityHandle::View),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_credentials_from_keychain(cx: &AsyncAppContext) -> Option<Credentials> {
|
||||
if IMPERSONATE_LOGIN.is_some() {
|
||||
return None;
|
||||
|
@ -994,7 +1096,7 @@ mod tests {
|
|||
|
||||
let (done_tx1, mut done_rx1) = smol::channel::unbounded();
|
||||
let (done_tx2, mut done_rx2) = smol::channel::unbounded();
|
||||
client.add_entity_message_handler(
|
||||
client.add_model_message_handler(
|
||||
move |model: ModelHandle<Model>, _: TypedEnvelope<proto::UnshareProject>, _, cx| {
|
||||
match model.read_with(&cx, |model, _| model.id) {
|
||||
1 => done_tx1.try_send(()).unwrap(),
|
||||
|
|
|
@ -27,6 +27,7 @@ gpui = { path = "../gpui" }
|
|||
language = { path = "../language" }
|
||||
lsp = { path = "../lsp" }
|
||||
project = { path = "../project" }
|
||||
rpc = { path = "../rpc" }
|
||||
snippet = { path = "../snippet" }
|
||||
sum_tree = { path = "../sum_tree" }
|
||||
theme = { path = "../theme" }
|
||||
|
|
|
@ -6,13 +6,34 @@ use gpui::{
|
|||
};
|
||||
use language::{Bias, Buffer, Diagnostic, File as _};
|
||||
use project::{File, Project, ProjectEntryId, ProjectPath};
|
||||
use std::fmt::Write;
|
||||
use std::path::PathBuf;
|
||||
use rpc::proto;
|
||||
use std::{fmt::Write, path::PathBuf};
|
||||
use text::{Point, Selection};
|
||||
use util::ResultExt;
|
||||
use workspace::{Item, ItemHandle, ItemNavHistory, ProjectItem, Settings, StatusItemView};
|
||||
use workspace::{
|
||||
FollowedItem, Item, ItemHandle, ItemNavHistory, ProjectItem, Settings, StatusItemView,
|
||||
};
|
||||
|
||||
impl FollowedItem for Editor {
|
||||
fn for_state_message(
|
||||
pane: ViewHandle<workspace::Pane>,
|
||||
project: ModelHandle<Project>,
|
||||
state: &mut Option<proto::view::Variant>,
|
||||
cx: &mut gpui::MutableAppContext,
|
||||
) -> Option<Task<Result<Box<dyn ItemHandle>>>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn to_state_message(&self, cx: &mut gpui::MutableAppContext) -> proto::view::Variant {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Item for Editor {
|
||||
fn as_followed(&self) -> Option<&dyn FollowedItem> {
|
||||
Some(self)
|
||||
}
|
||||
|
||||
fn navigate(&mut self, data: Box<dyn std::any::Any>, cx: &mut ViewContext<Self>) {
|
||||
if let Some(data) = data.downcast_ref::<NavigationData>() {
|
||||
let buffer = self.buffer.read(cx).read(cx);
|
||||
|
|
|
@ -124,6 +124,7 @@ pub enum Event {
|
|||
DiskBasedDiagnosticsUpdated,
|
||||
DiskBasedDiagnosticsFinished,
|
||||
DiagnosticsUpdated(ProjectPath),
|
||||
RemoteIdChanged(Option<u64>),
|
||||
}
|
||||
|
||||
enum LanguageServerEvent {
|
||||
|
@ -253,19 +254,19 @@ impl ProjectEntryId {
|
|||
|
||||
impl Project {
|
||||
pub fn init(client: &Arc<Client>) {
|
||||
client.add_entity_message_handler(Self::handle_add_collaborator);
|
||||
client.add_entity_message_handler(Self::handle_buffer_reloaded);
|
||||
client.add_entity_message_handler(Self::handle_buffer_saved);
|
||||
client.add_entity_message_handler(Self::handle_start_language_server);
|
||||
client.add_entity_message_handler(Self::handle_update_language_server);
|
||||
client.add_entity_message_handler(Self::handle_remove_collaborator);
|
||||
client.add_entity_message_handler(Self::handle_register_worktree);
|
||||
client.add_entity_message_handler(Self::handle_unregister_worktree);
|
||||
client.add_entity_message_handler(Self::handle_unshare_project);
|
||||
client.add_entity_message_handler(Self::handle_update_buffer_file);
|
||||
client.add_entity_message_handler(Self::handle_update_buffer);
|
||||
client.add_entity_message_handler(Self::handle_update_diagnostic_summary);
|
||||
client.add_entity_message_handler(Self::handle_update_worktree);
|
||||
client.add_model_message_handler(Self::handle_add_collaborator);
|
||||
client.add_model_message_handler(Self::handle_buffer_reloaded);
|
||||
client.add_model_message_handler(Self::handle_buffer_saved);
|
||||
client.add_model_message_handler(Self::handle_start_language_server);
|
||||
client.add_model_message_handler(Self::handle_update_language_server);
|
||||
client.add_model_message_handler(Self::handle_remove_collaborator);
|
||||
client.add_model_message_handler(Self::handle_register_worktree);
|
||||
client.add_model_message_handler(Self::handle_unregister_worktree);
|
||||
client.add_model_message_handler(Self::handle_unshare_project);
|
||||
client.add_model_message_handler(Self::handle_update_buffer_file);
|
||||
client.add_model_message_handler(Self::handle_update_buffer);
|
||||
client.add_model_message_handler(Self::handle_update_diagnostic_summary);
|
||||
client.add_model_message_handler(Self::handle_update_worktree);
|
||||
client.add_entity_request_handler(Self::handle_apply_additional_edits_for_completion);
|
||||
client.add_entity_request_handler(Self::handle_apply_code_action);
|
||||
client.add_entity_request_handler(Self::handle_format_buffers);
|
||||
|
@ -566,6 +567,7 @@ impl Project {
|
|||
self.subscriptions
|
||||
.push(self.client.add_model_for_remote_entity(remote_id, cx));
|
||||
}
|
||||
cx.emit(Event::RemoteIdChanged(remote_id))
|
||||
}
|
||||
|
||||
pub fn remote_id(&self) -> Option<u64> {
|
||||
|
|
|
@ -4563,6 +4563,9 @@ mod tests {
|
|||
|
||||
Channel::init(&client);
|
||||
Project::init(&client);
|
||||
cx.update(|cx| {
|
||||
workspace::init(&client, cx);
|
||||
});
|
||||
|
||||
let peer_id = PeerId(connection_id_rx.next().await.unwrap().0);
|
||||
let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http, cx));
|
||||
|
|
|
@ -7,7 +7,9 @@ pub mod sidebar;
|
|||
mod status_bar;
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use client::{proto, Authenticate, ChannelList, Client, PeerId, User, UserStore};
|
||||
use client::{
|
||||
proto, Authenticate, ChannelList, Client, PeerId, Subscription, TypedEnvelope, User, UserStore,
|
||||
};
|
||||
use clock::ReplicaId;
|
||||
use collections::HashMap;
|
||||
use gpui::{
|
||||
|
@ -18,9 +20,9 @@ use gpui::{
|
|||
json::{self, to_string_pretty, ToJson},
|
||||
keymap::Binding,
|
||||
platform::{CursorStyle, WindowOptions},
|
||||
AnyModelHandle, AnyViewHandle, AppContext, ClipboardItem, Entity, ImageData, ModelHandle,
|
||||
MutableAppContext, PathPromptOptions, PromptLevel, RenderContext, Task, View, ViewContext,
|
||||
ViewHandle, WeakViewHandle,
|
||||
AnyModelHandle, AnyViewHandle, AppContext, AsyncAppContext, ClipboardItem, Entity, ImageData,
|
||||
ModelHandle, MutableAppContext, PathPromptOptions, PromptLevel, RenderContext, Task, View,
|
||||
ViewContext, ViewHandle, WeakViewHandle,
|
||||
};
|
||||
use language::LanguageRegistry;
|
||||
use log::error;
|
||||
|
@ -64,7 +66,7 @@ action!(JoinProject, JoinProjectParams);
|
|||
action!(Save);
|
||||
action!(DebugElements);
|
||||
|
||||
pub fn init(cx: &mut MutableAppContext) {
|
||||
pub fn init(client: &Arc<Client>, cx: &mut MutableAppContext) {
|
||||
pane::init(cx);
|
||||
menu::init(cx);
|
||||
|
||||
|
@ -108,6 +110,9 @@ pub fn init(cx: &mut MutableAppContext) {
|
|||
None,
|
||||
),
|
||||
]);
|
||||
|
||||
client.add_entity_request_handler(Workspace::handle_follow);
|
||||
client.add_model_message_handler(Workspace::handle_unfollow);
|
||||
}
|
||||
|
||||
pub fn register_project_item<I: ProjectItem>(cx: &mut MutableAppContext) {
|
||||
|
@ -119,7 +124,7 @@ pub fn register_project_item<I: ProjectItem>(cx: &mut MutableAppContext) {
|
|||
});
|
||||
}
|
||||
|
||||
pub fn register_followed_item<I: FollowedItem>(cx: &mut MutableAppContext) {
|
||||
pub fn register_followed_item<I: FollowedItem + Item>(cx: &mut MutableAppContext) {
|
||||
cx.update_default_global(|builders: &mut FollowedItemBuilders, _| {
|
||||
builders.push(I::for_state_message)
|
||||
});
|
||||
|
@ -153,6 +158,9 @@ pub struct JoinProjectParams {
|
|||
}
|
||||
|
||||
pub trait Item: View {
|
||||
fn as_followed(&self) -> Option<&dyn FollowedItem> {
|
||||
None
|
||||
}
|
||||
fn deactivated(&mut self, _: &mut ViewContext<Self>) {}
|
||||
fn navigate(&mut self, _: Box<dyn Any>, _: &mut ViewContext<Self>) {}
|
||||
fn tab_content(&self, style: &theme::Tab, cx: &AppContext) -> ElementBox;
|
||||
|
@ -217,15 +225,17 @@ pub trait ProjectItem: Item {
|
|||
) -> Self;
|
||||
}
|
||||
|
||||
pub trait FollowedItem: Item {
|
||||
type UpdateMessage;
|
||||
|
||||
pub trait FollowedItem {
|
||||
fn for_state_message(
|
||||
pane: ViewHandle<Pane>,
|
||||
project: ModelHandle<Project>,
|
||||
state: &mut Option<proto::view::Variant>,
|
||||
cx: &mut MutableAppContext,
|
||||
) -> Option<Task<Result<Box<dyn ItemHandle>>>>;
|
||||
) -> Option<Task<Result<Box<dyn ItemHandle>>>>
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
fn to_state_message(&self, cx: &mut MutableAppContext) -> proto::view::Variant;
|
||||
}
|
||||
|
||||
pub trait ItemHandle: 'static {
|
||||
|
@ -459,6 +469,7 @@ pub struct Workspace {
|
|||
weak_self: WeakViewHandle<Self>,
|
||||
client: Arc<Client>,
|
||||
user_store: ModelHandle<client::UserStore>,
|
||||
remote_entity_subscription: Option<Subscription>,
|
||||
fs: Arc<dyn Fs>,
|
||||
modal: Option<AnyViewHandle>,
|
||||
center: PaneGroup,
|
||||
|
@ -481,6 +492,17 @@ impl Workspace {
|
|||
})
|
||||
.detach();
|
||||
|
||||
cx.subscribe(¶ms.project, move |this, project, event, cx| {
|
||||
if let project::Event::RemoteIdChanged(remote_id) = event {
|
||||
this.project_remote_id_changed(*remote_id, cx);
|
||||
}
|
||||
if project.read(cx).is_read_only() {
|
||||
cx.blur();
|
||||
}
|
||||
cx.notify()
|
||||
})
|
||||
.detach();
|
||||
|
||||
let pane = cx.add_view(|_| Pane::new());
|
||||
let pane_id = pane.id();
|
||||
cx.observe(&pane, move |me, _, cx| {
|
||||
|
@ -517,7 +539,7 @@ impl Workspace {
|
|||
|
||||
cx.emit_global(WorkspaceCreated(weak_self.clone()));
|
||||
|
||||
Workspace {
|
||||
let mut this = Workspace {
|
||||
modal: None,
|
||||
weak_self,
|
||||
center: PaneGroup::new(pane.clone()),
|
||||
|
@ -525,13 +547,16 @@ impl Workspace {
|
|||
active_pane: pane.clone(),
|
||||
status_bar,
|
||||
client: params.client.clone(),
|
||||
remote_entity_subscription: None,
|
||||
user_store: params.user_store.clone(),
|
||||
fs: params.fs.clone(),
|
||||
left_sidebar: Sidebar::new(Side::Left),
|
||||
right_sidebar: Sidebar::new(Side::Right),
|
||||
project: params.project.clone(),
|
||||
_observe_current_user,
|
||||
}
|
||||
};
|
||||
this.project_remote_id_changed(this.project.read(cx).remote_id(), cx);
|
||||
this
|
||||
}
|
||||
|
||||
pub fn weak_handle(&self) -> WeakViewHandle<Self> {
|
||||
|
@ -1008,6 +1033,15 @@ impl Workspace {
|
|||
});
|
||||
}
|
||||
|
||||
fn project_remote_id_changed(&mut self, remote_id: Option<u64>, cx: &mut ViewContext<Self>) {
|
||||
if let Some(remote_id) = remote_id {
|
||||
self.remote_entity_subscription =
|
||||
Some(self.client.add_view_for_remote_entity(remote_id, cx));
|
||||
} else {
|
||||
self.remote_entity_subscription.take();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn follow(&mut self, leader_id: PeerId, cx: &mut ViewContext<Self>) -> Task<Result<()>> {
|
||||
if let Some(project_id) = self.project.read(cx).remote_id() {
|
||||
let request = self.client.request(proto::Follow {
|
||||
|
@ -1271,6 +1305,29 @@ impl Workspace {
|
|||
None
|
||||
}
|
||||
}
|
||||
|
||||
// RPC handlers
|
||||
|
||||
async fn handle_follow(
|
||||
this: ViewHandle<Self>,
|
||||
envelope: TypedEnvelope<proto::Follow>,
|
||||
_: Arc<Client>,
|
||||
cx: AsyncAppContext,
|
||||
) -> Result<proto::FollowResponse> {
|
||||
Ok(proto::FollowResponse {
|
||||
current_view_id: 0,
|
||||
views: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
async fn handle_unfollow(
|
||||
this: ViewHandle<Self>,
|
||||
envelope: TypedEnvelope<proto::Unfollow>,
|
||||
_: Arc<Client>,
|
||||
cx: AsyncAppContext,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Entity for Workspace {
|
||||
|
|
|
@ -69,7 +69,7 @@ fn main() {
|
|||
project::Project::init(&client);
|
||||
client::Channel::init(&client);
|
||||
client::init(client.clone(), cx);
|
||||
workspace::init(cx);
|
||||
workspace::init(&client, cx);
|
||||
editor::init(cx);
|
||||
go_to_line::init(cx);
|
||||
file_finder::init(cx);
|
||||
|
|
|
@ -252,7 +252,7 @@ mod tests {
|
|||
async fn test_new_empty_workspace(cx: &mut TestAppContext) {
|
||||
let app_state = cx.update(test_app_state);
|
||||
cx.update(|cx| {
|
||||
workspace::init(cx);
|
||||
workspace::init(&app_state.client, cx);
|
||||
});
|
||||
cx.dispatch_global_action(workspace::OpenNew(app_state.clone()));
|
||||
let window_id = *cx.window_ids().first().unwrap();
|
||||
|
|
Loading…
Reference in a new issue