mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-16 00:47:39 +03:00
Move placeholder titlebar render to collab_ui
This commit is contained in:
parent
84bcbf1128
commit
793fa6e3a4
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1864,6 +1864,7 @@ dependencies = [
|
||||
"theme2",
|
||||
"time",
|
||||
"tree-sitter-markdown",
|
||||
"ui2",
|
||||
"util",
|
||||
"workspace2",
|
||||
"zed_actions2",
|
||||
|
@ -18,6 +18,7 @@ members = [
|
||||
"crates/collab",
|
||||
"crates/collab2",
|
||||
"crates/collab_ui",
|
||||
"crates/collab_ui2",
|
||||
"crates/collections",
|
||||
"crates/command_palette",
|
||||
"crates/command_palette2",
|
||||
|
@ -48,6 +48,7 @@ feature_flags = { package = "feature_flags2", path = "../feature_flags2"}
|
||||
theme = { package = "theme2", path = "../theme2" }
|
||||
# theme_selector = { path = "../theme_selector" }
|
||||
# vcs_menu = { path = "../vcs_menu" }
|
||||
ui = { package = "ui2", path = "../ui2" }
|
||||
util = { path = "../util" }
|
||||
workspace = { package = "workspace2", path = "../workspace2" }
|
||||
zed-actions = { package="zed_actions2", path = "../zed_actions2"}
|
||||
|
@ -1,454 +1,454 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
use call::report_call_event_for_channel;
|
||||
use channel::{Channel, ChannelBuffer, ChannelBufferEvent, ChannelId, ChannelStore};
|
||||
use client::{
|
||||
proto::{self, PeerId},
|
||||
Collaborator, ParticipantIndex,
|
||||
};
|
||||
use collections::HashMap;
|
||||
use editor::{CollaborationHub, Editor};
|
||||
use gpui::{
|
||||
actions,
|
||||
elements::{ChildView, Label},
|
||||
geometry::vector::Vector2F,
|
||||
AnyElement, AnyViewHandle, AppContext, Element, Entity, ModelHandle, Subscription, Task, View,
|
||||
ViewContext, ViewHandle,
|
||||
};
|
||||
use project::Project;
|
||||
use smallvec::SmallVec;
|
||||
use std::{
|
||||
any::{Any, TypeId},
|
||||
sync::Arc,
|
||||
};
|
||||
use util::ResultExt;
|
||||
use workspace::{
|
||||
item::{FollowableItem, Item, ItemEvent, ItemHandle},
|
||||
register_followable_item,
|
||||
searchable::SearchableItemHandle,
|
||||
ItemNavHistory, Pane, SaveIntent, ViewId, Workspace, WorkspaceId,
|
||||
};
|
||||
// use anyhow::{anyhow, Result};
|
||||
// use call::report_call_event_for_channel;
|
||||
// use channel::{Channel, ChannelBuffer, ChannelBufferEvent, ChannelId, ChannelStore};
|
||||
// use client::{
|
||||
// proto::{self, PeerId},
|
||||
// Collaborator, ParticipantIndex,
|
||||
// };
|
||||
// use collections::HashMap;
|
||||
// use editor::{CollaborationHub, Editor};
|
||||
// use gpui::{
|
||||
// actions,
|
||||
// elements::{ChildView, Label},
|
||||
// geometry::vector::Vector2F,
|
||||
// AnyElement, AnyViewHandle, AppContext, Element, Entity, ModelHandle, Subscription, Task, View,
|
||||
// ViewContext, ViewHandle,
|
||||
// };
|
||||
// use project::Project;
|
||||
// use smallvec::SmallVec;
|
||||
// use std::{
|
||||
// any::{Any, TypeId},
|
||||
// sync::Arc,
|
||||
// };
|
||||
// use util::ResultExt;
|
||||
// use workspace::{
|
||||
// item::{FollowableItem, Item, ItemEvent, ItemHandle},
|
||||
// register_followable_item,
|
||||
// searchable::SearchableItemHandle,
|
||||
// ItemNavHistory, Pane, SaveIntent, ViewId, Workspace, WorkspaceId,
|
||||
// };
|
||||
|
||||
actions!(channel_view, [Deploy]);
|
||||
// actions!(channel_view, [Deploy]);
|
||||
|
||||
pub fn init(cx: &mut AppContext) {
|
||||
register_followable_item::<ChannelView>(cx)
|
||||
}
|
||||
// pub fn init(cx: &mut AppContext) {
|
||||
// register_followable_item::<ChannelView>(cx)
|
||||
// }
|
||||
|
||||
pub struct ChannelView {
|
||||
pub editor: ViewHandle<Editor>,
|
||||
project: ModelHandle<Project>,
|
||||
channel_store: ModelHandle<ChannelStore>,
|
||||
channel_buffer: ModelHandle<ChannelBuffer>,
|
||||
remote_id: Option<ViewId>,
|
||||
_editor_event_subscription: Subscription,
|
||||
}
|
||||
// pub struct ChannelView {
|
||||
// pub editor: ViewHandle<Editor>,
|
||||
// project: ModelHandle<Project>,
|
||||
// channel_store: ModelHandle<ChannelStore>,
|
||||
// channel_buffer: ModelHandle<ChannelBuffer>,
|
||||
// remote_id: Option<ViewId>,
|
||||
// _editor_event_subscription: Subscription,
|
||||
// }
|
||||
|
||||
impl ChannelView {
|
||||
pub fn open(
|
||||
channel_id: ChannelId,
|
||||
workspace: ViewHandle<Workspace>,
|
||||
cx: &mut AppContext,
|
||||
) -> Task<Result<ViewHandle<Self>>> {
|
||||
let pane = workspace.read(cx).active_pane().clone();
|
||||
let channel_view = Self::open_in_pane(channel_id, pane.clone(), workspace.clone(), cx);
|
||||
cx.spawn(|mut cx| async move {
|
||||
let channel_view = channel_view.await?;
|
||||
pane.update(&mut cx, |pane, cx| {
|
||||
report_call_event_for_channel(
|
||||
"open channel notes",
|
||||
channel_id,
|
||||
&workspace.read(cx).app_state().client,
|
||||
cx,
|
||||
);
|
||||
pane.add_item(Box::new(channel_view.clone()), true, true, None, cx);
|
||||
});
|
||||
anyhow::Ok(channel_view)
|
||||
})
|
||||
}
|
||||
// impl ChannelView {
|
||||
// pub fn open(
|
||||
// channel_id: ChannelId,
|
||||
// workspace: ViewHandle<Workspace>,
|
||||
// cx: &mut AppContext,
|
||||
// ) -> Task<Result<ViewHandle<Self>>> {
|
||||
// let pane = workspace.read(cx).active_pane().clone();
|
||||
// let channel_view = Self::open_in_pane(channel_id, pane.clone(), workspace.clone(), cx);
|
||||
// cx.spawn(|mut cx| async move {
|
||||
// let channel_view = channel_view.await?;
|
||||
// pane.update(&mut cx, |pane, cx| {
|
||||
// report_call_event_for_channel(
|
||||
// "open channel notes",
|
||||
// channel_id,
|
||||
// &workspace.read(cx).app_state().client,
|
||||
// cx,
|
||||
// );
|
||||
// pane.add_item(Box::new(channel_view.clone()), true, true, None, cx);
|
||||
// });
|
||||
// anyhow::Ok(channel_view)
|
||||
// })
|
||||
// }
|
||||
|
||||
pub fn open_in_pane(
|
||||
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 = ChannelStore::global(cx);
|
||||
let language_registry = workspace.app_state().languages.clone();
|
||||
let markdown = language_registry.language_for_name("Markdown");
|
||||
let channel_buffer =
|
||||
channel_store.update(cx, |store, cx| store.open_channel_buffer(channel_id, cx));
|
||||
// pub fn open_in_pane(
|
||||
// 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 = ChannelStore::global(cx);
|
||||
// let language_registry = workspace.app_state().languages.clone();
|
||||
// let markdown = language_registry.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.log_err();
|
||||
// cx.spawn(|mut cx| async move {
|
||||
// let channel_buffer = channel_buffer.await?;
|
||||
// let markdown = markdown.await.log_err();
|
||||
|
||||
channel_buffer.update(&mut cx, |buffer, cx| {
|
||||
buffer.buffer().update(cx, |buffer, cx| {
|
||||
buffer.set_language_registry(language_registry);
|
||||
if let Some(markdown) = markdown {
|
||||
buffer.set_language(Some(markdown), cx);
|
||||
}
|
||||
})
|
||||
});
|
||||
// channel_buffer.update(&mut cx, |buffer, cx| {
|
||||
// buffer.buffer().update(cx, |buffer, cx| {
|
||||
// buffer.set_language_registry(language_registry);
|
||||
// if let Some(markdown) = markdown {
|
||||
// buffer.set_language(Some(markdown), cx);
|
||||
// }
|
||||
// })
|
||||
// });
|
||||
|
||||
pane.update(&mut cx, |pane, cx| {
|
||||
let buffer_id = channel_buffer.read(cx).remote_id(cx);
|
||||
// pane.update(&mut cx, |pane, cx| {
|
||||
// let buffer_id = channel_buffer.read(cx).remote_id(cx);
|
||||
|
||||
let existing_view = pane
|
||||
.items_of_type::<Self>()
|
||||
.find(|view| view.read(cx).channel_buffer.read(cx).remote_id(cx) == buffer_id);
|
||||
// let existing_view = pane
|
||||
// .items_of_type::<Self>()
|
||||
// .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 let Some(existing_view) = existing_view.clone() {
|
||||
if existing_view.read(cx).channel_buffer == channel_buffer {
|
||||
return existing_view;
|
||||
}
|
||||
}
|
||||
// // If this channel buffer is already open in this pane, just return it.
|
||||
// if let Some(existing_view) = existing_view.clone() {
|
||||
// if existing_view.read(cx).channel_buffer == channel_buffer {
|
||||
// return existing_view;
|
||||
// }
|
||||
// }
|
||||
|
||||
let view = cx.add_view(|cx| {
|
||||
let mut this = Self::new(project, channel_store, channel_buffer, cx);
|
||||
this.acknowledge_buffer_version(cx);
|
||||
this
|
||||
});
|
||||
// let view = cx.add_view(|cx| {
|
||||
// let mut this = Self::new(project, channel_store, channel_buffer, cx);
|
||||
// this.acknowledge_buffer_version(cx);
|
||||
// this
|
||||
// });
|
||||
|
||||
// If the pane contained a disconnected view for this channel buffer,
|
||||
// replace that.
|
||||
if let Some(existing_item) = existing_view {
|
||||
if let Some(ix) = pane.index_for_item(&existing_item) {
|
||||
pane.close_item_by_id(existing_item.id(), SaveIntent::Skip, cx)
|
||||
.detach();
|
||||
pane.add_item(Box::new(view.clone()), true, true, Some(ix), cx);
|
||||
}
|
||||
}
|
||||
// // If the pane contained a disconnected view for this channel buffer,
|
||||
// // replace that.
|
||||
// if let Some(existing_item) = existing_view {
|
||||
// if let Some(ix) = pane.index_for_item(&existing_item) {
|
||||
// pane.close_item_by_id(existing_item.id(), SaveIntent::Skip, cx)
|
||||
// .detach();
|
||||
// pane.add_item(Box::new(view.clone()), true, true, Some(ix), cx);
|
||||
// }
|
||||
// }
|
||||
|
||||
view
|
||||
})
|
||||
.ok_or_else(|| anyhow!("pane was dropped"))
|
||||
})
|
||||
}
|
||||
// view
|
||||
// })
|
||||
// .ok_or_else(|| anyhow!("pane was dropped"))
|
||||
// })
|
||||
// }
|
||||
|
||||
pub fn new(
|
||||
project: ModelHandle<Project>,
|
||||
channel_store: ModelHandle<ChannelStore>,
|
||||
channel_buffer: ModelHandle<ChannelBuffer>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Self {
|
||||
let buffer = channel_buffer.read(cx).buffer();
|
||||
let editor = cx.add_view(|cx| {
|
||||
let mut editor = Editor::for_buffer(buffer, None, cx);
|
||||
editor.set_collaboration_hub(Box::new(ChannelBufferCollaborationHub(
|
||||
channel_buffer.clone(),
|
||||
)));
|
||||
editor.set_read_only(
|
||||
!channel_buffer
|
||||
.read(cx)
|
||||
.channel(cx)
|
||||
.is_some_and(|c| c.can_edit_notes()),
|
||||
);
|
||||
editor
|
||||
});
|
||||
let _editor_event_subscription = cx.subscribe(&editor, |_, _, e, cx| cx.emit(e.clone()));
|
||||
// pub fn new(
|
||||
// project: ModelHandle<Project>,
|
||||
// channel_store: ModelHandle<ChannelStore>,
|
||||
// channel_buffer: ModelHandle<ChannelBuffer>,
|
||||
// cx: &mut ViewContext<Self>,
|
||||
// ) -> Self {
|
||||
// let buffer = channel_buffer.read(cx).buffer();
|
||||
// let editor = cx.add_view(|cx| {
|
||||
// let mut editor = Editor::for_buffer(buffer, None, cx);
|
||||
// editor.set_collaboration_hub(Box::new(ChannelBufferCollaborationHub(
|
||||
// channel_buffer.clone(),
|
||||
// )));
|
||||
// editor.set_read_only(
|
||||
// !channel_buffer
|
||||
// .read(cx)
|
||||
// .channel(cx)
|
||||
// .is_some_and(|c| c.can_edit_notes()),
|
||||
// );
|
||||
// editor
|
||||
// });
|
||||
// let _editor_event_subscription = cx.subscribe(&editor, |_, _, e, cx| cx.emit(e.clone()));
|
||||
|
||||
cx.subscribe(&channel_buffer, Self::handle_channel_buffer_event)
|
||||
.detach();
|
||||
// cx.subscribe(&channel_buffer, Self::handle_channel_buffer_event)
|
||||
// .detach();
|
||||
|
||||
Self {
|
||||
editor,
|
||||
project,
|
||||
channel_store,
|
||||
channel_buffer,
|
||||
remote_id: None,
|
||||
_editor_event_subscription,
|
||||
}
|
||||
}
|
||||
// Self {
|
||||
// editor,
|
||||
// project,
|
||||
// channel_store,
|
||||
// channel_buffer,
|
||||
// remote_id: None,
|
||||
// _editor_event_subscription,
|
||||
// }
|
||||
// }
|
||||
|
||||
pub fn channel(&self, cx: &AppContext) -> Option<Arc<Channel>> {
|
||||
self.channel_buffer.read(cx).channel(cx)
|
||||
}
|
||||
// pub fn channel(&self, cx: &AppContext) -> Option<Arc<Channel>> {
|
||||
// self.channel_buffer.read(cx).channel(cx)
|
||||
// }
|
||||
|
||||
fn handle_channel_buffer_event(
|
||||
&mut self,
|
||||
_: ModelHandle<ChannelBuffer>,
|
||||
event: &ChannelBufferEvent,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
match event {
|
||||
ChannelBufferEvent::Disconnected => self.editor.update(cx, |editor, cx| {
|
||||
editor.set_read_only(true);
|
||||
cx.notify();
|
||||
}),
|
||||
ChannelBufferEvent::ChannelChanged => {
|
||||
self.editor.update(cx, |editor, cx| {
|
||||
editor.set_read_only(!self.channel(cx).is_some_and(|c| c.can_edit_notes()));
|
||||
cx.emit(editor::Event::TitleChanged);
|
||||
cx.notify()
|
||||
});
|
||||
}
|
||||
ChannelBufferEvent::BufferEdited => {
|
||||
if cx.is_self_focused() || self.editor.is_focused(cx) {
|
||||
self.acknowledge_buffer_version(cx);
|
||||
} else {
|
||||
self.channel_store.update(cx, |store, cx| {
|
||||
let channel_buffer = self.channel_buffer.read(cx);
|
||||
store.notes_changed(
|
||||
channel_buffer.channel_id,
|
||||
channel_buffer.epoch(),
|
||||
&channel_buffer.buffer().read(cx).version(),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
ChannelBufferEvent::CollaboratorsChanged => {}
|
||||
}
|
||||
}
|
||||
// fn handle_channel_buffer_event(
|
||||
// &mut self,
|
||||
// _: ModelHandle<ChannelBuffer>,
|
||||
// event: &ChannelBufferEvent,
|
||||
// cx: &mut ViewContext<Self>,
|
||||
// ) {
|
||||
// match event {
|
||||
// ChannelBufferEvent::Disconnected => self.editor.update(cx, |editor, cx| {
|
||||
// editor.set_read_only(true);
|
||||
// cx.notify();
|
||||
// }),
|
||||
// ChannelBufferEvent::ChannelChanged => {
|
||||
// self.editor.update(cx, |editor, cx| {
|
||||
// editor.set_read_only(!self.channel(cx).is_some_and(|c| c.can_edit_notes()));
|
||||
// cx.emit(editor::Event::TitleChanged);
|
||||
// cx.notify()
|
||||
// });
|
||||
// }
|
||||
// ChannelBufferEvent::BufferEdited => {
|
||||
// if cx.is_self_focused() || self.editor.is_focused(cx) {
|
||||
// self.acknowledge_buffer_version(cx);
|
||||
// } else {
|
||||
// self.channel_store.update(cx, |store, cx| {
|
||||
// let channel_buffer = self.channel_buffer.read(cx);
|
||||
// store.notes_changed(
|
||||
// channel_buffer.channel_id,
|
||||
// channel_buffer.epoch(),
|
||||
// &channel_buffer.buffer().read(cx).version(),
|
||||
// cx,
|
||||
// )
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// ChannelBufferEvent::CollaboratorsChanged => {}
|
||||
// }
|
||||
// }
|
||||
|
||||
fn acknowledge_buffer_version(&mut self, cx: &mut ViewContext<'_, '_, ChannelView>) {
|
||||
self.channel_store.update(cx, |store, cx| {
|
||||
let channel_buffer = self.channel_buffer.read(cx);
|
||||
store.acknowledge_notes_version(
|
||||
channel_buffer.channel_id,
|
||||
channel_buffer.epoch(),
|
||||
&channel_buffer.buffer().read(cx).version(),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
self.channel_buffer.update(cx, |buffer, cx| {
|
||||
buffer.acknowledge_buffer_version(cx);
|
||||
});
|
||||
}
|
||||
}
|
||||
// fn acknowledge_buffer_version(&mut self, cx: &mut ViewContext<'_, '_, ChannelView>) {
|
||||
// self.channel_store.update(cx, |store, cx| {
|
||||
// let channel_buffer = self.channel_buffer.read(cx);
|
||||
// store.acknowledge_notes_version(
|
||||
// channel_buffer.channel_id,
|
||||
// channel_buffer.epoch(),
|
||||
// &channel_buffer.buffer().read(cx).version(),
|
||||
// cx,
|
||||
// )
|
||||
// });
|
||||
// self.channel_buffer.update(cx, |buffer, cx| {
|
||||
// buffer.acknowledge_buffer_version(cx);
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
impl Entity for ChannelView {
|
||||
type Event = editor::Event;
|
||||
}
|
||||
// impl Entity for ChannelView {
|
||||
// type Event = editor::Event;
|
||||
// }
|
||||
|
||||
impl View for ChannelView {
|
||||
fn ui_name() -> &'static str {
|
||||
"ChannelView"
|
||||
}
|
||||
// impl View for ChannelView {
|
||||
// fn ui_name() -> &'static str {
|
||||
// "ChannelView"
|
||||
// }
|
||||
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
||||
ChildView::new(self.editor.as_any(), cx).into_any()
|
||||
}
|
||||
// fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
||||
// ChildView::new(self.editor.as_any(), cx).into_any()
|
||||
// }
|
||||
|
||||
fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||
if cx.is_self_focused() {
|
||||
self.acknowledge_buffer_version(cx);
|
||||
cx.focus(self.editor.as_any())
|
||||
}
|
||||
}
|
||||
}
|
||||
// fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||
// if cx.is_self_focused() {
|
||||
// self.acknowledge_buffer_version(cx);
|
||||
// cx.focus(self.editor.as_any())
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl Item for ChannelView {
|
||||
fn act_as_type<'a>(
|
||||
&'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
|
||||
}
|
||||
}
|
||||
// impl Item for ChannelView {
|
||||
// fn act_as_type<'a>(
|
||||
// &'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>(
|
||||
&self,
|
||||
_: Option<usize>,
|
||||
style: &theme::Tab,
|
||||
cx: &gpui::AppContext,
|
||||
) -> AnyElement<V> {
|
||||
let label = if let Some(channel) = self.channel(cx) {
|
||||
match (
|
||||
channel.can_edit_notes(),
|
||||
self.channel_buffer.read(cx).is_connected(),
|
||||
) {
|
||||
(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, style.label.to_owned()).into_any()
|
||||
}
|
||||
// fn tab_content<V: 'static>(
|
||||
// &self,
|
||||
// _: Option<usize>,
|
||||
// style: &theme::Tab,
|
||||
// cx: &gpui::AppContext,
|
||||
// ) -> AnyElement<V> {
|
||||
// let label = if let Some(channel) = self.channel(cx) {
|
||||
// match (
|
||||
// channel.can_edit_notes(),
|
||||
// self.channel_buffer.read(cx).is_connected(),
|
||||
// ) {
|
||||
// (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, 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_store.clone(),
|
||||
self.channel_buffer.clone(),
|
||||
cx,
|
||||
))
|
||||
}
|
||||
// fn clone_on_split(&self, _: WorkspaceId, cx: &mut ViewContext<Self>) -> Option<Self> {
|
||||
// Some(Self::new(
|
||||
// self.project.clone(),
|
||||
// self.channel_store.clone(),
|
||||
// self.channel_buffer.clone(),
|
||||
// cx,
|
||||
// ))
|
||||
// }
|
||||
|
||||
fn is_singleton(&self, _cx: &AppContext) -> bool {
|
||||
false
|
||||
}
|
||||
// fn is_singleton(&self, _cx: &AppContext) -> bool {
|
||||
// false
|
||||
// }
|
||||
|
||||
fn navigate(&mut self, data: Box<dyn Any>, cx: &mut ViewContext<Self>) -> bool {
|
||||
self.editor
|
||||
.update(cx, |editor, cx| editor.navigate(data, cx))
|
||||
}
|
||||
// fn navigate(&mut self, data: Box<dyn Any>, cx: &mut ViewContext<Self>) -> bool {
|
||||
// self.editor
|
||||
// .update(cx, |editor, cx| editor.navigate(data, cx))
|
||||
// }
|
||||
|
||||
fn deactivated(&mut self, cx: &mut ViewContext<Self>) {
|
||||
self.editor
|
||||
.update(cx, |editor, cx| Item::deactivated(editor, cx))
|
||||
}
|
||||
// fn deactivated(&mut self, cx: &mut ViewContext<Self>) {
|
||||
// self.editor
|
||||
// .update(cx, |editor, cx| Item::deactivated(editor, cx))
|
||||
// }
|
||||
|
||||
fn set_nav_history(&mut self, history: ItemNavHistory, cx: &mut ViewContext<Self>) {
|
||||
self.editor
|
||||
.update(cx, |editor, cx| Item::set_nav_history(editor, history, cx))
|
||||
}
|
||||
// fn set_nav_history(&mut self, history: ItemNavHistory, cx: &mut ViewContext<Self>) {
|
||||
// self.editor
|
||||
// .update(cx, |editor, cx| Item::set_nav_history(editor, history, cx))
|
||||
// }
|
||||
|
||||
fn as_searchable(&self, _: &ViewHandle<Self>) -> Option<Box<dyn SearchableItemHandle>> {
|
||||
Some(Box::new(self.editor.clone()))
|
||||
}
|
||||
// fn as_searchable(&self, _: &ViewHandle<Self>) -> Option<Box<dyn SearchableItemHandle>> {
|
||||
// Some(Box::new(self.editor.clone()))
|
||||
// }
|
||||
|
||||
fn show_toolbar(&self) -> bool {
|
||||
true
|
||||
}
|
||||
// fn show_toolbar(&self) -> bool {
|
||||
// true
|
||||
// }
|
||||
|
||||
fn pixel_position_of_cursor(&self, cx: &AppContext) -> Option<Vector2F> {
|
||||
self.editor.read(cx).pixel_position_of_cursor(cx)
|
||||
}
|
||||
// fn pixel_position_of_cursor(&self, cx: &AppContext) -> Option<Vector2F> {
|
||||
// self.editor.read(cx).pixel_position_of_cursor(cx)
|
||||
// }
|
||||
|
||||
fn to_item_events(event: &Self::Event) -> SmallVec<[ItemEvent; 2]> {
|
||||
editor::Editor::to_item_events(event)
|
||||
}
|
||||
}
|
||||
// fn to_item_events(event: &Self::Event) -> SmallVec<[ItemEvent; 2]> {
|
||||
// editor::Editor::to_item_events(event)
|
||||
// }
|
||||
// }
|
||||
|
||||
impl FollowableItem for ChannelView {
|
||||
fn remote_id(&self) -> Option<workspace::ViewId> {
|
||||
self.remote_id
|
||||
}
|
||||
// impl FollowableItem for ChannelView {
|
||||
// fn remote_id(&self) -> Option<workspace::ViewId> {
|
||||
// self.remote_id
|
||||
// }
|
||||
|
||||
fn to_state_proto(&self, cx: &AppContext) -> Option<proto::view::Variant> {
|
||||
let channel_buffer = self.channel_buffer.read(cx);
|
||||
if !channel_buffer.is_connected() {
|
||||
return None;
|
||||
}
|
||||
// fn to_state_proto(&self, cx: &AppContext) -> Option<proto::view::Variant> {
|
||||
// let channel_buffer = self.channel_buffer.read(cx);
|
||||
// if !channel_buffer.is_connected() {
|
||||
// return None;
|
||||
// }
|
||||
|
||||
Some(proto::view::Variant::ChannelView(
|
||||
proto::view::ChannelView {
|
||||
channel_id: channel_buffer.channel_id,
|
||||
editor: if let Some(proto::view::Variant::Editor(proto)) =
|
||||
self.editor.read(cx).to_state_proto(cx)
|
||||
{
|
||||
Some(proto)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
// Some(proto::view::Variant::ChannelView(
|
||||
// proto::view::ChannelView {
|
||||
// channel_id: channel_buffer.channel_id,
|
||||
// editor: if let Some(proto::view::Variant::Editor(proto)) =
|
||||
// self.editor.read(cx).to_state_proto(cx)
|
||||
// {
|
||||
// Some(proto)
|
||||
// } else {
|
||||
// None
|
||||
// },
|
||||
// },
|
||||
// ))
|
||||
// }
|
||||
|
||||
fn from_state_proto(
|
||||
pane: ViewHandle<workspace::Pane>,
|
||||
workspace: ViewHandle<workspace::Workspace>,
|
||||
remote_id: workspace::ViewId,
|
||||
state: &mut Option<proto::view::Variant>,
|
||||
cx: &mut AppContext,
|
||||
) -> Option<gpui::Task<anyhow::Result<ViewHandle<Self>>>> {
|
||||
let Some(proto::view::Variant::ChannelView(_)) = state else {
|
||||
return None;
|
||||
};
|
||||
let Some(proto::view::Variant::ChannelView(state)) = state.take() else {
|
||||
unreachable!()
|
||||
};
|
||||
// fn from_state_proto(
|
||||
// pane: ViewHandle<workspace::Pane>,
|
||||
// workspace: ViewHandle<workspace::Workspace>,
|
||||
// remote_id: workspace::ViewId,
|
||||
// state: &mut Option<proto::view::Variant>,
|
||||
// cx: &mut AppContext,
|
||||
// ) -> Option<gpui::Task<anyhow::Result<ViewHandle<Self>>>> {
|
||||
// let Some(proto::view::Variant::ChannelView(_)) = state else {
|
||||
// return None;
|
||||
// };
|
||||
// let Some(proto::view::Variant::ChannelView(state)) = state.take() else {
|
||||
// unreachable!()
|
||||
// };
|
||||
|
||||
let open = ChannelView::open_in_pane(state.channel_id, pane, workspace, cx);
|
||||
// let open = ChannelView::open_in_pane(state.channel_id, pane, workspace, cx);
|
||||
|
||||
Some(cx.spawn(|mut cx| async move {
|
||||
let this = open.await?;
|
||||
// Some(cx.spawn(|mut cx| async move {
|
||||
// let this = open.await?;
|
||||
|
||||
let task = this
|
||||
.update(&mut cx, |this, cx| {
|
||||
this.remote_id = Some(remote_id);
|
||||
// let task = this
|
||||
// .update(&mut cx, |this, cx| {
|
||||
// this.remote_id = Some(remote_id);
|
||||
|
||||
if let Some(state) = state.editor {
|
||||
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!("window was closed"))?;
|
||||
// if let Some(state) = state.editor {
|
||||
// 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!("window was closed"))?;
|
||||
|
||||
if let Some(task) = task {
|
||||
task.await?;
|
||||
}
|
||||
// if let Some(task) = task {
|
||||
// task.await?;
|
||||
// }
|
||||
|
||||
Ok(this)
|
||||
}))
|
||||
}
|
||||
// Ok(this)
|
||||
// }))
|
||||
// }
|
||||
|
||||
fn add_event_to_update_proto(
|
||||
&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 add_event_to_update_proto(
|
||||
// &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(
|
||||
&mut self,
|
||||
project: &ModelHandle<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 apply_update_proto(
|
||||
// &mut self,
|
||||
// project: &ModelHandle<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 set_leader_peer_id(&mut self, leader_peer_id: Option<PeerId>, cx: &mut ViewContext<Self>) {
|
||||
self.editor.update(cx, |editor, cx| {
|
||||
editor.set_leader_peer_id(leader_peer_id, cx)
|
||||
})
|
||||
}
|
||||
// fn set_leader_peer_id(&mut self, leader_peer_id: Option<PeerId>, cx: &mut ViewContext<Self>) {
|
||||
// self.editor.update(cx, |editor, cx| {
|
||||
// editor.set_leader_peer_id(leader_peer_id, cx)
|
||||
// })
|
||||
// }
|
||||
|
||||
fn should_unfollow_on_event(event: &Self::Event, cx: &AppContext) -> bool {
|
||||
Editor::should_unfollow_on_event(event, cx)
|
||||
}
|
||||
// fn should_unfollow_on_event(event: &Self::Event, cx: &AppContext) -> bool {
|
||||
// Editor::should_unfollow_on_event(event, cx)
|
||||
// }
|
||||
|
||||
fn is_project_item(&self, _cx: &AppContext) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
// fn is_project_item(&self, _cx: &AppContext) -> bool {
|
||||
// false
|
||||
// }
|
||||
// }
|
||||
|
||||
struct ChannelBufferCollaborationHub(ModelHandle<ChannelBuffer>);
|
||||
// struct ChannelBufferCollaborationHub(ModelHandle<ChannelBuffer>);
|
||||
|
||||
impl CollaborationHub for ChannelBufferCollaborationHub {
|
||||
fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
|
||||
self.0.read(cx).collaborators()
|
||||
}
|
||||
// impl CollaborationHub for ChannelBufferCollaborationHub {
|
||||
// fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
|
||||
// self.0.read(cx).collaborators()
|
||||
// }
|
||||
|
||||
fn user_participant_indices<'a>(
|
||||
&self,
|
||||
cx: &'a AppContext,
|
||||
) -> &'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()
|
||||
// }
|
||||
// }
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -7,159 +7,147 @@ pub mod notification_panel;
|
||||
pub mod notifications;
|
||||
mod panel_settings;
|
||||
|
||||
use call::{report_call_event_for_room, ActiveCall, Room};
|
||||
use feature_flags::{ChannelsAlpha, FeatureFlagAppExt};
|
||||
use gpui::{
|
||||
actions,
|
||||
elements::{ContainerStyle, Empty, Image},
|
||||
geometry::{
|
||||
rect::RectF,
|
||||
vector::{vec2f, Vector2F},
|
||||
},
|
||||
platform::{Screen, WindowBounds, WindowKind, WindowOptions},
|
||||
AnyElement, AppContext, Element, ImageData, Task,
|
||||
};
|
||||
use std::{rc::Rc, sync::Arc};
|
||||
use theme::AvatarStyle;
|
||||
use util::ResultExt;
|
||||
use workspace::AppState;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub use collab_titlebar_item::CollabTitlebarItem;
|
||||
use gpui::AppContext;
|
||||
pub use panel_settings::{
|
||||
ChatPanelSettings, CollaborationPanelSettings, NotificationPanelSettings,
|
||||
};
|
||||
use settings::Settings;
|
||||
use workspace::AppState;
|
||||
|
||||
actions!(
|
||||
collab,
|
||||
[ToggleScreenSharing, ToggleMute, ToggleDeafen, LeaveCall]
|
||||
);
|
||||
// actions!(
|
||||
// collab,
|
||||
// [ToggleScreenSharing, ToggleMute, ToggleDeafen, LeaveCall]
|
||||
// );
|
||||
|
||||
pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
|
||||
settings::register::<CollaborationPanelSettings>(cx);
|
||||
settings::register::<ChatPanelSettings>(cx);
|
||||
settings::register::<NotificationPanelSettings>(cx);
|
||||
pub fn init(_app_state: &Arc<AppState>, cx: &mut AppContext) {
|
||||
CollaborationPanelSettings::register(cx);
|
||||
ChatPanelSettings::register(cx);
|
||||
NotificationPanelSettings::register(cx);
|
||||
|
||||
vcs_menu::init(cx);
|
||||
// vcs_menu::init(cx);
|
||||
collab_titlebar_item::init(cx);
|
||||
collab_panel::init(cx);
|
||||
chat_panel::init(cx);
|
||||
notifications::init(&app_state, cx);
|
||||
// collab_panel::init(cx);
|
||||
// chat_panel::init(cx);
|
||||
// notifications::init(&app_state, cx);
|
||||
|
||||
cx.add_global_action(toggle_screen_sharing);
|
||||
cx.add_global_action(toggle_mute);
|
||||
cx.add_global_action(toggle_deafen);
|
||||
// cx.add_global_action(toggle_screen_sharing);
|
||||
// cx.add_global_action(toggle_mute);
|
||||
// cx.add_global_action(toggle_deafen);
|
||||
}
|
||||
|
||||
pub fn toggle_screen_sharing(_: &ToggleScreenSharing, cx: &mut AppContext) {
|
||||
let call = ActiveCall::global(cx).read(cx);
|
||||
if let Some(room) = call.room().cloned() {
|
||||
let client = call.client();
|
||||
let toggle_screen_sharing = room.update(cx, |room, cx| {
|
||||
if room.is_screen_sharing() {
|
||||
report_call_event_for_room(
|
||||
"disable screen share",
|
||||
room.id(),
|
||||
room.channel_id(),
|
||||
&client,
|
||||
cx,
|
||||
);
|
||||
Task::ready(room.unshare_screen(cx))
|
||||
} else {
|
||||
report_call_event_for_room(
|
||||
"enable screen share",
|
||||
room.id(),
|
||||
room.channel_id(),
|
||||
&client,
|
||||
cx,
|
||||
);
|
||||
room.share_screen(cx)
|
||||
}
|
||||
});
|
||||
toggle_screen_sharing.detach_and_log_err(cx);
|
||||
}
|
||||
}
|
||||
// pub fn toggle_screen_sharing(_: &ToggleScreenSharing, cx: &mut AppContext) {
|
||||
// let call = ActiveCall::global(cx).read(cx);
|
||||
// if let Some(room) = call.room().cloned() {
|
||||
// let client = call.client();
|
||||
// let toggle_screen_sharing = room.update(cx, |room, cx| {
|
||||
// if room.is_screen_sharing() {
|
||||
// report_call_event_for_room(
|
||||
// "disable screen share",
|
||||
// room.id(),
|
||||
// room.channel_id(),
|
||||
// &client,
|
||||
// cx,
|
||||
// );
|
||||
// Task::ready(room.unshare_screen(cx))
|
||||
// } else {
|
||||
// report_call_event_for_room(
|
||||
// "enable screen share",
|
||||
// room.id(),
|
||||
// room.channel_id(),
|
||||
// &client,
|
||||
// cx,
|
||||
// );
|
||||
// room.share_screen(cx)
|
||||
// }
|
||||
// });
|
||||
// toggle_screen_sharing.detach_and_log_err(cx);
|
||||
// }
|
||||
// }
|
||||
|
||||
pub fn toggle_mute(_: &ToggleMute, cx: &mut AppContext) {
|
||||
let call = ActiveCall::global(cx).read(cx);
|
||||
if let Some(room) = call.room().cloned() {
|
||||
let client = call.client();
|
||||
room.update(cx, |room, cx| {
|
||||
let operation = if room.is_muted(cx) {
|
||||
"enable microphone"
|
||||
} else {
|
||||
"disable microphone"
|
||||
};
|
||||
report_call_event_for_room(operation, room.id(), room.channel_id(), &client, cx);
|
||||
// pub fn toggle_mute(_: &ToggleMute, cx: &mut AppContext) {
|
||||
// let call = ActiveCall::global(cx).read(cx);
|
||||
// if let Some(room) = call.room().cloned() {
|
||||
// let client = call.client();
|
||||
// room.update(cx, |room, cx| {
|
||||
// let operation = if room.is_muted(cx) {
|
||||
// "enable microphone"
|
||||
// } else {
|
||||
// "disable microphone"
|
||||
// };
|
||||
// report_call_event_for_room(operation, room.id(), room.channel_id(), &client, cx);
|
||||
|
||||
room.toggle_mute(cx)
|
||||
})
|
||||
.map(|task| task.detach_and_log_err(cx))
|
||||
.log_err();
|
||||
}
|
||||
}
|
||||
// room.toggle_mute(cx)
|
||||
// })
|
||||
// .map(|task| task.detach_and_log_err(cx))
|
||||
// .log_err();
|
||||
// }
|
||||
// }
|
||||
|
||||
pub fn toggle_deafen(_: &ToggleDeafen, cx: &mut AppContext) {
|
||||
if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
|
||||
room.update(cx, Room::toggle_deafen)
|
||||
.map(|task| task.detach_and_log_err(cx))
|
||||
.log_err();
|
||||
}
|
||||
}
|
||||
// pub fn toggle_deafen(_: &ToggleDeafen, cx: &mut AppContext) {
|
||||
// if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
|
||||
// room.update(cx, Room::toggle_deafen)
|
||||
// .map(|task| task.detach_and_log_err(cx))
|
||||
// .log_err();
|
||||
// }
|
||||
// }
|
||||
|
||||
fn notification_window_options(
|
||||
screen: Rc<dyn Screen>,
|
||||
window_size: Vector2F,
|
||||
) -> WindowOptions<'static> {
|
||||
const NOTIFICATION_PADDING: f32 = 16.;
|
||||
// fn notification_window_options(
|
||||
// screen: Rc<dyn Screen>,
|
||||
// window_size: Vector2F,
|
||||
// ) -> WindowOptions<'static> {
|
||||
// const NOTIFICATION_PADDING: f32 = 16.;
|
||||
|
||||
let screen_bounds = screen.content_bounds();
|
||||
WindowOptions {
|
||||
bounds: WindowBounds::Fixed(RectF::new(
|
||||
screen_bounds.upper_right()
|
||||
+ vec2f(
|
||||
-NOTIFICATION_PADDING - window_size.x(),
|
||||
NOTIFICATION_PADDING,
|
||||
),
|
||||
window_size,
|
||||
)),
|
||||
titlebar: None,
|
||||
center: false,
|
||||
focus: false,
|
||||
show: true,
|
||||
kind: WindowKind::PopUp,
|
||||
is_movable: false,
|
||||
screen: Some(screen),
|
||||
}
|
||||
}
|
||||
// let screen_bounds = screen.content_bounds();
|
||||
// WindowOptions {
|
||||
// bounds: WindowBounds::Fixed(RectF::new(
|
||||
// screen_bounds.upper_right()
|
||||
// + vec2f(
|
||||
// -NOTIFICATION_PADDING - window_size.x(),
|
||||
// NOTIFICATION_PADDING,
|
||||
// ),
|
||||
// window_size,
|
||||
// )),
|
||||
// titlebar: None,
|
||||
// center: false,
|
||||
// focus: false,
|
||||
// show: true,
|
||||
// kind: WindowKind::PopUp,
|
||||
// is_movable: false,
|
||||
// screen: Some(screen),
|
||||
// }
|
||||
// }
|
||||
|
||||
fn render_avatar<T: 'static>(
|
||||
avatar: Option<Arc<ImageData>>,
|
||||
avatar_style: &AvatarStyle,
|
||||
container: ContainerStyle,
|
||||
) -> AnyElement<T> {
|
||||
avatar
|
||||
.map(|avatar| {
|
||||
Image::from_data(avatar)
|
||||
.with_style(avatar_style.image)
|
||||
.aligned()
|
||||
.contained()
|
||||
.with_corner_radius(avatar_style.outer_corner_radius)
|
||||
.constrained()
|
||||
.with_width(avatar_style.outer_width)
|
||||
.with_height(avatar_style.outer_width)
|
||||
.into_any()
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
Empty::new()
|
||||
.constrained()
|
||||
.with_width(avatar_style.outer_width)
|
||||
.into_any()
|
||||
})
|
||||
.contained()
|
||||
.with_style(container)
|
||||
.into_any()
|
||||
}
|
||||
// fn render_avatar<T: 'static>(
|
||||
// avatar: Option<Arc<ImageData>>,
|
||||
// avatar_style: &AvatarStyle,
|
||||
// container: ContainerStyle,
|
||||
// ) -> AnyElement<T> {
|
||||
// avatar
|
||||
// .map(|avatar| {
|
||||
// Image::from_data(avatar)
|
||||
// .with_style(avatar_style.image)
|
||||
// .aligned()
|
||||
// .contained()
|
||||
// .with_corner_radius(avatar_style.outer_corner_radius)
|
||||
// .constrained()
|
||||
// .with_width(avatar_style.outer_width)
|
||||
// .with_height(avatar_style.outer_width)
|
||||
// .into_any()
|
||||
// })
|
||||
// .unwrap_or_else(|| {
|
||||
// Empty::new()
|
||||
// .constrained()
|
||||
// .with_width(avatar_style.outer_width)
|
||||
// .into_any()
|
||||
// })
|
||||
// .contained()
|
||||
// .with_style(container)
|
||||
// .into_any()
|
||||
// }
|
||||
|
||||
fn is_channels_feature_enabled(cx: &gpui::WindowContext<'_>) -> bool {
|
||||
cx.is_staff() || cx.has_flag::<ChannelsAlpha>()
|
||||
}
|
||||
// fn is_channels_feature_enabled(cx: &gpui::WindowContext<'_>) -> bool {
|
||||
// cx.is_staff() || cx.has_flag::<ChannelsAlpha>()
|
||||
// }
|
||||
|
@ -1,113 +1,113 @@
|
||||
use std::ops::Range;
|
||||
// use std::ops::Range;
|
||||
|
||||
use gpui::{
|
||||
geometry::{
|
||||
rect::RectF,
|
||||
vector::{vec2f, Vector2F},
|
||||
},
|
||||
json::ToJson,
|
||||
serde_json::{self, json},
|
||||
AnyElement, Axis, Element, View, ViewContext,
|
||||
};
|
||||
// use gpui::{
|
||||
// geometry::{
|
||||
// rect::RectF,
|
||||
// vector::{vec2f, Vector2F},
|
||||
// },
|
||||
// json::ToJson,
|
||||
// serde_json::{self, json},
|
||||
// AnyElement, Axis, Element, View, ViewContext,
|
||||
// };
|
||||
|
||||
pub(crate) struct FacePile<V: View> {
|
||||
overlap: f32,
|
||||
faces: Vec<AnyElement<V>>,
|
||||
}
|
||||
// pub(crate) struct FacePile<V: View> {
|
||||
// overlap: f32,
|
||||
// faces: Vec<AnyElement<V>>,
|
||||
// }
|
||||
|
||||
impl<V: View> FacePile<V> {
|
||||
pub fn new(overlap: f32) -> Self {
|
||||
Self {
|
||||
overlap,
|
||||
faces: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
// impl<V: View> FacePile<V> {
|
||||
// pub fn new(overlap: f32) -> Self {
|
||||
// Self {
|
||||
// overlap,
|
||||
// faces: Vec::new(),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl<V: View> Element<V> for FacePile<V> {
|
||||
type LayoutState = ();
|
||||
type PaintState = ();
|
||||
// impl<V: View> Element<V> for FacePile<V> {
|
||||
// type LayoutState = ();
|
||||
// type PaintState = ();
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
constraint: gpui::SizeConstraint,
|
||||
view: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
debug_assert!(constraint.max_along(Axis::Horizontal) == f32::INFINITY);
|
||||
// fn layout(
|
||||
// &mut self,
|
||||
// constraint: gpui::SizeConstraint,
|
||||
// view: &mut V,
|
||||
// cx: &mut ViewContext<V>,
|
||||
// ) -> (Vector2F, Self::LayoutState) {
|
||||
// debug_assert!(constraint.max_along(Axis::Horizontal) == f32::INFINITY);
|
||||
|
||||
let mut width = 0.;
|
||||
let mut max_height = 0.;
|
||||
for face in &mut self.faces {
|
||||
let layout = face.layout(constraint, view, cx);
|
||||
width += layout.x();
|
||||
max_height = f32::max(max_height, layout.y());
|
||||
}
|
||||
width -= self.overlap * self.faces.len().saturating_sub(1) as f32;
|
||||
// let mut width = 0.;
|
||||
// let mut max_height = 0.;
|
||||
// for face in &mut self.faces {
|
||||
// let layout = face.layout(constraint, view, cx);
|
||||
// width += layout.x();
|
||||
// max_height = f32::max(max_height, layout.y());
|
||||
// }
|
||||
// width -= self.overlap * self.faces.len().saturating_sub(1) as f32;
|
||||
|
||||
(
|
||||
Vector2F::new(width, max_height.clamp(1., constraint.max.y())),
|
||||
(),
|
||||
)
|
||||
}
|
||||
// (
|
||||
// Vector2F::new(width, max_height.clamp(1., constraint.max.y())),
|
||||
// (),
|
||||
// )
|
||||
// }
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: RectF,
|
||||
visible_bounds: RectF,
|
||||
_layout: &mut Self::LayoutState,
|
||||
view: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Self::PaintState {
|
||||
let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
|
||||
// fn paint(
|
||||
// &mut self,
|
||||
// bounds: RectF,
|
||||
// visible_bounds: RectF,
|
||||
// _layout: &mut Self::LayoutState,
|
||||
// view: &mut V,
|
||||
// cx: &mut ViewContext<V>,
|
||||
// ) -> Self::PaintState {
|
||||
// let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
|
||||
|
||||
let origin_y = bounds.upper_right().y();
|
||||
let mut origin_x = bounds.upper_right().x();
|
||||
// let origin_y = bounds.upper_right().y();
|
||||
// let mut origin_x = bounds.upper_right().x();
|
||||
|
||||
for face in self.faces.iter_mut().rev() {
|
||||
let size = face.size();
|
||||
origin_x -= size.x();
|
||||
let origin_y = origin_y + (bounds.height() - size.y()) / 2.0;
|
||||
// for face in self.faces.iter_mut().rev() {
|
||||
// let size = face.size();
|
||||
// origin_x -= size.x();
|
||||
// let origin_y = origin_y + (bounds.height() - size.y()) / 2.0;
|
||||
|
||||
cx.scene().push_layer(None);
|
||||
face.paint(vec2f(origin_x, origin_y), visible_bounds, view, cx);
|
||||
cx.scene().pop_layer();
|
||||
origin_x += self.overlap;
|
||||
}
|
||||
// cx.scene().push_layer(None);
|
||||
// face.paint(vec2f(origin_x, origin_y), visible_bounds, view, cx);
|
||||
// cx.scene().pop_layer();
|
||||
// origin_x += self.overlap;
|
||||
// }
|
||||
|
||||
()
|
||||
}
|
||||
// ()
|
||||
// }
|
||||
|
||||
fn rect_for_text_range(
|
||||
&self,
|
||||
_: Range<usize>,
|
||||
_: RectF,
|
||||
_: RectF,
|
||||
_: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
_: &V,
|
||||
_: &ViewContext<V>,
|
||||
) -> Option<RectF> {
|
||||
None
|
||||
}
|
||||
// fn rect_for_text_range(
|
||||
// &self,
|
||||
// _: Range<usize>,
|
||||
// _: RectF,
|
||||
// _: RectF,
|
||||
// _: &Self::LayoutState,
|
||||
// _: &Self::PaintState,
|
||||
// _: &V,
|
||||
// _: &ViewContext<V>,
|
||||
// ) -> Option<RectF> {
|
||||
// None
|
||||
// }
|
||||
|
||||
fn debug(
|
||||
&self,
|
||||
bounds: RectF,
|
||||
_: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
_: &V,
|
||||
_: &ViewContext<V>,
|
||||
) -> serde_json::Value {
|
||||
json!({
|
||||
"type": "FacePile",
|
||||
"bounds": bounds.to_json()
|
||||
})
|
||||
}
|
||||
}
|
||||
// fn debug(
|
||||
// &self,
|
||||
// bounds: RectF,
|
||||
// _: &Self::LayoutState,
|
||||
// _: &Self::PaintState,
|
||||
// _: &V,
|
||||
// _: &ViewContext<V>,
|
||||
// ) -> serde_json::Value {
|
||||
// json!({
|
||||
// "type": "FacePile",
|
||||
// "bounds": bounds.to_json()
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
|
||||
impl<V: View> Extend<AnyElement<V>> for FacePile<V> {
|
||||
fn extend<T: IntoIterator<Item = AnyElement<V>>>(&mut self, children: T) {
|
||||
self.faces.extend(children);
|
||||
}
|
||||
}
|
||||
// impl<V: View> Extend<AnyElement<V>> for FacePile<V> {
|
||||
// fn extend<T: IntoIterator<Item = AnyElement<V>>>(&mut self, children: T) {
|
||||
// self.faces.extend(children);
|
||||
// }
|
||||
// }
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,11 @@
|
||||
use gpui::AppContext;
|
||||
use std::sync::Arc;
|
||||
use workspace::AppState;
|
||||
// use gpui::AppContext;
|
||||
// use std::sync::Arc;
|
||||
// use workspace::AppState;
|
||||
|
||||
pub mod incoming_call_notification;
|
||||
pub mod project_shared_notification;
|
||||
// pub mod incoming_call_notification;
|
||||
// pub mod project_shared_notification;
|
||||
|
||||
pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
|
||||
incoming_call_notification::init(app_state, cx);
|
||||
project_shared_notification::init(app_state, cx);
|
||||
}
|
||||
// pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
|
||||
// incoming_call_notification::init(app_state, cx);
|
||||
// project_shared_notification::init(app_state, cx);
|
||||
// }
|
||||
|
@ -1,7 +1,7 @@
|
||||
use anyhow;
|
||||
use schemars::JsonSchema;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use settings::Setting;
|
||||
use settings::Settings;
|
||||
use workspace::dock::DockPosition;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
@ -32,37 +32,37 @@ pub struct PanelSettingsContent {
|
||||
pub default_width: Option<f32>,
|
||||
}
|
||||
|
||||
impl Setting for CollaborationPanelSettings {
|
||||
impl Settings for CollaborationPanelSettings {
|
||||
const KEY: Option<&'static str> = Some("collaboration_panel");
|
||||
type FileContent = PanelSettingsContent;
|
||||
fn load(
|
||||
default_value: &Self::FileContent,
|
||||
user_values: &[&Self::FileContent],
|
||||
_: &gpui::AppContext,
|
||||
_: &mut gpui::AppContext,
|
||||
) -> anyhow::Result<Self> {
|
||||
Self::load_via_json_merge(default_value, user_values)
|
||||
}
|
||||
}
|
||||
|
||||
impl Setting for ChatPanelSettings {
|
||||
impl Settings for ChatPanelSettings {
|
||||
const KEY: Option<&'static str> = Some("chat_panel");
|
||||
type FileContent = PanelSettingsContent;
|
||||
fn load(
|
||||
default_value: &Self::FileContent,
|
||||
user_values: &[&Self::FileContent],
|
||||
_: &gpui::AppContext,
|
||||
_: &mut gpui::AppContext,
|
||||
) -> anyhow::Result<Self> {
|
||||
Self::load_via_json_merge(default_value, user_values)
|
||||
}
|
||||
}
|
||||
|
||||
impl Setting for NotificationPanelSettings {
|
||||
impl Settings for NotificationPanelSettings {
|
||||
const KEY: Option<&'static str> = Some("notification_panel");
|
||||
type FileContent = PanelSettingsContent;
|
||||
fn load(
|
||||
default_value: &Self::FileContent,
|
||||
user_values: &[&Self::FileContent],
|
||||
_: &gpui::AppContext,
|
||||
_: &mut gpui::AppContext,
|
||||
) -> anyhow::Result<Self> {
|
||||
Self::load_via_json_merge(default_value, user_values)
|
||||
}
|
||||
|
@ -36,11 +36,10 @@ use futures::{
|
||||
Future, FutureExt, StreamExt,
|
||||
};
|
||||
use gpui::{
|
||||
actions, div, point, prelude::*, rems, size, Action, AnyModel, AnyView, AnyWeakView,
|
||||
AppContext, AsyncAppContext, AsyncWindowContext, Bounds, Component, Div, Entity, EntityId,
|
||||
EventEmitter, GlobalPixels, KeyContext, Model, ModelContext, ParentComponent, Point, Render,
|
||||
Size, Styled, Subscription, Task, View, ViewContext, WeakView, WindowBounds, WindowContext,
|
||||
WindowHandle, WindowOptions,
|
||||
actions, div, point, prelude::*, size, Action, AnyModel, AnyView, AnyWeakView, AppContext,
|
||||
AsyncAppContext, AsyncWindowContext, Bounds, Div, Entity, EntityId, EventEmitter, GlobalPixels,
|
||||
KeyContext, Model, ModelContext, ParentComponent, Point, Render, Size, Styled, Subscription,
|
||||
Task, View, ViewContext, WeakView, WindowBounds, WindowContext, WindowHandle, WindowOptions,
|
||||
};
|
||||
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem};
|
||||
use itertools::Itertools;
|
||||
@ -68,8 +67,6 @@ use std::{
|
||||
};
|
||||
use theme2::{ActiveTheme, ThemeSettings};
|
||||
pub use toolbar::{ToolbarItemLocation, ToolbarItemView};
|
||||
use ui::TextColor;
|
||||
use ui::{h_stack, Button, ButtonVariant, KeyBinding, Label, TextTooltip};
|
||||
use util::ResultExt;
|
||||
use uuid::Uuid;
|
||||
pub use workspace_settings::{AutosaveSetting, WorkspaceSettings};
|
||||
@ -447,7 +444,7 @@ pub struct Workspace {
|
||||
last_active_view_id: Option<proto::ViewId>,
|
||||
status_bar: View<StatusBar>,
|
||||
modal_layer: View<ModalLayer>,
|
||||
// titlebar_item: Option<AnyViewHandle>,
|
||||
titlebar_item: Option<AnyView>,
|
||||
notifications: Vec<(TypeId, usize, Box<dyn NotificationHandle>)>,
|
||||
project: Model<Project>,
|
||||
follower_states: HashMap<View<Pane>, FollowerState>,
|
||||
@ -660,7 +657,7 @@ impl Workspace {
|
||||
last_active_view_id: None,
|
||||
status_bar,
|
||||
modal_layer,
|
||||
// titlebar_item: None,
|
||||
titlebar_item: None,
|
||||
notifications: Default::default(),
|
||||
left_dock,
|
||||
bottom_dock,
|
||||
@ -1033,15 +1030,14 @@ impl Workspace {
|
||||
&self.app_state.client
|
||||
}
|
||||
|
||||
// todo!()
|
||||
// pub fn set_titlebar_item(&mut self, item: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||
// self.titlebar_item = Some(item);
|
||||
// cx.notify();
|
||||
// }
|
||||
pub fn set_titlebar_item(&mut self, item: AnyView, cx: &mut ViewContext<Self>) {
|
||||
self.titlebar_item = Some(item);
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
// pub fn titlebar_item(&self) -> Option<AnyViewHandle> {
|
||||
// self.titlebar_item.clone()
|
||||
// }
|
||||
pub fn titlebar_item(&self) -> Option<AnyView> {
|
||||
self.titlebar_item.clone()
|
||||
}
|
||||
|
||||
/// Call the given callback with a workspace whose project is local.
|
||||
///
|
||||
@ -2448,75 +2444,6 @@ impl Workspace {
|
||||
// .any(|state| state.leader_id == peer_id)
|
||||
// }
|
||||
|
||||
fn render_titlebar(&self, cx: &mut ViewContext<Self>) -> impl Component<Self> {
|
||||
h_stack()
|
||||
.id("titlebar")
|
||||
.justify_between()
|
||||
.when(
|
||||
!matches!(cx.window_bounds(), WindowBounds::Fullscreen),
|
||||
|s| s.pl_20(),
|
||||
)
|
||||
.w_full()
|
||||
.h(rems(1.75))
|
||||
.bg(cx.theme().colors().title_bar_background)
|
||||
.on_click(|_, event, cx| {
|
||||
if event.up.click_count == 2 {
|
||||
cx.zoom_window();
|
||||
}
|
||||
})
|
||||
.child(
|
||||
h_stack()
|
||||
// TODO - Add player menu
|
||||
.child(
|
||||
div()
|
||||
.id("project_owner_indicator")
|
||||
.child(
|
||||
Button::new("player")
|
||||
.variant(ButtonVariant::Ghost)
|
||||
.color(Some(TextColor::Player(0))),
|
||||
)
|
||||
.tooltip(move |_, cx| {
|
||||
cx.build_view(|cx| TextTooltip::new("Toggle following"))
|
||||
}),
|
||||
)
|
||||
// TODO - Add project menu
|
||||
.child(
|
||||
div()
|
||||
.id("titlebar_project_menu_button")
|
||||
.child(Button::new("project_name").variant(ButtonVariant::Ghost))
|
||||
.tooltip(move |_, cx| {
|
||||
cx.build_view(|cx| TextTooltip::new("Recent Projects"))
|
||||
}),
|
||||
)
|
||||
// TODO - Add git menu
|
||||
.child(
|
||||
div()
|
||||
.id("titlebar_git_menu_button")
|
||||
.child(
|
||||
Button::new("branch_name")
|
||||
.variant(ButtonVariant::Ghost)
|
||||
.color(Some(TextColor::Muted)),
|
||||
)
|
||||
.tooltip(move |_, cx| {
|
||||
// todo!() Replace with real action.
|
||||
#[gpui::action]
|
||||
struct NoAction {}
|
||||
|
||||
cx.build_view(|cx| {
|
||||
TextTooltip::new("Recent Branches")
|
||||
.key_binding(KeyBinding::new(gpui::KeyBinding::new(
|
||||
"cmd-b",
|
||||
NoAction {},
|
||||
None,
|
||||
)))
|
||||
.meta("Only local branches shown")
|
||||
})
|
||||
}),
|
||||
),
|
||||
) // self.titlebar_item
|
||||
.child(h_stack().child(Label::new("Right side titlebar item")))
|
||||
}
|
||||
|
||||
fn active_item_path_changed(&mut self, cx: &mut ViewContext<Self>) {
|
||||
let active_entry = self.active_project_path(cx);
|
||||
self.project
|
||||
@ -3719,7 +3646,7 @@ impl Render for Workspace {
|
||||
.items_start()
|
||||
.text_color(cx.theme().colors().text)
|
||||
.bg(cx.theme().colors().background)
|
||||
.child(self.render_titlebar(cx))
|
||||
.children(self.titlebar_item.clone())
|
||||
.child(
|
||||
// todo! should this be a component a view?
|
||||
div()
|
||||
|
@ -207,7 +207,7 @@ fn main() {
|
||||
// activity_indicator::init(cx);
|
||||
// language_tools::init(cx);
|
||||
call::init(app_state.client.clone(), app_state.user_store.clone(), cx);
|
||||
// collab_ui::init(&app_state, cx);
|
||||
collab_ui::init(&app_state, cx);
|
||||
// feedback::init(cx);
|
||||
// welcome::init(cx);
|
||||
// zed::init(&app_state, cx);
|
||||
|
@ -341,10 +341,6 @@ pub fn initialize_workspace(
|
||||
// workspace.active_pane().clone(),
|
||||
// ));
|
||||
|
||||
// let collab_titlebar_item =
|
||||
// cx.add_view(|cx| CollabTitlebarItem::new(workspace, &workspace_handle, cx));
|
||||
// workspace.set_titlebar_item(collab_titlebar_item.into_any(), cx);
|
||||
|
||||
// let copilot =
|
||||
// cx.add_view(|cx| copilot_button::CopilotButton::new(app_state.fs.clone(), cx));
|
||||
// let diagnostic_summary =
|
||||
|
Loading…
Reference in New Issue
Block a user