Move placeholder titlebar render to collab_ui

This commit is contained in:
Conrad Irwin
2023-11-15 16:09:21 -07:00
parent 84bcbf1128
commit 793fa6e3a4
15 changed files with 7323 additions and 7316 deletions
Generated
+1
View File
@@ -1864,6 +1864,7 @@ dependencies = [
"theme2",
"time",
"tree-sitter-markdown",
"ui2",
"util",
"workspace2",
"zed_actions2",
+1
View File
@@ -18,6 +18,7 @@ members = [
"crates/collab",
"crates/collab2",
"crates/collab_ui",
"crates/collab_ui2",
"crates/collections",
"crates/command_palette",
"crates/command_palette2",
+1
View File
@@ -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"}
+402 -402
View File
@@ -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
+125 -137
View File
@@ -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>()
// }
+98 -98
View File
@@ -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
+9 -9
View File
@@ -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);
// }
+7 -7
View File
@@ -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)
}
+14 -87
View File
@@ -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()
+1 -1
View File
@@ -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);
-4
View File
@@ -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 =