Move channels panel into collab and rename to collab panel
remove contacts popover and add to collab panel
This commit is contained in:
parent
fe5db3035f
commit
7f9df6dd24
18 changed files with 95 additions and 292 deletions
|
@ -1,12 +1,11 @@
|
|||
use crate::{
|
||||
contact_notification::ContactNotification, contacts_popover, face_pile::FacePile,
|
||||
contact_notification::ContactNotification, face_pile::FacePile,
|
||||
toggle_deafen, toggle_mute, toggle_screen_sharing, LeaveCall, ToggleDeafen, ToggleMute,
|
||||
ToggleScreenSharing,
|
||||
};
|
||||
use call::{ActiveCall, ParticipantLocation, Room};
|
||||
use client::{proto::PeerId, Client, ContactEventKind, SignIn, SignOut, User, UserStore};
|
||||
use clock::ReplicaId;
|
||||
use contacts_popover::ContactsPopover;
|
||||
use context_menu::{ContextMenu, ContextMenuItem};
|
||||
use gpui::{
|
||||
actions,
|
||||
|
@ -33,7 +32,6 @@ const MAX_BRANCH_NAME_LENGTH: usize = 40;
|
|||
actions!(
|
||||
collab,
|
||||
[
|
||||
ToggleContactsMenu,
|
||||
ToggleUserMenu,
|
||||
ToggleProjectMenu,
|
||||
SwitchBranch,
|
||||
|
@ -43,7 +41,6 @@ actions!(
|
|||
);
|
||||
|
||||
pub fn init(cx: &mut AppContext) {
|
||||
cx.add_action(CollabTitlebarItem::toggle_contacts_popover);
|
||||
cx.add_action(CollabTitlebarItem::share_project);
|
||||
cx.add_action(CollabTitlebarItem::unshare_project);
|
||||
cx.add_action(CollabTitlebarItem::toggle_user_menu);
|
||||
|
@ -56,7 +53,6 @@ pub struct CollabTitlebarItem {
|
|||
user_store: ModelHandle<UserStore>,
|
||||
client: Arc<Client>,
|
||||
workspace: WeakViewHandle<Workspace>,
|
||||
contacts_popover: Option<ViewHandle<ContactsPopover>>,
|
||||
branch_popover: Option<ViewHandle<BranchList>>,
|
||||
project_popover: Option<ViewHandle<recent_projects::RecentProjects>>,
|
||||
user_menu: ViewHandle<ContextMenu>,
|
||||
|
@ -109,7 +105,6 @@ impl View for CollabTitlebarItem {
|
|||
let status = workspace.read(cx).client().status();
|
||||
let status = &*status.borrow();
|
||||
if matches!(status, client::Status::Connected { .. }) {
|
||||
right_container.add_child(self.render_toggle_contacts_button(&theme, cx));
|
||||
let avatar = user.as_ref().and_then(|user| user.avatar.clone());
|
||||
right_container.add_child(self.render_user_menu_button(&theme, avatar, cx));
|
||||
} else {
|
||||
|
@ -184,7 +179,6 @@ impl CollabTitlebarItem {
|
|||
project,
|
||||
user_store,
|
||||
client,
|
||||
contacts_popover: None,
|
||||
user_menu: cx.add_view(|cx| {
|
||||
let view_id = cx.view_id();
|
||||
let mut menu = ContextMenu::new(view_id, cx);
|
||||
|
@ -315,9 +309,6 @@ impl CollabTitlebarItem {
|
|||
}
|
||||
|
||||
fn active_call_changed(&mut self, cx: &mut ViewContext<Self>) {
|
||||
if ActiveCall::global(cx).read(cx).room().is_none() {
|
||||
self.contacts_popover = None;
|
||||
}
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
|
@ -337,32 +328,6 @@ impl CollabTitlebarItem {
|
|||
.log_err();
|
||||
}
|
||||
|
||||
pub fn toggle_contacts_popover(&mut self, _: &ToggleContactsMenu, cx: &mut ViewContext<Self>) {
|
||||
if self.contacts_popover.take().is_none() {
|
||||
let view = cx.add_view(|cx| {
|
||||
ContactsPopover::new(
|
||||
self.project.clone(),
|
||||
self.user_store.clone(),
|
||||
self.workspace.clone(),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
cx.subscribe(&view, |this, _, event, cx| {
|
||||
match event {
|
||||
contacts_popover::Event::Dismissed => {
|
||||
this.contacts_popover = None;
|
||||
}
|
||||
}
|
||||
|
||||
cx.notify();
|
||||
})
|
||||
.detach();
|
||||
self.contacts_popover = Some(view);
|
||||
}
|
||||
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
pub fn toggle_user_menu(&mut self, _: &ToggleUserMenu, cx: &mut ViewContext<Self>) {
|
||||
self.user_menu.update(cx, |user_menu, cx| {
|
||||
let items = if let Some(_) = self.user_store.read(cx).current_user() {
|
||||
|
@ -519,79 +484,7 @@ impl CollabTitlebarItem {
|
|||
}
|
||||
cx.notify();
|
||||
}
|
||||
fn render_toggle_contacts_button(
|
||||
&self,
|
||||
theme: &Theme,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> AnyElement<Self> {
|
||||
let titlebar = &theme.titlebar;
|
||||
|
||||
let badge = if self
|
||||
.user_store
|
||||
.read(cx)
|
||||
.incoming_contact_requests()
|
||||
.is_empty()
|
||||
{
|
||||
None
|
||||
} else {
|
||||
Some(
|
||||
Empty::new()
|
||||
.collapsed()
|
||||
.contained()
|
||||
.with_style(titlebar.toggle_contacts_badge)
|
||||
.contained()
|
||||
.with_margin_left(
|
||||
titlebar
|
||||
.toggle_contacts_button
|
||||
.inactive_state()
|
||||
.default
|
||||
.icon_width,
|
||||
)
|
||||
.with_margin_top(
|
||||
titlebar
|
||||
.toggle_contacts_button
|
||||
.inactive_state()
|
||||
.default
|
||||
.icon_width,
|
||||
)
|
||||
.aligned(),
|
||||
)
|
||||
};
|
||||
|
||||
Stack::new()
|
||||
.with_child(
|
||||
MouseEventHandler::<ToggleContactsMenu, Self>::new(0, cx, |state, _| {
|
||||
let style = titlebar
|
||||
.toggle_contacts_button
|
||||
.in_state(self.contacts_popover.is_some())
|
||||
.style_for(state);
|
||||
Svg::new("icons/radix/person.svg")
|
||||
.with_color(style.color)
|
||||
.constrained()
|
||||
.with_width(style.icon_width)
|
||||
.aligned()
|
||||
.constrained()
|
||||
.with_width(style.button_width)
|
||||
.with_height(style.button_width)
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||
this.toggle_contacts_popover(&Default::default(), cx)
|
||||
})
|
||||
.with_tooltip::<ToggleContactsMenu>(
|
||||
0,
|
||||
"Show contacts menu".into(),
|
||||
Some(Box::new(ToggleContactsMenu)),
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
),
|
||||
)
|
||||
.with_children(badge)
|
||||
.with_children(self.render_contacts_popover_host(titlebar, cx))
|
||||
.into_any()
|
||||
}
|
||||
fn render_toggle_screen_sharing_button(
|
||||
&self,
|
||||
theme: &Theme,
|
||||
|
@ -923,23 +816,6 @@ impl CollabTitlebarItem {
|
|||
.into_any()
|
||||
}
|
||||
|
||||
fn render_contacts_popover_host<'a>(
|
||||
&'a self,
|
||||
_theme: &'a theme::Titlebar,
|
||||
cx: &'a ViewContext<Self>,
|
||||
) -> Option<AnyElement<Self>> {
|
||||
self.contacts_popover.as_ref().map(|popover| {
|
||||
Overlay::new(ChildView::new(popover, cx))
|
||||
.with_fit_mode(OverlayFitMode::SwitchAnchor)
|
||||
.with_anchor_corner(AnchorCorner::TopLeft)
|
||||
.with_z_index(999)
|
||||
.aligned()
|
||||
.bottom()
|
||||
.right()
|
||||
.into_any()
|
||||
})
|
||||
}
|
||||
|
||||
fn render_collaborators(
|
||||
&self,
|
||||
workspace: &ViewHandle<Workspace>,
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
mod collab_titlebar_item;
|
||||
mod contact_finder;
|
||||
mod contact_list;
|
||||
mod contact_notification;
|
||||
mod contacts_popover;
|
||||
mod face_pile;
|
||||
mod incoming_call_notification;
|
||||
mod notifications;
|
||||
mod project_shared_notification;
|
||||
mod sharing_status_indicator;
|
||||
pub mod panel;
|
||||
|
||||
use call::{ActiveCall, Room};
|
||||
pub use collab_titlebar_item::{CollabTitlebarItem, ToggleContactsMenu};
|
||||
pub use collab_titlebar_item::CollabTitlebarItem;
|
||||
use gpui::{actions, AppContext, Task};
|
||||
use std::sync::Arc;
|
||||
use util::ResultExt;
|
||||
|
@ -24,9 +22,7 @@ actions!(
|
|||
pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
|
||||
vcs_menu::init(cx);
|
||||
collab_titlebar_item::init(cx);
|
||||
contact_list::init(cx);
|
||||
contact_finder::init(cx);
|
||||
contacts_popover::init(cx);
|
||||
panel::init(app_state.client.clone(), cx);
|
||||
incoming_call_notification::init(&app_state, cx);
|
||||
project_shared_notification::init(&app_state, cx);
|
||||
sharing_status_indicator::init(cx);
|
||||
|
|
247
crates/collab_ui/src/panel.rs
Normal file
247
crates/collab_ui/src/panel.rs
Normal file
|
@ -0,0 +1,247 @@
|
|||
mod contacts;
|
||||
mod panel_settings;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::Result;
|
||||
use client::Client;
|
||||
use context_menu::ContextMenu;
|
||||
use db::kvp::KEY_VALUE_STORE;
|
||||
use gpui::{
|
||||
actions,
|
||||
elements::{ChildView, Flex, Label, ParentElement, Stack},
|
||||
serde_json, AppContext, AsyncAppContext, Element, Entity, Task, View, ViewContext, ViewHandle,
|
||||
WeakViewHandle,
|
||||
};
|
||||
use project::Fs;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use settings::SettingsStore;
|
||||
use util::{ResultExt, TryFutureExt};
|
||||
use workspace::{
|
||||
dock::{DockPosition, Panel},
|
||||
Workspace,
|
||||
};
|
||||
|
||||
use self::{
|
||||
contacts::Contacts,
|
||||
panel_settings::{ChannelsPanelDockPosition, ChannelsPanelSettings},
|
||||
};
|
||||
|
||||
actions!(collab_panel, [ToggleFocus]);
|
||||
|
||||
const CHANNELS_PANEL_KEY: &'static str = "ChannelsPanel";
|
||||
|
||||
pub fn init(_client: Arc<Client>, cx: &mut AppContext) {
|
||||
settings::register::<panel_settings::ChannelsPanelSettings>(cx);
|
||||
contacts::init(cx);
|
||||
}
|
||||
|
||||
pub struct CollabPanel {
|
||||
width: Option<f32>,
|
||||
fs: Arc<dyn Fs>,
|
||||
has_focus: bool,
|
||||
pending_serialization: Task<Option<()>>,
|
||||
context_menu: ViewHandle<ContextMenu>,
|
||||
contacts: ViewHandle<contacts::Contacts>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct SerializedChannelsPanel {
|
||||
width: Option<f32>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Event {
|
||||
DockPositionChanged,
|
||||
Focus,
|
||||
}
|
||||
|
||||
impl Entity for CollabPanel {
|
||||
type Event = Event;
|
||||
}
|
||||
|
||||
impl CollabPanel {
|
||||
pub fn new(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) -> ViewHandle<Self> {
|
||||
cx.add_view(|cx| {
|
||||
let view_id = cx.view_id();
|
||||
|
||||
let this = Self {
|
||||
width: None,
|
||||
has_focus: false,
|
||||
fs: workspace.app_state().fs.clone(),
|
||||
pending_serialization: Task::ready(None),
|
||||
context_menu: cx.add_view(|cx| ContextMenu::new(view_id, cx)),
|
||||
contacts: cx.add_view(|cx| {
|
||||
Contacts::new(
|
||||
workspace.project().clone(),
|
||||
workspace.user_store().clone(),
|
||||
workspace.weak_handle(),
|
||||
cx,
|
||||
)
|
||||
}),
|
||||
};
|
||||
|
||||
// Update the dock position when the setting changes.
|
||||
let mut old_dock_position = this.position(cx);
|
||||
cx.observe_global::<SettingsStore, _>(move |this: &mut CollabPanel, cx| {
|
||||
let new_dock_position = this.position(cx);
|
||||
if new_dock_position != old_dock_position {
|
||||
old_dock_position = new_dock_position;
|
||||
cx.emit(Event::DockPositionChanged);
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
this
|
||||
})
|
||||
}
|
||||
|
||||
pub fn load(
|
||||
workspace: WeakViewHandle<Workspace>,
|
||||
cx: AsyncAppContext,
|
||||
) -> Task<Result<ViewHandle<Self>>> {
|
||||
cx.spawn(|mut cx| async move {
|
||||
let serialized_panel = if let Some(panel) = cx
|
||||
.background()
|
||||
.spawn(async move { KEY_VALUE_STORE.read_kvp(CHANNELS_PANEL_KEY) })
|
||||
.await
|
||||
.log_err()
|
||||
.flatten()
|
||||
{
|
||||
Some(serde_json::from_str::<SerializedChannelsPanel>(&panel)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
workspace.update(&mut cx, |workspace, cx| {
|
||||
let panel = CollabPanel::new(workspace, cx);
|
||||
if let Some(serialized_panel) = serialized_panel {
|
||||
panel.update(cx, |panel, cx| {
|
||||
panel.width = serialized_panel.width;
|
||||
cx.notify();
|
||||
});
|
||||
}
|
||||
panel
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn serialize(&mut self, cx: &mut ViewContext<Self>) {
|
||||
let width = self.width;
|
||||
self.pending_serialization = cx.background().spawn(
|
||||
async move {
|
||||
KEY_VALUE_STORE
|
||||
.write_kvp(
|
||||
CHANNELS_PANEL_KEY.into(),
|
||||
serde_json::to_string(&SerializedChannelsPanel { width })?,
|
||||
)
|
||||
.await?;
|
||||
anyhow::Ok(())
|
||||
}
|
||||
.log_err(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl View for CollabPanel {
|
||||
fn ui_name() -> &'static str {
|
||||
"ChannelsPanel"
|
||||
}
|
||||
|
||||
fn focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||
if !self.has_focus {
|
||||
self.has_focus = true;
|
||||
cx.emit(Event::Focus);
|
||||
}
|
||||
}
|
||||
|
||||
fn focus_out(&mut self, _: gpui::AnyViewHandle, _: &mut ViewContext<Self>) {
|
||||
self.has_focus = false;
|
||||
}
|
||||
|
||||
fn render(&mut self, cx: &mut gpui::ViewContext<'_, '_, Self>) -> gpui::AnyElement<Self> {
|
||||
let theme = theme::current(cx).clone();
|
||||
|
||||
enum ChannelsPanelScrollTag {}
|
||||
Stack::new()
|
||||
.with_child(
|
||||
// Full panel column
|
||||
Flex::column()
|
||||
.with_child(
|
||||
Flex::column()
|
||||
.with_child(
|
||||
Flex::row().with_child(
|
||||
Label::new(
|
||||
"Contacts",
|
||||
theme.editor.invalid_information_diagnostic.message.clone(),
|
||||
)
|
||||
.into_any(),
|
||||
),
|
||||
)
|
||||
.with_child(ChildView::new(&self.contacts, cx)),
|
||||
)
|
||||
.scrollable::<ChannelsPanelScrollTag>(0, None, cx),
|
||||
)
|
||||
.with_child(ChildView::new(&self.context_menu, cx))
|
||||
.into_any_named("channels panel")
|
||||
.into_any()
|
||||
}
|
||||
}
|
||||
|
||||
impl Panel for CollabPanel {
|
||||
fn position(&self, cx: &gpui::WindowContext) -> DockPosition {
|
||||
match settings::get::<ChannelsPanelSettings>(cx).dock {
|
||||
ChannelsPanelDockPosition::Left => DockPosition::Left,
|
||||
ChannelsPanelDockPosition::Right => DockPosition::Right,
|
||||
}
|
||||
}
|
||||
|
||||
fn position_is_valid(&self, position: DockPosition) -> bool {
|
||||
matches!(position, DockPosition::Left | DockPosition::Right)
|
||||
}
|
||||
|
||||
fn set_position(&mut self, position: DockPosition, cx: &mut ViewContext<Self>) {
|
||||
settings::update_settings_file::<ChannelsPanelSettings>(
|
||||
self.fs.clone(),
|
||||
cx,
|
||||
move |settings| {
|
||||
let dock = match position {
|
||||
DockPosition::Left | DockPosition::Bottom => ChannelsPanelDockPosition::Left,
|
||||
DockPosition::Right => ChannelsPanelDockPosition::Right,
|
||||
};
|
||||
settings.dock = Some(dock);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn size(&self, cx: &gpui::WindowContext) -> f32 {
|
||||
self.width
|
||||
.unwrap_or_else(|| settings::get::<ChannelsPanelSettings>(cx).default_width)
|
||||
}
|
||||
|
||||
fn set_size(&mut self, size: f32, cx: &mut ViewContext<Self>) {
|
||||
self.width = Some(size);
|
||||
self.serialize(cx);
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn icon_path(&self) -> &'static str {
|
||||
"icons/radix/person.svg"
|
||||
}
|
||||
|
||||
fn icon_tooltip(&self) -> (String, Option<Box<dyn gpui::Action>>) {
|
||||
("Channels Panel".to_string(), Some(Box::new(ToggleFocus)))
|
||||
}
|
||||
|
||||
fn should_change_position_on_event(event: &Self::Event) -> bool {
|
||||
matches!(event, Event::DockPositionChanged)
|
||||
}
|
||||
|
||||
fn has_focus(&self, _cx: &gpui::WindowContext) -> bool {
|
||||
self.has_focus
|
||||
}
|
||||
|
||||
fn is_focus_event(event: &Self::Event) -> bool {
|
||||
matches!(event, Event::Focus)
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
use crate::{
|
||||
contact_finder::{build_contact_finder, ContactFinder},
|
||||
contact_list::ContactList,
|
||||
};
|
||||
mod contact_finder;
|
||||
mod contacts_list;
|
||||
|
||||
use client::UserStore;
|
||||
use gpui::{
|
||||
actions, elements::*, platform::MouseButton, AppContext, Entity, ModelHandle, View,
|
||||
|
@ -11,10 +10,14 @@ use picker::PickerEvent;
|
|||
use project::Project;
|
||||
use workspace::Workspace;
|
||||
|
||||
use self::{contacts_list::ContactList, contact_finder::{ContactFinder, build_contact_finder}};
|
||||
|
||||
actions!(contacts_popover, [ToggleContactFinder]);
|
||||
|
||||
pub fn init(cx: &mut AppContext) {
|
||||
cx.add_action(ContactsPopover::toggle_contact_finder);
|
||||
cx.add_action(Contacts::toggle_contact_finder);
|
||||
contact_finder::init(cx);
|
||||
contacts_list::init(cx);
|
||||
}
|
||||
|
||||
pub enum Event {
|
||||
|
@ -26,7 +29,7 @@ enum Child {
|
|||
ContactFinder(ViewHandle<ContactFinder>),
|
||||
}
|
||||
|
||||
pub struct ContactsPopover {
|
||||
pub struct Contacts {
|
||||
child: Child,
|
||||
project: ModelHandle<Project>,
|
||||
user_store: ModelHandle<UserStore>,
|
||||
|
@ -34,7 +37,7 @@ pub struct ContactsPopover {
|
|||
_subscription: Option<gpui::Subscription>,
|
||||
}
|
||||
|
||||
impl ContactsPopover {
|
||||
impl Contacts {
|
||||
pub fn new(
|
||||
project: ModelHandle<Project>,
|
||||
user_store: ModelHandle<UserStore>,
|
||||
|
@ -61,7 +64,7 @@ impl ContactsPopover {
|
|||
}
|
||||
}
|
||||
|
||||
fn show_contact_finder(&mut self, editor_text: String, cx: &mut ViewContext<ContactsPopover>) {
|
||||
fn show_contact_finder(&mut self, editor_text: String, cx: &mut ViewContext<Contacts>) {
|
||||
let child = cx.add_view(|cx| {
|
||||
let finder = build_contact_finder(self.user_store.clone(), cx);
|
||||
finder.set_query(editor_text, cx);
|
||||
|
@ -75,7 +78,7 @@ impl ContactsPopover {
|
|||
cx.notify();
|
||||
}
|
||||
|
||||
fn show_contact_list(&mut self, editor_text: String, cx: &mut ViewContext<ContactsPopover>) {
|
||||
fn show_contact_list(&mut self, editor_text: String, cx: &mut ViewContext<Contacts>) {
|
||||
let child = cx.add_view(|cx| {
|
||||
ContactList::new(
|
||||
self.project.clone(),
|
||||
|
@ -87,8 +90,8 @@ impl ContactsPopover {
|
|||
});
|
||||
cx.focus(&child);
|
||||
self._subscription = Some(cx.subscribe(&child, |this, _, event, cx| match event {
|
||||
crate::contact_list::Event::Dismissed => cx.emit(Event::Dismissed),
|
||||
crate::contact_list::Event::ToggleContactFinder => {
|
||||
contacts_list::Event::Dismissed => cx.emit(Event::Dismissed),
|
||||
contacts_list::Event::ToggleContactFinder => {
|
||||
this.toggle_contact_finder(&Default::default(), cx)
|
||||
}
|
||||
}));
|
||||
|
@ -97,11 +100,11 @@ impl ContactsPopover {
|
|||
}
|
||||
}
|
||||
|
||||
impl Entity for ContactsPopover {
|
||||
impl Entity for Contacts {
|
||||
type Event = Event;
|
||||
}
|
||||
|
||||
impl View for ContactsPopover {
|
||||
impl View for Contacts {
|
||||
fn ui_name() -> &'static str {
|
||||
"ContactsPopover"
|
||||
}
|
||||
|
@ -113,9 +116,9 @@ impl View for ContactsPopover {
|
|||
Child::ContactFinder(child) => ChildView::new(child, cx),
|
||||
};
|
||||
|
||||
MouseEventHandler::<ContactsPopover, Self>::new(0, cx, |_, _| {
|
||||
MouseEventHandler::<Contacts, Self>::new(0, cx, |_, _| {
|
||||
Flex::column()
|
||||
.with_child(child.flex(1., true))
|
||||
.with_child(child)
|
||||
.contained()
|
||||
.with_style(theme.contacts_popover.container)
|
||||
.constrained()
|
|
@ -1326,12 +1326,11 @@ impl View for ContactList {
|
|||
Flex::column()
|
||||
.with_child(
|
||||
Flex::row()
|
||||
.with_child(
|
||||
ChildView::new(&self.filter_editor, cx)
|
||||
.contained()
|
||||
.with_style(theme.contact_list.user_query_editor.container)
|
||||
.flex(1., true),
|
||||
)
|
||||
// .with_child(
|
||||
// ChildView::new(&self.filter_editor, cx)
|
||||
// .contained()
|
||||
// .with_style(theme.contact_list.user_query_editor.container)
|
||||
// )
|
||||
.with_child(
|
||||
MouseEventHandler::<AddContact, Self>::new(0, cx, |_, _| {
|
||||
render_icon_button(
|
||||
|
@ -1354,7 +1353,7 @@ impl View for ContactList {
|
|||
.constrained()
|
||||
.with_height(theme.contact_list.user_query_editor_height),
|
||||
)
|
||||
.with_child(List::new(self.list_state.clone()).flex(1., false))
|
||||
// .with_child(List::new(self.list_state.clone()))
|
||||
.into_any()
|
||||
}
|
||||
|
37
crates/collab_ui/src/panel/panel_settings.rs
Normal file
37
crates/collab_ui/src/panel/panel_settings.rs
Normal file
|
@ -0,0 +1,37 @@
|
|||
use anyhow;
|
||||
use schemars::JsonSchema;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use settings::Setting;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum ChannelsPanelDockPosition {
|
||||
Left,
|
||||
Right,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct ChannelsPanelSettings {
|
||||
pub dock: ChannelsPanelDockPosition,
|
||||
pub default_width: f32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)]
|
||||
pub struct ChannelsPanelSettingsContent {
|
||||
pub dock: Option<ChannelsPanelDockPosition>,
|
||||
pub default_width: Option<f32>,
|
||||
}
|
||||
|
||||
impl Setting for ChannelsPanelSettings {
|
||||
const KEY: Option<&'static str> = Some("channels_panel");
|
||||
|
||||
type FileContent = ChannelsPanelSettingsContent;
|
||||
|
||||
fn load(
|
||||
default_value: &Self::FileContent,
|
||||
user_values: &[&Self::FileContent],
|
||||
_: &gpui::AppContext,
|
||||
) -> anyhow::Result<Self> {
|
||||
Self::load_via_json_merge(default_value, user_values)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue