diff --git a/crates/client/src/channel_store.rs b/crates/client/src/channel_store.rs index 534bd0b05a..1d3ed24d1b 100644 --- a/crates/client/src/channel_store.rs +++ b/crates/client/src/channel_store.rs @@ -6,8 +6,8 @@ use gpui::{AsyncAppContext, Entity, ModelContext, ModelHandle, Task}; use rpc::{proto, TypedEnvelope}; use std::sync::Arc; -type ChannelId = u64; -type UserId = u64; +pub type ChannelId = u64; +pub type UserId = u64; pub struct ChannelStore { channels: Vec>, diff --git a/crates/collab_ui/src/panel.rs b/crates/collab_ui/src/panel.rs index 667e8d3a5c..4092351a75 100644 --- a/crates/collab_ui/src/panel.rs +++ b/crates/collab_ui/src/panel.rs @@ -42,6 +42,8 @@ use workspace::{ use crate::face_pile::FacePile; +use self::channel_modal::ChannelModal; + #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] struct RemoveChannel { channel_id: u64, @@ -52,9 +54,14 @@ struct NewChannel { channel_id: u64, } +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +struct AddMember { + channel_id: u64, +} + actions!(collab_panel, [ToggleFocus]); -impl_actions!(collab_panel, [RemoveChannel, NewChannel]); +impl_actions!(collab_panel, [RemoveChannel, NewChannel, AddMember]); const CHANNELS_PANEL_KEY: &'static str = "ChannelsPanel"; @@ -69,6 +76,7 @@ pub fn init(_client: Arc, cx: &mut AppContext) { cx.add_action(CollabPanel::confirm); cx.add_action(CollabPanel::remove_channel); cx.add_action(CollabPanel::new_subchannel); + cx.add_action(CollabPanel::add_member); } #[derive(Debug, Default)] @@ -1506,6 +1514,7 @@ impl CollabPanel { vec![ ContextMenuItem::action("New Channel", NewChannel { channel_id }), ContextMenuItem::action("Remove Channel", RemoveChannel { channel_id }), + ContextMenuItem::action("Add member", AddMember { channel_id }), ], cx, ); @@ -1668,6 +1677,18 @@ impl CollabPanel { cx.notify(); } + fn add_member(&mut self, action: &AddMember, cx: &mut ViewContext) { + if let Some(workspace) = self.workspace.upgrade(cx) { + workspace.update(cx, |workspace, cx| { + workspace.toggle_modal(cx, |_, cx| { + cx.add_view(|cx| { + ChannelModal::new(action.channel_id, self.channel_store.clone(), cx) + }) + }) + }); + } + } + fn remove_channel(&mut self, action: &RemoveChannel, cx: &mut ViewContext) { let channel_id = action.channel_id; let channel_store = self.channel_store.clone(); diff --git a/crates/collab_ui/src/panel/channel_modal.rs b/crates/collab_ui/src/panel/channel_modal.rs index aa1b3e5a13..96424114c7 100644 --- a/crates/collab_ui/src/panel/channel_modal.rs +++ b/crates/collab_ui/src/panel/channel_modal.rs @@ -1,5 +1,8 @@ +use client::{ChannelId, ChannelStore}; use editor::Editor; -use gpui::{elements::*, AnyViewHandle, AppContext, Entity, View, ViewContext, ViewHandle}; +use gpui::{ + elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, View, ViewContext, ViewHandle, +}; use menu::Cancel; use workspace::{item::ItemHandle, Modal}; @@ -10,6 +13,10 @@ pub fn init(cx: &mut AppContext) { pub struct ChannelModal { has_focus: bool, filter_editor: ViewHandle, + selection: usize, + list_state: ListState, + channel_store: ModelHandle, + channel_id: ChannelId, } pub enum Event { @@ -21,16 +28,28 @@ impl Entity for ChannelModal { } impl ChannelModal { - pub fn new(cx: &mut ViewContext) -> Self { + pub fn new( + channel_id: ChannelId, + channel_store: ModelHandle, + cx: &mut ViewContext, + ) -> Self { let input_editor = cx.add_view(|cx| { let mut editor = Editor::single_line(None, cx); - editor.set_placeholder_text("Create or add a channel", cx); + editor.set_placeholder_text("Add a member", cx); editor }); + let list_state = ListState::::new(0, Orientation::Top, 1000., move |this, ix, cx| { + Empty::new().into_any() + }); + ChannelModal { has_focus: false, filter_editor: input_editor, + selection: 0, + list_state, + channel_id, + channel_store, } } @@ -49,14 +68,21 @@ impl View for ChannelModal { } fn render(&mut self, cx: &mut gpui::ViewContext<'_, '_, Self>) -> gpui::AnyElement { - let style = theme::current(cx).editor.hint_diagnostic.message.clone(); + let theme = theme::current(cx).clone(); + let style = &theme.collab_panel.modal; let modal_container = theme::current(cx).picker.container.clone(); enum ChannelModal {} MouseEventHandler::::new(0, cx, |_, cx| { Flex::column() .with_child(ChildView::new(self.filter_editor.as_any(), cx)) - .with_child(Label::new("ADD OR BROWSE CHANNELS HERE", style)) + .with_child( + List::new(self.list_state.clone()) + .constrained() + .with_width(style.width) + .flex(1., true) + .into_any(), + ) .contained() .with_style(modal_container) .constrained() diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index 96eac81a50..8f0ceeab88 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -220,6 +220,7 @@ pub struct CopilotAuthAuthorized { pub struct CollabPanel { #[serde(flatten)] pub container: ContainerStyle, + pub modal: ChannelModal, pub user_query_editor: FieldEditor, pub user_query_editor_height: f32, pub leave_call_button: IconButton, @@ -244,6 +245,11 @@ pub struct CollabPanel { pub face_overlap: f32, } +#[derive(Deserialize, Default, JsonSchema)] +pub struct ChannelModal { + pub width: f32, +} + #[derive(Deserialize, Default, JsonSchema)] pub struct ProjectRow { #[serde(flatten)] diff --git a/styles/src/style_tree/channel_modal.ts b/styles/src/style_tree/channel_modal.ts new file mode 100644 index 0000000000..95ae337cbc --- /dev/null +++ b/styles/src/style_tree/channel_modal.ts @@ -0,0 +1,9 @@ +import { useTheme } from "../theme" + +export default function contacts_panel(): any { + const theme = useTheme() + + return { + width: 100, + } +} diff --git a/styles/src/style_tree/collab_panel.ts b/styles/src/style_tree/collab_panel.ts index 3390dd51f8..37145d0c46 100644 --- a/styles/src/style_tree/collab_panel.ts +++ b/styles/src/style_tree/collab_panel.ts @@ -7,6 +7,7 @@ import { } from "./components" import { interactive, toggleable } from "../element" import { useTheme } from "../theme" +import channel_modal from "./channel_modal" export default function contacts_panel(): any { @@ -51,6 +52,7 @@ export default function contacts_panel(): any { } return { + modal: channel_modal(), background: background(layer), padding: { top: 12,