Bring back channel notes (#3506)
This commit is contained in:
commit
dba94c5122
9 changed files with 1304 additions and 1301 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1830,7 +1830,7 @@ dependencies = [
|
||||||
"clap 3.2.25",
|
"clap 3.2.25",
|
||||||
"client2",
|
"client2",
|
||||||
"clock",
|
"clock",
|
||||||
"collab_ui",
|
"collab_ui2",
|
||||||
"collections",
|
"collections",
|
||||||
"ctor",
|
"ctor",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
|
|
|
@ -81,7 +81,7 @@ settings = { package = "settings2", path = "../settings2", features = ["test-sup
|
||||||
theme = { package = "theme2", path = "../theme2" }
|
theme = { package = "theme2", path = "../theme2" }
|
||||||
workspace = { package = "workspace2", path = "../workspace2", features = ["test-support"] }
|
workspace = { package = "workspace2", path = "../workspace2", features = ["test-support"] }
|
||||||
|
|
||||||
collab_ui = { path = "../collab_ui", features = ["test-support"] }
|
collab_ui = { path = "../collab_ui2", package = "collab_ui2", features = ["test-support"] }
|
||||||
|
|
||||||
async-trait.workspace = true
|
async-trait.workspace = true
|
||||||
pretty_assertions.workspace = true
|
pretty_assertions.workspace = true
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -13,7 +13,7 @@ use client::{
|
||||||
use collections::{HashMap, HashSet};
|
use collections::{HashMap, HashSet};
|
||||||
use fs::FakeFs;
|
use fs::FakeFs;
|
||||||
use futures::{channel::oneshot, StreamExt as _};
|
use futures::{channel::oneshot, StreamExt as _};
|
||||||
use gpui::{BackgroundExecutor, Context, Model, TestAppContext, WindowHandle};
|
use gpui::{BackgroundExecutor, Context, Model, TestAppContext, View, VisualTestContext};
|
||||||
use language::LanguageRegistry;
|
use language::LanguageRegistry;
|
||||||
use node_runtime::FakeNodeRuntime;
|
use node_runtime::FakeNodeRuntime;
|
||||||
|
|
||||||
|
@ -602,14 +602,12 @@ impl TestClient {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo(workspace)
|
pub fn build_workspace<'a>(
|
||||||
#[allow(dead_code)]
|
&'a self,
|
||||||
pub fn build_workspace(
|
|
||||||
&self,
|
|
||||||
project: &Model<Project>,
|
project: &Model<Project>,
|
||||||
cx: &mut TestAppContext,
|
cx: &'a mut TestAppContext,
|
||||||
) -> WindowHandle<Workspace> {
|
) -> (View<Workspace>, &'a mut VisualTestContext) {
|
||||||
cx.add_window(|cx| Workspace::new(0, project.clone(), self.app_state.clone(), cx))
|
cx.add_window_view(|cx| Workspace::new(0, project.clone(), self.app_state.clone(), cx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,454 +1,444 @@
|
||||||
// use anyhow::{anyhow, Result};
|
use anyhow::Result;
|
||||||
// use call::report_call_event_for_channel;
|
use call::report_call_event_for_channel;
|
||||||
// use channel::{Channel, ChannelBuffer, ChannelBufferEvent, ChannelId, ChannelStore};
|
use channel::{Channel, ChannelBuffer, ChannelBufferEvent, ChannelId, ChannelStore};
|
||||||
// use client::{
|
use client::{
|
||||||
// proto::{self, PeerId},
|
proto::{self, PeerId},
|
||||||
// Collaborator, ParticipantIndex,
|
Collaborator, ParticipantIndex,
|
||||||
// };
|
};
|
||||||
// use collections::HashMap;
|
use collections::HashMap;
|
||||||
// use editor::{CollaborationHub, Editor};
|
use editor::{CollaborationHub, Editor, EditorEvent};
|
||||||
// use gpui::{
|
use gpui::{
|
||||||
// actions,
|
actions, AnyElement, AnyView, AppContext, Entity as _, EventEmitter, FocusableView,
|
||||||
// elements::{ChildView, Label},
|
IntoElement as _, Model, Pixels, Point, Render, Subscription, Task, View, ViewContext,
|
||||||
// geometry::vector::Vector2F,
|
VisualContext as _, WindowContext,
|
||||||
// AnyElement, AnyViewHandle, AppContext, Element, Entity, ModelHandle, Subscription, Task, View,
|
};
|
||||||
// ViewContext, ViewHandle,
|
use project::Project;
|
||||||
// };
|
use std::{
|
||||||
// use project::Project;
|
any::{Any, TypeId},
|
||||||
// use smallvec::SmallVec;
|
sync::Arc,
|
||||||
// use std::{
|
};
|
||||||
// any::{Any, TypeId},
|
use ui::Label;
|
||||||
// sync::Arc,
|
use util::ResultExt;
|
||||||
// };
|
use workspace::{
|
||||||
// use util::ResultExt;
|
item::{FollowableItem, Item, ItemEvent, ItemHandle},
|
||||||
// use workspace::{
|
register_followable_item,
|
||||||
// item::{FollowableItem, Item, ItemEvent, ItemHandle},
|
searchable::SearchableItemHandle,
|
||||||
// register_followable_item,
|
ItemNavHistory, Pane, SaveIntent, ViewId, Workspace, WorkspaceId,
|
||||||
// searchable::SearchableItemHandle,
|
};
|
||||||
// ItemNavHistory, Pane, SaveIntent, ViewId, Workspace, WorkspaceId,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// actions!(channel_view, [Deploy]);
|
actions!(Deploy);
|
||||||
|
|
||||||
// pub fn init(cx: &mut AppContext) {
|
pub fn init(cx: &mut AppContext) {
|
||||||
// register_followable_item::<ChannelView>(cx)
|
register_followable_item::<ChannelView>(cx)
|
||||||
// }
|
}
|
||||||
|
|
||||||
// pub struct ChannelView {
|
pub struct ChannelView {
|
||||||
// pub editor: ViewHandle<Editor>,
|
pub editor: View<Editor>,
|
||||||
// project: ModelHandle<Project>,
|
project: Model<Project>,
|
||||||
// channel_store: ModelHandle<ChannelStore>,
|
channel_store: Model<ChannelStore>,
|
||||||
// channel_buffer: ModelHandle<ChannelBuffer>,
|
channel_buffer: Model<ChannelBuffer>,
|
||||||
// remote_id: Option<ViewId>,
|
remote_id: Option<ViewId>,
|
||||||
// _editor_event_subscription: Subscription,
|
_editor_event_subscription: Subscription,
|
||||||
// }
|
}
|
||||||
|
|
||||||
// impl ChannelView {
|
impl ChannelView {
|
||||||
// pub fn open(
|
pub fn open(
|
||||||
// channel_id: ChannelId,
|
channel_id: ChannelId,
|
||||||
// workspace: ViewHandle<Workspace>,
|
workspace: View<Workspace>,
|
||||||
// cx: &mut AppContext,
|
cx: &mut WindowContext,
|
||||||
// ) -> Task<Result<ViewHandle<Self>>> {
|
) -> Task<Result<View<Self>>> {
|
||||||
// let pane = workspace.read(cx).active_pane().clone();
|
let pane = workspace.read(cx).active_pane().clone();
|
||||||
// let channel_view = Self::open_in_pane(channel_id, pane.clone(), workspace.clone(), cx);
|
let channel_view = Self::open_in_pane(channel_id, pane.clone(), workspace.clone(), cx);
|
||||||
// cx.spawn(|mut cx| async move {
|
cx.spawn(|mut cx| async move {
|
||||||
// let channel_view = channel_view.await?;
|
let channel_view = channel_view.await?;
|
||||||
// pane.update(&mut cx, |pane, cx| {
|
pane.update(&mut cx, |pane, cx| {
|
||||||
// report_call_event_for_channel(
|
report_call_event_for_channel(
|
||||||
// "open channel notes",
|
"open channel notes",
|
||||||
// channel_id,
|
channel_id,
|
||||||
// &workspace.read(cx).app_state().client,
|
&workspace.read(cx).app_state().client,
|
||||||
// cx,
|
cx,
|
||||||
// );
|
);
|
||||||
// pane.add_item(Box::new(channel_view.clone()), true, true, None, cx);
|
pane.add_item(Box::new(channel_view.clone()), true, true, None, cx);
|
||||||
// });
|
})?;
|
||||||
// anyhow::Ok(channel_view)
|
anyhow::Ok(channel_view)
|
||||||
// })
|
})
|
||||||
// }
|
}
|
||||||
|
|
||||||
// pub fn open_in_pane(
|
pub fn open_in_pane(
|
||||||
// channel_id: ChannelId,
|
channel_id: ChannelId,
|
||||||
// pane: ViewHandle<Pane>,
|
pane: View<Pane>,
|
||||||
// workspace: ViewHandle<Workspace>,
|
workspace: View<Workspace>,
|
||||||
// cx: &mut AppContext,
|
cx: &mut WindowContext,
|
||||||
// ) -> Task<Result<ViewHandle<Self>>> {
|
) -> Task<Result<View<Self>>> {
|
||||||
// let workspace = workspace.read(cx);
|
let workspace = workspace.read(cx);
|
||||||
// let project = workspace.project().to_owned();
|
let project = workspace.project().to_owned();
|
||||||
// let channel_store = ChannelStore::global(cx);
|
let channel_store = ChannelStore::global(cx);
|
||||||
// let language_registry = workspace.app_state().languages.clone();
|
let language_registry = workspace.app_state().languages.clone();
|
||||||
// let markdown = language_registry.language_for_name("Markdown");
|
let markdown = language_registry.language_for_name("Markdown");
|
||||||
// let channel_buffer =
|
let channel_buffer =
|
||||||
// channel_store.update(cx, |store, cx| store.open_channel_buffer(channel_id, cx));
|
channel_store.update(cx, |store, cx| store.open_channel_buffer(channel_id, cx));
|
||||||
|
|
||||||
// cx.spawn(|mut cx| async move {
|
cx.spawn(|mut cx| async move {
|
||||||
// let channel_buffer = channel_buffer.await?;
|
let channel_buffer = channel_buffer.await?;
|
||||||
// let markdown = markdown.await.log_err();
|
let markdown = markdown.await.log_err();
|
||||||
|
|
||||||
// channel_buffer.update(&mut cx, |buffer, cx| {
|
channel_buffer.update(&mut cx, |buffer, cx| {
|
||||||
// buffer.buffer().update(cx, |buffer, cx| {
|
buffer.buffer().update(cx, |buffer, cx| {
|
||||||
// buffer.set_language_registry(language_registry);
|
buffer.set_language_registry(language_registry);
|
||||||
// if let Some(markdown) = markdown {
|
if let Some(markdown) = markdown {
|
||||||
// buffer.set_language(Some(markdown), cx);
|
buffer.set_language(Some(markdown), cx);
|
||||||
// }
|
}
|
||||||
// })
|
})
|
||||||
// });
|
})?;
|
||||||
|
|
||||||
// pane.update(&mut cx, |pane, cx| {
|
pane.update(&mut cx, |pane, cx| {
|
||||||
// let buffer_id = channel_buffer.read(cx).remote_id(cx);
|
let buffer_id = channel_buffer.read(cx).remote_id(cx);
|
||||||
|
|
||||||
// let existing_view = pane
|
let existing_view = pane
|
||||||
// .items_of_type::<Self>()
|
.items_of_type::<Self>()
|
||||||
// .find(|view| view.read(cx).channel_buffer.read(cx).remote_id(cx) == buffer_id);
|
.find(|view| view.read(cx).channel_buffer.read(cx).remote_id(cx) == buffer_id);
|
||||||
|
|
||||||
// // If this channel buffer is already open in this pane, just return it.
|
// If this channel buffer is already open in this pane, just return it.
|
||||||
// if let Some(existing_view) = existing_view.clone() {
|
if let Some(existing_view) = existing_view.clone() {
|
||||||
// if existing_view.read(cx).channel_buffer == channel_buffer {
|
if existing_view.read(cx).channel_buffer == channel_buffer {
|
||||||
// return existing_view;
|
return existing_view;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// let view = cx.add_view(|cx| {
|
let view = cx.build_view(|cx| {
|
||||||
// let mut this = Self::new(project, channel_store, channel_buffer, cx);
|
let mut this = Self::new(project, channel_store, channel_buffer, cx);
|
||||||
// this.acknowledge_buffer_version(cx);
|
this.acknowledge_buffer_version(cx);
|
||||||
// this
|
this
|
||||||
// });
|
});
|
||||||
|
|
||||||
// // If the pane contained a disconnected view for this channel buffer,
|
// If the pane contained a disconnected view for this channel buffer,
|
||||||
// // replace that.
|
// replace that.
|
||||||
// if let Some(existing_item) = existing_view {
|
if let Some(existing_item) = existing_view {
|
||||||
// if let Some(ix) = pane.index_for_item(&existing_item) {
|
if let Some(ix) = pane.index_for_item(&existing_item) {
|
||||||
// pane.close_item_by_id(existing_item.id(), SaveIntent::Skip, cx)
|
pane.close_item_by_id(existing_item.entity_id(), SaveIntent::Skip, cx)
|
||||||
// .detach();
|
.detach();
|
||||||
// pane.add_item(Box::new(view.clone()), true, true, Some(ix), cx);
|
pane.add_item(Box::new(view.clone()), true, true, Some(ix), cx);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// view
|
view
|
||||||
// })
|
})
|
||||||
// .ok_or_else(|| anyhow!("pane was dropped"))
|
})
|
||||||
// })
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn new(
|
pub fn new(
|
||||||
// project: ModelHandle<Project>,
|
project: Model<Project>,
|
||||||
// channel_store: ModelHandle<ChannelStore>,
|
channel_store: Model<ChannelStore>,
|
||||||
// channel_buffer: ModelHandle<ChannelBuffer>,
|
channel_buffer: Model<ChannelBuffer>,
|
||||||
// cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
// ) -> Self {
|
) -> Self {
|
||||||
// let buffer = channel_buffer.read(cx).buffer();
|
let buffer = channel_buffer.read(cx).buffer();
|
||||||
// let editor = cx.add_view(|cx| {
|
let editor = cx.build_view(|cx| {
|
||||||
// let mut editor = Editor::for_buffer(buffer, None, cx);
|
let mut editor = Editor::for_buffer(buffer, None, cx);
|
||||||
// editor.set_collaboration_hub(Box::new(ChannelBufferCollaborationHub(
|
editor.set_collaboration_hub(Box::new(ChannelBufferCollaborationHub(
|
||||||
// channel_buffer.clone(),
|
channel_buffer.clone(),
|
||||||
// )));
|
)));
|
||||||
// editor.set_read_only(
|
editor.set_read_only(
|
||||||
// !channel_buffer
|
!channel_buffer
|
||||||
// .read(cx)
|
.read(cx)
|
||||||
// .channel(cx)
|
.channel(cx)
|
||||||
// .is_some_and(|c| c.can_edit_notes()),
|
.is_some_and(|c| c.can_edit_notes()),
|
||||||
// );
|
);
|
||||||
// editor
|
editor
|
||||||
// });
|
});
|
||||||
// let _editor_event_subscription = cx.subscribe(&editor, |_, _, e, cx| cx.emit(e.clone()));
|
let _editor_event_subscription =
|
||||||
|
cx.subscribe(&editor, |_, _, e: &EditorEvent, cx| cx.emit(e.clone()));
|
||||||
|
|
||||||
// cx.subscribe(&channel_buffer, Self::handle_channel_buffer_event)
|
cx.subscribe(&channel_buffer, Self::handle_channel_buffer_event)
|
||||||
// .detach();
|
.detach();
|
||||||
|
|
||||||
// Self {
|
Self {
|
||||||
// editor,
|
editor,
|
||||||
// project,
|
project,
|
||||||
// channel_store,
|
channel_store,
|
||||||
// channel_buffer,
|
channel_buffer,
|
||||||
// remote_id: None,
|
remote_id: None,
|
||||||
// _editor_event_subscription,
|
_editor_event_subscription,
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// pub fn channel(&self, cx: &AppContext) -> Option<Arc<Channel>> {
|
pub fn channel(&self, cx: &AppContext) -> Option<Arc<Channel>> {
|
||||||
// self.channel_buffer.read(cx).channel(cx)
|
self.channel_buffer.read(cx).channel(cx)
|
||||||
// }
|
}
|
||||||
|
|
||||||
// fn handle_channel_buffer_event(
|
fn handle_channel_buffer_event(
|
||||||
// &mut self,
|
&mut self,
|
||||||
// _: ModelHandle<ChannelBuffer>,
|
_: Model<ChannelBuffer>,
|
||||||
// event: &ChannelBufferEvent,
|
event: &ChannelBufferEvent,
|
||||||
// cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
// ) {
|
) {
|
||||||
// match event {
|
match event {
|
||||||
// ChannelBufferEvent::Disconnected => self.editor.update(cx, |editor, cx| {
|
ChannelBufferEvent::Disconnected => self.editor.update(cx, |editor, cx| {
|
||||||
// editor.set_read_only(true);
|
editor.set_read_only(true);
|
||||||
// cx.notify();
|
cx.notify();
|
||||||
// }),
|
}),
|
||||||
// ChannelBufferEvent::ChannelChanged => {
|
ChannelBufferEvent::ChannelChanged => {
|
||||||
// self.editor.update(cx, |editor, cx| {
|
self.editor.update(cx, |editor, cx| {
|
||||||
// editor.set_read_only(!self.channel(cx).is_some_and(|c| c.can_edit_notes()));
|
editor.set_read_only(!self.channel(cx).is_some_and(|c| c.can_edit_notes()));
|
||||||
// cx.emit(editor::Event::TitleChanged);
|
cx.emit(editor::EditorEvent::TitleChanged);
|
||||||
// cx.notify()
|
cx.notify()
|
||||||
// });
|
});
|
||||||
// }
|
}
|
||||||
// ChannelBufferEvent::BufferEdited => {
|
ChannelBufferEvent::BufferEdited => {
|
||||||
// if cx.is_self_focused() || self.editor.is_focused(cx) {
|
if self.editor.read(cx).is_focused(cx) {
|
||||||
// self.acknowledge_buffer_version(cx);
|
self.acknowledge_buffer_version(cx);
|
||||||
// } else {
|
} else {
|
||||||
// self.channel_store.update(cx, |store, cx| {
|
self.channel_store.update(cx, |store, cx| {
|
||||||
// let channel_buffer = self.channel_buffer.read(cx);
|
let channel_buffer = self.channel_buffer.read(cx);
|
||||||
// store.notes_changed(
|
store.notes_changed(
|
||||||
// channel_buffer.channel_id,
|
channel_buffer.channel_id,
|
||||||
// channel_buffer.epoch(),
|
channel_buffer.epoch(),
|
||||||
// &channel_buffer.buffer().read(cx).version(),
|
&channel_buffer.buffer().read(cx).version(),
|
||||||
// cx,
|
cx,
|
||||||
// )
|
)
|
||||||
// });
|
});
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// ChannelBufferEvent::CollaboratorsChanged => {}
|
ChannelBufferEvent::CollaboratorsChanged => {}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// fn acknowledge_buffer_version(&mut self, cx: &mut ViewContext<'_, '_, ChannelView>) {
|
fn acknowledge_buffer_version(&mut self, cx: &mut ViewContext<ChannelView>) {
|
||||||
// self.channel_store.update(cx, |store, cx| {
|
self.channel_store.update(cx, |store, cx| {
|
||||||
// let channel_buffer = self.channel_buffer.read(cx);
|
let channel_buffer = self.channel_buffer.read(cx);
|
||||||
// store.acknowledge_notes_version(
|
store.acknowledge_notes_version(
|
||||||
// channel_buffer.channel_id,
|
channel_buffer.channel_id,
|
||||||
// channel_buffer.epoch(),
|
channel_buffer.epoch(),
|
||||||
// &channel_buffer.buffer().read(cx).version(),
|
&channel_buffer.buffer().read(cx).version(),
|
||||||
// cx,
|
cx,
|
||||||
// )
|
)
|
||||||
// });
|
});
|
||||||
// self.channel_buffer.update(cx, |buffer, cx| {
|
self.channel_buffer.update(cx, |buffer, cx| {
|
||||||
// buffer.acknowledge_buffer_version(cx);
|
buffer.acknowledge_buffer_version(cx);
|
||||||
// });
|
});
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// impl Entity for ChannelView {
|
impl EventEmitter<EditorEvent> for ChannelView {}
|
||||||
// type Event = editor::Event;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl View for ChannelView {
|
impl Render for ChannelView {
|
||||||
// fn ui_name() -> &'static str {
|
type Element = AnyView;
|
||||||
// "ChannelView"
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
// ChildView::new(self.editor.as_any(), cx).into_any()
|
self.editor.clone().into()
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
impl FocusableView for ChannelView {
|
||||||
// if cx.is_self_focused() {
|
fn focus_handle(&self, cx: &AppContext) -> gpui::FocusHandle {
|
||||||
// self.acknowledge_buffer_version(cx);
|
self.editor.read(cx).focus_handle(cx)
|
||||||
// cx.focus(self.editor.as_any())
|
}
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl Item for ChannelView {
|
impl Item for ChannelView {
|
||||||
// fn act_as_type<'a>(
|
type Event = EditorEvent;
|
||||||
// &'a self,
|
|
||||||
// type_id: TypeId,
|
|
||||||
// self_handle: &'a ViewHandle<Self>,
|
|
||||||
// _: &'a AppContext,
|
|
||||||
// ) -> Option<&'a AnyViewHandle> {
|
|
||||||
// if type_id == TypeId::of::<Self>() {
|
|
||||||
// Some(self_handle)
|
|
||||||
// } else if type_id == TypeId::of::<Editor>() {
|
|
||||||
// Some(&self.editor)
|
|
||||||
// } else {
|
|
||||||
// None
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn tab_content<V: 'static>(
|
fn act_as_type<'a>(
|
||||||
// &self,
|
&'a self,
|
||||||
// _: Option<usize>,
|
type_id: TypeId,
|
||||||
// style: &theme::Tab,
|
self_handle: &'a View<Self>,
|
||||||
// cx: &gpui::AppContext,
|
_: &'a AppContext,
|
||||||
// ) -> AnyElement<V> {
|
) -> Option<AnyView> {
|
||||||
// let label = if let Some(channel) = self.channel(cx) {
|
if type_id == TypeId::of::<Self>() {
|
||||||
// match (
|
Some(self_handle.to_any())
|
||||||
// channel.can_edit_notes(),
|
} else if type_id == TypeId::of::<Editor>() {
|
||||||
// self.channel_buffer.read(cx).is_connected(),
|
Some(self.editor.to_any())
|
||||||
// ) {
|
} else {
|
||||||
// (true, true) => format!("#{}", channel.name),
|
None
|
||||||
// (false, true) => format!("#{} (read-only)", channel.name),
|
}
|
||||||
// (_, false) => format!("#{} (disconnected)", channel.name),
|
}
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// format!("channel notes (disconnected)")
|
|
||||||
// };
|
|
||||||
// Label::new(label, style.label.to_owned()).into_any()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn clone_on_split(&self, _: WorkspaceId, cx: &mut ViewContext<Self>) -> Option<Self> {
|
fn tab_content(&self, _: Option<usize>, cx: &WindowContext) -> AnyElement {
|
||||||
// Some(Self::new(
|
let label = if let Some(channel) = self.channel(cx) {
|
||||||
// self.project.clone(),
|
match (
|
||||||
// self.channel_store.clone(),
|
channel.can_edit_notes(),
|
||||||
// self.channel_buffer.clone(),
|
self.channel_buffer.read(cx).is_connected(),
|
||||||
// cx,
|
) {
|
||||||
// ))
|
(true, true) => format!("#{}", channel.name),
|
||||||
// }
|
(false, true) => format!("#{} (read-only)", channel.name),
|
||||||
|
(_, false) => format!("#{} (disconnected)", channel.name),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
format!("channel notes (disconnected)")
|
||||||
|
};
|
||||||
|
Label::new(label).into_any_element()
|
||||||
|
}
|
||||||
|
|
||||||
// fn is_singleton(&self, _cx: &AppContext) -> bool {
|
fn clone_on_split(&self, _: WorkspaceId, cx: &mut ViewContext<Self>) -> Option<View<Self>> {
|
||||||
// false
|
Some(cx.build_view(|cx| {
|
||||||
// }
|
Self::new(
|
||||||
|
self.project.clone(),
|
||||||
|
self.channel_store.clone(),
|
||||||
|
self.channel_buffer.clone(),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
// fn navigate(&mut self, data: Box<dyn Any>, cx: &mut ViewContext<Self>) -> bool {
|
fn is_singleton(&self, _cx: &AppContext) -> bool {
|
||||||
// self.editor
|
false
|
||||||
// .update(cx, |editor, cx| editor.navigate(data, cx))
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// fn deactivated(&mut self, cx: &mut ViewContext<Self>) {
|
fn navigate(&mut self, data: Box<dyn Any>, cx: &mut ViewContext<Self>) -> bool {
|
||||||
// self.editor
|
self.editor
|
||||||
// .update(cx, |editor, cx| Item::deactivated(editor, cx))
|
.update(cx, |editor, cx| editor.navigate(data, cx))
|
||||||
// }
|
}
|
||||||
|
|
||||||
// fn set_nav_history(&mut self, history: ItemNavHistory, cx: &mut ViewContext<Self>) {
|
fn deactivated(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
// self.editor
|
self.editor
|
||||||
// .update(cx, |editor, cx| Item::set_nav_history(editor, history, cx))
|
.update(cx, |editor, cx| Item::deactivated(editor, cx))
|
||||||
// }
|
}
|
||||||
|
|
||||||
// fn as_searchable(&self, _: &ViewHandle<Self>) -> Option<Box<dyn SearchableItemHandle>> {
|
fn set_nav_history(&mut self, history: ItemNavHistory, cx: &mut ViewContext<Self>) {
|
||||||
// Some(Box::new(self.editor.clone()))
|
self.editor
|
||||||
// }
|
.update(cx, |editor, cx| Item::set_nav_history(editor, history, cx))
|
||||||
|
}
|
||||||
|
|
||||||
// fn show_toolbar(&self) -> bool {
|
fn as_searchable(&self, _: &View<Self>) -> Option<Box<dyn SearchableItemHandle>> {
|
||||||
// true
|
Some(Box::new(self.editor.clone()))
|
||||||
// }
|
}
|
||||||
|
|
||||||
// fn pixel_position_of_cursor(&self, cx: &AppContext) -> Option<Vector2F> {
|
fn show_toolbar(&self) -> bool {
|
||||||
// self.editor.read(cx).pixel_position_of_cursor(cx)
|
true
|
||||||
// }
|
}
|
||||||
|
|
||||||
// fn to_item_events(event: &Self::Event) -> SmallVec<[ItemEvent; 2]> {
|
fn pixel_position_of_cursor(&self, cx: &AppContext) -> Option<Point<Pixels>> {
|
||||||
// editor::Editor::to_item_events(event)
|
self.editor.read(cx).pixel_position_of_cursor(cx)
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// impl FollowableItem for ChannelView {
|
fn to_item_events(event: &EditorEvent, f: impl FnMut(ItemEvent)) {
|
||||||
// fn remote_id(&self) -> Option<workspace::ViewId> {
|
Editor::to_item_events(event, f)
|
||||||
// self.remote_id
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// fn to_state_proto(&self, cx: &AppContext) -> Option<proto::view::Variant> {
|
impl FollowableItem for ChannelView {
|
||||||
// let channel_buffer = self.channel_buffer.read(cx);
|
fn remote_id(&self) -> Option<workspace::ViewId> {
|
||||||
// if !channel_buffer.is_connected() {
|
self.remote_id
|
||||||
// return None;
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// Some(proto::view::Variant::ChannelView(
|
fn to_state_proto(&self, cx: &WindowContext) -> Option<proto::view::Variant> {
|
||||||
// proto::view::ChannelView {
|
let channel_buffer = self.channel_buffer.read(cx);
|
||||||
// channel_id: channel_buffer.channel_id,
|
if !channel_buffer.is_connected() {
|
||||||
// editor: if let Some(proto::view::Variant::Editor(proto)) =
|
return None;
|
||||||
// self.editor.read(cx).to_state_proto(cx)
|
}
|
||||||
// {
|
|
||||||
// Some(proto)
|
|
||||||
// } else {
|
|
||||||
// None
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// ))
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn from_state_proto(
|
Some(proto::view::Variant::ChannelView(
|
||||||
// pane: ViewHandle<workspace::Pane>,
|
proto::view::ChannelView {
|
||||||
// workspace: ViewHandle<workspace::Workspace>,
|
channel_id: channel_buffer.channel_id,
|
||||||
// remote_id: workspace::ViewId,
|
editor: if let Some(proto::view::Variant::Editor(proto)) =
|
||||||
// state: &mut Option<proto::view::Variant>,
|
self.editor.read(cx).to_state_proto(cx)
|
||||||
// cx: &mut AppContext,
|
{
|
||||||
// ) -> Option<gpui::Task<anyhow::Result<ViewHandle<Self>>>> {
|
Some(proto)
|
||||||
// let Some(proto::view::Variant::ChannelView(_)) = state else {
|
} else {
|
||||||
// return None;
|
None
|
||||||
// };
|
},
|
||||||
// let Some(proto::view::Variant::ChannelView(state)) = state.take() else {
|
},
|
||||||
// unreachable!()
|
))
|
||||||
// };
|
}
|
||||||
|
|
||||||
// let open = ChannelView::open_in_pane(state.channel_id, pane, workspace, cx);
|
fn from_state_proto(
|
||||||
|
pane: View<workspace::Pane>,
|
||||||
|
workspace: View<workspace::Workspace>,
|
||||||
|
remote_id: workspace::ViewId,
|
||||||
|
state: &mut Option<proto::view::Variant>,
|
||||||
|
cx: &mut WindowContext,
|
||||||
|
) -> Option<gpui::Task<anyhow::Result<View<Self>>>> {
|
||||||
|
let Some(proto::view::Variant::ChannelView(_)) = state else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
let Some(proto::view::Variant::ChannelView(state)) = state.take() else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
// Some(cx.spawn(|mut cx| async move {
|
let open = ChannelView::open_in_pane(state.channel_id, pane, workspace, cx);
|
||||||
// let this = open.await?;
|
|
||||||
|
|
||||||
// let task = this
|
Some(cx.spawn(|mut cx| async move {
|
||||||
// .update(&mut cx, |this, cx| {
|
let this = open.await?;
|
||||||
// this.remote_id = Some(remote_id);
|
|
||||||
|
|
||||||
// if let Some(state) = state.editor {
|
let task = this.update(&mut cx, |this, cx| {
|
||||||
// Some(this.editor.update(cx, |editor, cx| {
|
this.remote_id = Some(remote_id);
|
||||||
// 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!("window was closed"))?;
|
|
||||||
|
|
||||||
// if let Some(task) = task {
|
if let Some(state) = state.editor {
|
||||||
// task.await?;
|
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(this)
|
if let Some(task) = task {
|
||||||
// }))
|
task.await?;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// fn add_event_to_update_proto(
|
Ok(this)
|
||||||
// &self,
|
}))
|
||||||
// event: &Self::Event,
|
}
|
||||||
// update: &mut Option<proto::update_view::Variant>,
|
|
||||||
// cx: &AppContext,
|
|
||||||
// ) -> bool {
|
|
||||||
// self.editor
|
|
||||||
// .read(cx)
|
|
||||||
// .add_event_to_update_proto(event, update, cx)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn apply_update_proto(
|
fn add_event_to_update_proto(
|
||||||
// &mut self,
|
&self,
|
||||||
// project: &ModelHandle<Project>,
|
event: &EditorEvent,
|
||||||
// message: proto::update_view::Variant,
|
update: &mut Option<proto::update_view::Variant>,
|
||||||
// cx: &mut ViewContext<Self>,
|
cx: &WindowContext,
|
||||||
// ) -> gpui::Task<anyhow::Result<()>> {
|
) -> bool {
|
||||||
// self.editor.update(cx, |editor, cx| {
|
self.editor
|
||||||
// editor.apply_update_proto(project, message, cx)
|
.read(cx)
|
||||||
// })
|
.add_event_to_update_proto(event, update, cx)
|
||||||
// }
|
}
|
||||||
|
|
||||||
// fn set_leader_peer_id(&mut self, leader_peer_id: Option<PeerId>, cx: &mut ViewContext<Self>) {
|
fn apply_update_proto(
|
||||||
// self.editor.update(cx, |editor, cx| {
|
&mut self,
|
||||||
// editor.set_leader_peer_id(leader_peer_id, cx)
|
project: &Model<Project>,
|
||||||
// })
|
message: proto::update_view::Variant,
|
||||||
// }
|
cx: &mut ViewContext<Self>,
|
||||||
|
) -> gpui::Task<anyhow::Result<()>> {
|
||||||
|
self.editor.update(cx, |editor, cx| {
|
||||||
|
editor.apply_update_proto(project, message, cx)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// fn should_unfollow_on_event(event: &Self::Event, cx: &AppContext) -> bool {
|
fn set_leader_peer_id(&mut self, leader_peer_id: Option<PeerId>, cx: &mut ViewContext<Self>) {
|
||||||
// Editor::should_unfollow_on_event(event, cx)
|
self.editor.update(cx, |editor, cx| {
|
||||||
// }
|
editor.set_leader_peer_id(leader_peer_id, cx)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// fn is_project_item(&self, _cx: &AppContext) -> bool {
|
fn is_project_item(&self, _cx: &WindowContext) -> bool {
|
||||||
// false
|
false
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// struct ChannelBufferCollaborationHub(ModelHandle<ChannelBuffer>);
|
fn to_follow_event(event: &Self::Event) -> Option<workspace::item::FollowEvent> {
|
||||||
|
Editor::to_follow_event(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// impl CollaborationHub for ChannelBufferCollaborationHub {
|
struct ChannelBufferCollaborationHub(Model<ChannelBuffer>);
|
||||||
// fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
|
|
||||||
// self.0.read(cx).collaborators()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn user_participant_indices<'a>(
|
impl CollaborationHub for ChannelBufferCollaborationHub {
|
||||||
// &self,
|
fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
|
||||||
// cx: &'a AppContext,
|
self.0.read(cx).collaborators()
|
||||||
// ) -> &'a HashMap<u64, ParticipantIndex> {
|
}
|
||||||
// self.0.read(cx).user_store().read(cx).participant_indices()
|
|
||||||
// }
|
fn user_participant_indices<'a>(
|
||||||
// }
|
&self,
|
||||||
|
cx: &'a AppContext,
|
||||||
|
) -> &'a HashMap<u64, ParticipantIndex> {
|
||||||
|
self.0.read(cx).user_store().read(cx).participant_indices()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -191,6 +191,7 @@ use workspace::{
|
||||||
Workspace,
|
Workspace,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::channel_view::ChannelView;
|
||||||
use crate::{face_pile::FacePile, CollaborationPanelSettings};
|
use crate::{face_pile::FacePile, CollaborationPanelSettings};
|
||||||
|
|
||||||
use self::channel_modal::ChannelModal;
|
use self::channel_modal::ChannelModal;
|
||||||
|
@ -1935,8 +1936,7 @@ impl CollabPanel {
|
||||||
|
|
||||||
fn open_channel_notes(&mut self, channel_id: ChannelId, cx: &mut ViewContext<Self>) {
|
fn open_channel_notes(&mut self, channel_id: ChannelId, cx: &mut ViewContext<Self>) {
|
||||||
if let Some(workspace) = self.workspace.upgrade() {
|
if let Some(workspace) = self.workspace.upgrade() {
|
||||||
todo!();
|
ChannelView::open(channel_id, workspace, cx).detach();
|
||||||
// ChannelView::open(action.channel_id, workspace, cx).detach();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2619,6 +2619,9 @@ impl CollabPanel {
|
||||||
} else {
|
} else {
|
||||||
Color::Muted
|
Color::Muted
|
||||||
})
|
})
|
||||||
|
.on_click(cx.listener(move |this, _, cx| {
|
||||||
|
this.open_channel_notes(channel_id, cx)
|
||||||
|
}))
|
||||||
.tooltip(|cx| {
|
.tooltip(|cx| {
|
||||||
Tooltip::text("Open channel notes", cx)
|
Tooltip::text("Open channel notes", cx)
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -33,6 +33,7 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
|
||||||
// vcs_menu::init(cx);
|
// vcs_menu::init(cx);
|
||||||
collab_titlebar_item::init(cx);
|
collab_titlebar_item::init(cx);
|
||||||
collab_panel::init(cx);
|
collab_panel::init(cx);
|
||||||
|
channel_view::init(cx);
|
||||||
// chat_panel::init(cx);
|
// chat_panel::init(cx);
|
||||||
notifications::init(&app_state, cx);
|
notifications::init(&app_state, cx);
|
||||||
|
|
||||||
|
|
|
@ -545,6 +545,10 @@ pub struct VisualTestContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> VisualTestContext<'a> {
|
impl<'a> VisualTestContext<'a> {
|
||||||
|
pub fn update<R>(&mut self, f: impl FnOnce(&mut WindowContext) -> R) -> R {
|
||||||
|
self.cx.update_window(self.window, |_, cx| f(cx)).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_window(window: AnyWindowHandle, cx: &'a mut TestAppContext) -> Self {
|
pub fn from_window(window: AnyWindowHandle, cx: &'a mut TestAppContext) -> Self {
|
||||||
Self { cx, window }
|
Self { cx, window }
|
||||||
}
|
}
|
||||||
|
|
|
@ -2077,6 +2077,7 @@ impl Workspace {
|
||||||
}
|
}
|
||||||
if &pane == self.active_pane() {
|
if &pane == self.active_pane() {
|
||||||
self.active_item_path_changed(cx);
|
self.active_item_path_changed(cx);
|
||||||
|
self.update_active_view_for_followers(cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pane::Event::ChangeItemTitle => {
|
pane::Event::ChangeItemTitle => {
|
||||||
|
@ -2756,11 +2757,10 @@ impl Workspace {
|
||||||
fn update_active_view_for_followers(&mut self, cx: &mut ViewContext<Self>) {
|
fn update_active_view_for_followers(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
let mut is_project_item = true;
|
let mut is_project_item = true;
|
||||||
let mut update = proto::UpdateActiveView::default();
|
let mut update = proto::UpdateActiveView::default();
|
||||||
if self.active_pane.read(cx).has_focus(cx) {
|
|
||||||
let item = self
|
if let Some(item) = self.active_item(cx) {
|
||||||
.active_item(cx)
|
if item.focus_handle(cx).contains_focused(cx) {
|
||||||
.and_then(|item| item.to_followable_item_handle(cx));
|
if let Some(item) = item.to_followable_item_handle(cx) {
|
||||||
if let Some(item) = item {
|
|
||||||
is_project_item = item.is_project_item(cx);
|
is_project_item = item.is_project_item(cx);
|
||||||
update = proto::UpdateActiveView {
|
update = proto::UpdateActiveView {
|
||||||
id: item
|
id: item
|
||||||
|
@ -2770,6 +2770,7 @@ impl Workspace {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if update.id != self.last_active_view_id {
|
if update.id != self.last_active_view_id {
|
||||||
self.last_active_view_id = update.id.clone();
|
self.last_active_view_id = update.id.clone();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue