Dedup channel views

Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
Max Brunsfeld 2023-08-24 14:29:04 -07:00
parent 5888e7b214
commit 1ae54ca620
3 changed files with 94 additions and 86 deletions

View file

@ -213,17 +213,12 @@ async fn test_channel_buffer_replica_ids(
assert_eq!(channel_buffer.buffer().read(cx).replica_id(), 0); assert_eq!(channel_buffer.buffer().read(cx).replica_id(), 0);
}); });
let channel_window_a = cx_a let channel_window_a =
.add_window(|cx| ChannelView::new(project_a.clone(), channel_buffer_a.clone(), None, cx)); cx_a.add_window(|cx| ChannelView::new(project_a.clone(), channel_buffer_a.clone(), cx));
let channel_window_b = cx_b let channel_window_b =
.add_window(|cx| ChannelView::new(project_b.clone(), channel_buffer_b.clone(), None, cx)); cx_b.add_window(|cx| ChannelView::new(project_b.clone(), channel_buffer_b.clone(), cx));
let channel_window_c = cx_c.add_window(|cx| { let channel_window_c = cx_c.add_window(|cx| {
ChannelView::new( ChannelView::new(separate_project_c.clone(), channel_buffer_c.clone(), cx)
separate_project_c.clone(),
channel_buffer_c.clone(),
None,
cx,
)
}); });
let channel_view_a = channel_window_a.root(cx_a); let channel_view_a = channel_window_a.root(cx_a);

View file

@ -1,4 +1,8 @@
use channel::channel_buffer::{self, ChannelBuffer}; use anyhow::{anyhow, Result};
use channel::{
channel_buffer::{self, ChannelBuffer},
ChannelId,
};
use client::proto; use client::proto;
use clock::ReplicaId; use clock::ReplicaId;
use collections::HashMap; use collections::HashMap;
@ -6,15 +10,13 @@ use editor::Editor;
use gpui::{ use gpui::{
actions, actions,
elements::{ChildView, Label}, elements::{ChildView, Label},
AnyElement, AnyViewHandle, AppContext, Element, Entity, ModelHandle, Subscription, View, AnyElement, AnyViewHandle, AppContext, Element, Entity, ModelHandle, Subscription, Task, View,
ViewContext, ViewHandle, ViewContext, ViewHandle,
}; };
use language::Language;
use project::Project; use project::Project;
use std::sync::Arc;
use workspace::{ use workspace::{
item::{FollowableItem, Item, ItemHandle}, item::{FollowableItem, Item, ItemHandle},
register_followable_item, ViewId, register_followable_item, Pane, ViewId, Workspace, WorkspaceId,
}; };
actions!(channel_view, [Deploy]); actions!(channel_view, [Deploy]);
@ -32,14 +34,47 @@ pub struct ChannelView {
} }
impl ChannelView { impl ChannelView {
pub fn open(
channel_id: ChannelId,
pane: ViewHandle<Pane>,
workspace: ViewHandle<Workspace>,
cx: &mut AppContext,
) -> Task<Result<ViewHandle<Self>>> {
let workspace = workspace.read(cx);
let project = workspace.project().to_owned();
let channel_store = workspace.app_state().channel_store.clone();
let markdown = workspace
.app_state()
.languages
.language_for_name("Markdown");
let channel_buffer =
channel_store.update(cx, |store, cx| store.open_channel_buffer(channel_id, cx));
cx.spawn(|mut cx| async move {
let channel_buffer = channel_buffer.await?;
let markdown = markdown.await?;
channel_buffer.update(&mut cx, |buffer, cx| {
buffer.buffer().update(cx, |buffer, cx| {
buffer.set_language(Some(markdown), cx);
})
});
pane.update(&mut cx, |pane, cx| {
pane.items_of_type::<Self>()
.find(|channel_view| channel_view.read(cx).channel_buffer == channel_buffer)
.unwrap_or_else(|| cx.add_view(|cx| Self::new(project, channel_buffer, cx)))
})
.ok_or_else(|| anyhow!("pane was dropped"))
})
}
pub fn new( pub fn new(
project: ModelHandle<Project>, project: ModelHandle<Project>,
channel_buffer: ModelHandle<ChannelBuffer>, channel_buffer: ModelHandle<ChannelBuffer>,
language: Option<Arc<Language>>,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) -> Self { ) -> Self {
let buffer = channel_buffer.read(cx).buffer(); let buffer = channel_buffer.read(cx).buffer();
buffer.update(cx, |buffer, cx| buffer.set_language(language, cx)); // buffer.update(cx, |buffer, cx| buffer.set_language(language, cx));
let editor = cx.add_view(|cx| Editor::for_buffer(buffer, None, cx)); let editor = cx.add_view(|cx| Editor::for_buffer(buffer, None, cx));
let _editor_event_subscription = cx.subscribe(&editor, |_, _, e, cx| cx.emit(e.clone())); let _editor_event_subscription = cx.subscribe(&editor, |_, _, e, cx| cx.emit(e.clone()));
@ -157,6 +192,14 @@ impl Item for ChannelView {
}); });
Label::new(channel_name, style.label.to_owned()).into_any() Label::new(channel_name, style.label.to_owned()).into_any()
} }
fn clone_on_split(&self, _: WorkspaceId, cx: &mut ViewContext<Self>) -> Option<Self> {
Some(Self::new(
self.project.clone(),
self.channel_buffer.clone(),
cx,
))
}
} }
impl FollowableItem for ChannelView { impl FollowableItem for ChannelView {
@ -180,7 +223,7 @@ impl FollowableItem for ChannelView {
} }
fn from_state_proto( fn from_state_proto(
_: ViewHandle<workspace::Pane>, pane: ViewHandle<workspace::Pane>,
workspace: ViewHandle<workspace::Workspace>, workspace: ViewHandle<workspace::Workspace>,
remote_id: workspace::ViewId, remote_id: workspace::ViewId,
state: &mut Option<proto::view::Variant>, state: &mut Option<proto::view::Variant>,
@ -189,48 +232,38 @@ impl FollowableItem for ChannelView {
let Some(proto::view::Variant::ChannelView(_)) = state else { return None }; let Some(proto::view::Variant::ChannelView(_)) = state else { return None };
let Some(proto::view::Variant::ChannelView(state)) = state.take() else { unreachable!() }; let Some(proto::view::Variant::ChannelView(state)) = state.take() else { unreachable!() };
let channel_store = &workspace.read(cx).app_state().channel_store.clone(); let open = ChannelView::open(state.channel_id, pane, workspace, cx);
let open_channel_buffer = channel_store.update(cx, |store, cx| {
store.open_channel_buffer(state.channel_id, cx)
});
let project = workspace.read(cx).project().to_owned();
let language = workspace.read(cx).app_state().languages.clone();
let get_markdown = language.language_for_name("Markdown");
Some(cx.spawn(|mut cx| async move { Some(cx.spawn(|mut cx| async move {
let channel_buffer = open_channel_buffer.await?; let this = open.await?;
let markdown = get_markdown.await?;
let this = workspace let task = this
.update(&mut cx, move |_, cx| { .update(&mut cx, |this, cx| {
cx.add_view(|cx| { this.remote_id = Some(remote_id);
let mut this = Self::new(project, channel_buffer, Some(markdown), cx);
this.remote_id = Some(remote_id); if let Some(state) = state.editor {
this Some(this.editor.update(cx, |editor, cx| {
}) editor.apply_update_proto(
&this.project,
proto::update_view::Variant::Editor(proto::update_view::Editor {
selections: state.selections,
pending_selection: state.pending_selection,
scroll_top_anchor: state.scroll_top_anchor,
scroll_x: state.scroll_x,
scroll_y: state.scroll_y,
..Default::default()
}),
cx,
)
}))
} else {
None
}
}) })
.ok_or_else(|| anyhow::anyhow!("workspace dropped"))?; .ok_or_else(|| anyhow!("window was closed"))?;
if let Some(state) = state.editor { if let Some(task) = task {
let task = this.update(&mut cx, |this, cx| { task.await?;
this.editor.update(cx, |editor, cx| {
editor.apply_update_proto(
&this.project,
proto::update_view::Variant::Editor(proto::update_view::Editor {
selections: state.selections,
pending_selection: state.pending_selection,
scroll_top_anchor: state.scroll_top_anchor,
scroll_x: state.scroll_x,
scroll_y: state.scroll_y,
..Default::default()
}),
cx,
)
})
});
if let Some(task) = task {
task.await?;
}
} }
Ok(this) Ok(this)

View file

@ -2220,38 +2220,18 @@ impl CollabPanel {
} }
fn open_channel_buffer(&mut self, action: &OpenChannelBuffer, cx: &mut ViewContext<Self>) { fn open_channel_buffer(&mut self, action: &OpenChannelBuffer, cx: &mut ViewContext<Self>) {
let workspace = self.workspace; if let Some(workspace) = self.workspace.upgrade(cx) {
let open = self.channel_store.update(cx, |channel_store, cx| { let pane = workspace.read(cx).active_pane().clone();
channel_store.open_channel_buffer(action.channel_id, cx) let channel_view = ChannelView::open(action.channel_id, pane.clone(), workspace, cx);
}); cx.spawn(|_, mut cx| async move {
let channel_view = channel_view.await?;
cx.spawn(|_, mut cx| async move { pane.update(&mut cx, |pane, cx| {
let channel_buffer = open.await?; pane.add_item(Box::new(channel_view), true, true, None, cx)
let markdown = workspace
.read_with(&cx, |workspace, _| {
workspace
.app_state()
.languages
.language_for_name("Markdown")
})?
.await?;
workspace.update(&mut cx, |workspace, cx| {
let channel_view = cx.add_view(|cx| {
ChannelView::new(
workspace.project().to_owned(),
channel_buffer,
Some(markdown),
cx,
)
}); });
workspace.add_item(Box::new(channel_view), cx); anyhow::Ok(())
})?; })
.detach();
anyhow::Ok(()) }
})
.detach();
} }
fn show_inline_context_menu(&mut self, _: &menu::ShowContextMenu, cx: &mut ViewContext<Self>) { fn show_inline_context_menu(&mut self, _: &menu::ShowContextMenu, cx: &mut ViewContext<Self>) {