Get ChannelModal opening
This commit is contained in:
parent
63b65b2b2e
commit
859f2d2862
4 changed files with 403 additions and 406 deletions
|
@ -1,5 +1,5 @@
|
|||
#![allow(unused)]
|
||||
// mod channel_modal;
|
||||
mod channel_modal;
|
||||
mod contact_finder;
|
||||
|
||||
// use crate::{
|
||||
|
@ -192,6 +192,8 @@ use workspace::{
|
|||
|
||||
use crate::{face_pile::FacePile, CollaborationPanelSettings};
|
||||
|
||||
use self::channel_modal::ChannelModal;
|
||||
|
||||
pub fn init(cx: &mut AppContext) {
|
||||
cx.observe_new_views(|workspace: &mut Workspace, _| {
|
||||
workspace.register_action(|workspace, _: &ToggleFocus, cx| {
|
||||
|
@ -2058,13 +2060,11 @@ impl CollabPanel {
|
|||
}
|
||||
|
||||
fn invite_members(&mut self, channel_id: ChannelId, cx: &mut ViewContext<Self>) {
|
||||
todo!();
|
||||
// self.show_channel_modal(channel_id, channel_modal::Mode::InviteMembers, cx);
|
||||
self.show_channel_modal(channel_id, channel_modal::Mode::InviteMembers, cx);
|
||||
}
|
||||
|
||||
fn manage_members(&mut self, channel_id: ChannelId, cx: &mut ViewContext<Self>) {
|
||||
todo!();
|
||||
// self.show_channel_modal(channel_id, channel_modal::Mode::ManageMembers, cx);
|
||||
self.show_channel_modal(channel_id, channel_modal::Mode::ManageMembers, cx);
|
||||
}
|
||||
|
||||
fn remove_selected_channel(&mut self, _: &Remove, cx: &mut ViewContext<Self>) {
|
||||
|
@ -2156,38 +2156,36 @@ impl CollabPanel {
|
|||
})
|
||||
}
|
||||
|
||||
// fn show_channel_modal(
|
||||
// &mut self,
|
||||
// channel_id: ChannelId,
|
||||
// mode: channel_modal::Mode,
|
||||
// cx: &mut ViewContext<Self>,
|
||||
// ) {
|
||||
// let workspace = self.workspace.clone();
|
||||
// let user_store = self.user_store.clone();
|
||||
// let channel_store = self.channel_store.clone();
|
||||
// let members = self.channel_store.update(cx, |channel_store, cx| {
|
||||
// channel_store.get_channel_member_details(channel_id, cx)
|
||||
// });
|
||||
fn show_channel_modal(
|
||||
&mut self,
|
||||
channel_id: ChannelId,
|
||||
mode: channel_modal::Mode,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
let workspace = self.workspace.clone();
|
||||
let user_store = self.user_store.clone();
|
||||
let channel_store = self.channel_store.clone();
|
||||
let members = self.channel_store.update(cx, |channel_store, cx| {
|
||||
channel_store.get_channel_member_details(channel_id, cx)
|
||||
});
|
||||
|
||||
// cx.spawn(|_, mut cx| async move {
|
||||
// let members = members.await?;
|
||||
// workspace.update(&mut cx, |workspace, cx| {
|
||||
// workspace.toggle_modal(cx, |_, cx| {
|
||||
// cx.add_view(|cx| {
|
||||
// ChannelModal::new(
|
||||
// user_store.clone(),
|
||||
// channel_store.clone(),
|
||||
// channel_id,
|
||||
// mode,
|
||||
// members,
|
||||
// cx,
|
||||
// )
|
||||
// })
|
||||
// });
|
||||
// })
|
||||
// })
|
||||
// .detach();
|
||||
// }
|
||||
cx.spawn(|_, mut cx| async move {
|
||||
let members = members.await?;
|
||||
workspace.update(&mut cx, |workspace, cx| {
|
||||
workspace.toggle_modal(cx, |cx| {
|
||||
ChannelModal::new(
|
||||
user_store.clone(),
|
||||
channel_store.clone(),
|
||||
channel_id,
|
||||
mode,
|
||||
members,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
})
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
// fn remove_selected_channel(&mut self, action: &RemoveChannel, cx: &mut ViewContext<Self>) {
|
||||
// self.remove_channel(action.channel_id, cx)
|
||||
|
|
|
@ -3,58 +3,54 @@ use client::{
|
|||
proto::{self, ChannelRole, ChannelVisibility},
|
||||
User, UserId, UserStore,
|
||||
};
|
||||
use context_menu::{ContextMenu, ContextMenuItem};
|
||||
use fuzzy::{match_strings, StringMatchCandidate};
|
||||
use gpui::{
|
||||
actions,
|
||||
elements::*,
|
||||
platform::{CursorStyle, MouseButton},
|
||||
AppContext, ClipboardItem, Entity, ModelHandle, MouseState, Task, View, ViewContext,
|
||||
ViewHandle,
|
||||
actions, div, AppContext, ClipboardItem, DismissEvent, Div, Entity, EventEmitter,
|
||||
FocusableView, Model, ParentElement, Render, Styled, Task, View, ViewContext, VisualContext,
|
||||
WeakView,
|
||||
};
|
||||
use picker::{Picker, PickerDelegate, PickerEvent};
|
||||
use picker::{Picker, PickerDelegate};
|
||||
use std::sync::Arc;
|
||||
use ui::v_stack;
|
||||
use util::TryFutureExt;
|
||||
use workspace::Modal;
|
||||
|
||||
actions!(
|
||||
channel_modal,
|
||||
[
|
||||
SelectNextControl,
|
||||
ToggleMode,
|
||||
ToggleMemberAdmin,
|
||||
RemoveMember
|
||||
]
|
||||
SelectNextControl,
|
||||
ToggleMode,
|
||||
ToggleMemberAdmin,
|
||||
RemoveMember
|
||||
);
|
||||
|
||||
pub fn init(cx: &mut AppContext) {
|
||||
Picker::<ChannelModalDelegate>::init(cx);
|
||||
cx.add_action(ChannelModal::toggle_mode);
|
||||
cx.add_action(ChannelModal::toggle_member_admin);
|
||||
cx.add_action(ChannelModal::remove_member);
|
||||
cx.add_action(ChannelModal::dismiss);
|
||||
}
|
||||
// pub fn init(cx: &mut AppContext) {
|
||||
// Picker::<ChannelModalDelegate>::init(cx);
|
||||
// cx.add_action(ChannelModal::toggle_mode);
|
||||
// cx.add_action(ChannelModal::toggle_member_admin);
|
||||
// cx.add_action(ChannelModal::remove_member);
|
||||
// cx.add_action(ChannelModal::dismiss);
|
||||
// }
|
||||
|
||||
pub struct ChannelModal {
|
||||
picker: ViewHandle<Picker<ChannelModalDelegate>>,
|
||||
channel_store: ModelHandle<ChannelStore>,
|
||||
picker: View<Picker<ChannelModalDelegate>>,
|
||||
channel_store: Model<ChannelStore>,
|
||||
channel_id: ChannelId,
|
||||
has_focus: bool,
|
||||
}
|
||||
|
||||
impl ChannelModal {
|
||||
pub fn new(
|
||||
user_store: ModelHandle<UserStore>,
|
||||
channel_store: ModelHandle<ChannelStore>,
|
||||
user_store: Model<UserStore>,
|
||||
channel_store: Model<ChannelStore>,
|
||||
channel_id: ChannelId,
|
||||
mode: Mode,
|
||||
members: Vec<ChannelMembership>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Self {
|
||||
cx.observe(&channel_store, |_, _, cx| cx.notify()).detach();
|
||||
let picker = cx.add_view(|cx| {
|
||||
let channel_modal = cx.view().downgrade();
|
||||
let picker = cx.build_view(|cx| {
|
||||
Picker::new(
|
||||
ChannelModalDelegate {
|
||||
channel_modal,
|
||||
matching_users: Vec::new(),
|
||||
matching_member_indices: Vec::new(),
|
||||
selected_index: 0,
|
||||
|
@ -64,20 +60,17 @@ impl ChannelModal {
|
|||
match_candidates: Vec::new(),
|
||||
members,
|
||||
mode,
|
||||
context_menu: cx.add_view(|cx| {
|
||||
let mut menu = ContextMenu::new(cx.view_id(), cx);
|
||||
menu.set_position_mode(OverlayPositionMode::Local);
|
||||
menu
|
||||
}),
|
||||
// context_menu: cx.add_view(|cx| {
|
||||
// let mut menu = ContextMenu::new(cx.view_id(), cx);
|
||||
// menu.set_position_mode(OverlayPositionMode::Local);
|
||||
// menu
|
||||
// }),
|
||||
},
|
||||
cx,
|
||||
)
|
||||
.with_theme(|theme| theme.collab_panel.tabbed_modal.picker.clone())
|
||||
});
|
||||
|
||||
cx.subscribe(&picker, |_, _, e, cx| cx.emit(*e)).detach();
|
||||
|
||||
let has_focus = picker.read(cx).has_focus();
|
||||
let has_focus = picker.focus_handle(cx).contains_focused(cx);
|
||||
|
||||
Self {
|
||||
picker,
|
||||
|
@ -88,7 +81,7 @@ impl ChannelModal {
|
|||
}
|
||||
|
||||
fn toggle_mode(&mut self, _: &ToggleMode, cx: &mut ViewContext<Self>) {
|
||||
let mode = match self.picker.read(cx).delegate().mode {
|
||||
let mode = match self.picker.read(cx).delegate.mode {
|
||||
Mode::ManageMembers => Mode::InviteMembers,
|
||||
Mode::InviteMembers => Mode::ManageMembers,
|
||||
};
|
||||
|
@ -103,20 +96,20 @@ impl ChannelModal {
|
|||
let mut members = channel_store
|
||||
.update(&mut cx, |channel_store, cx| {
|
||||
channel_store.get_channel_member_details(channel_id, cx)
|
||||
})
|
||||
})?
|
||||
.await?;
|
||||
|
||||
members.sort_by(|a, b| a.sort_key().cmp(&b.sort_key()));
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.picker
|
||||
.update(cx, |picker, _| picker.delegate_mut().members = members);
|
||||
.update(cx, |picker, _| picker.delegate.members = members);
|
||||
})?;
|
||||
}
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.picker.update(cx, |picker, cx| {
|
||||
let delegate = picker.delegate_mut();
|
||||
let delegate = &mut picker.delegate;
|
||||
delegate.mode = mode;
|
||||
delegate.selected_index = 0;
|
||||
picker.set_query("", cx);
|
||||
|
@ -131,203 +124,194 @@ impl ChannelModal {
|
|||
|
||||
fn toggle_member_admin(&mut self, _: &ToggleMemberAdmin, cx: &mut ViewContext<Self>) {
|
||||
self.picker.update(cx, |picker, cx| {
|
||||
picker.delegate_mut().toggle_selected_member_admin(cx);
|
||||
picker.delegate.toggle_selected_member_admin(cx);
|
||||
})
|
||||
}
|
||||
|
||||
fn remove_member(&mut self, _: &RemoveMember, cx: &mut ViewContext<Self>) {
|
||||
self.picker.update(cx, |picker, cx| {
|
||||
picker.delegate_mut().remove_selected_member(cx);
|
||||
picker.delegate.remove_selected_member(cx);
|
||||
});
|
||||
}
|
||||
|
||||
fn dismiss(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
|
||||
cx.emit(PickerEvent::Dismiss);
|
||||
cx.emit(DismissEvent);
|
||||
}
|
||||
}
|
||||
|
||||
impl Entity for ChannelModal {
|
||||
type Event = PickerEvent;
|
||||
}
|
||||
impl EventEmitter<DismissEvent> for ChannelModal {}
|
||||
|
||||
impl View for ChannelModal {
|
||||
fn ui_name() -> &'static str {
|
||||
"ChannelModal"
|
||||
}
|
||||
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
||||
let theme = &theme::current(cx).collab_panel.tabbed_modal;
|
||||
|
||||
let mode = self.picker.read(cx).delegate().mode;
|
||||
let Some(channel) = self.channel_store.read(cx).channel_for_id(self.channel_id) else {
|
||||
return Empty::new().into_any();
|
||||
};
|
||||
|
||||
enum InviteMembers {}
|
||||
enum ManageMembers {}
|
||||
|
||||
fn render_mode_button<T: 'static>(
|
||||
mode: Mode,
|
||||
text: &'static str,
|
||||
current_mode: Mode,
|
||||
theme: &theme::TabbedModal,
|
||||
cx: &mut ViewContext<ChannelModal>,
|
||||
) -> AnyElement<ChannelModal> {
|
||||
let active = mode == current_mode;
|
||||
MouseEventHandler::new::<T, _>(0, cx, move |state, _| {
|
||||
let contained_text = theme.tab_button.style_for(active, state);
|
||||
Label::new(text, contained_text.text.clone())
|
||||
.contained()
|
||||
.with_style(contained_text.container.clone())
|
||||
})
|
||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||
if !active {
|
||||
this.set_mode(mode, cx);
|
||||
}
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.into_any()
|
||||
}
|
||||
|
||||
fn render_visibility(
|
||||
channel_id: ChannelId,
|
||||
visibility: ChannelVisibility,
|
||||
theme: &theme::TabbedModal,
|
||||
cx: &mut ViewContext<ChannelModal>,
|
||||
) -> AnyElement<ChannelModal> {
|
||||
enum TogglePublic {}
|
||||
|
||||
if visibility == ChannelVisibility::Members {
|
||||
return Flex::row()
|
||||
.with_child(
|
||||
MouseEventHandler::new::<TogglePublic, _>(0, cx, move |state, _| {
|
||||
let style = theme.visibility_toggle.style_for(state);
|
||||
Label::new(format!("{}", "Public access: OFF"), style.text.clone())
|
||||
.contained()
|
||||
.with_style(style.container.clone())
|
||||
})
|
||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||
this.channel_store
|
||||
.update(cx, |channel_store, cx| {
|
||||
channel_store.set_channel_visibility(
|
||||
channel_id,
|
||||
ChannelVisibility::Public,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand),
|
||||
)
|
||||
.into_any();
|
||||
}
|
||||
|
||||
Flex::row()
|
||||
.with_child(
|
||||
MouseEventHandler::new::<TogglePublic, _>(0, cx, move |state, _| {
|
||||
let style = theme.visibility_toggle.style_for(state);
|
||||
Label::new(format!("{}", "Public access: ON"), style.text.clone())
|
||||
.contained()
|
||||
.with_style(style.container.clone())
|
||||
})
|
||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||
this.channel_store
|
||||
.update(cx, |channel_store, cx| {
|
||||
channel_store.set_channel_visibility(
|
||||
channel_id,
|
||||
ChannelVisibility::Members,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand),
|
||||
)
|
||||
.with_spacing(14.0)
|
||||
.with_child(
|
||||
MouseEventHandler::new::<TogglePublic, _>(1, cx, move |state, _| {
|
||||
let style = theme.channel_link.style_for(state);
|
||||
Label::new(format!("{}", "copy link"), style.text.clone())
|
||||
.contained()
|
||||
.with_style(style.container.clone())
|
||||
})
|
||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||
if let Some(channel) =
|
||||
this.channel_store.read(cx).channel_for_id(channel_id)
|
||||
{
|
||||
let item = ClipboardItem::new(channel.link());
|
||||
cx.write_to_clipboard(item);
|
||||
}
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand),
|
||||
)
|
||||
.into_any()
|
||||
}
|
||||
|
||||
Flex::column()
|
||||
.with_child(
|
||||
Flex::column()
|
||||
.with_child(
|
||||
Label::new(format!("#{}", channel.name), theme.title.text.clone())
|
||||
.contained()
|
||||
.with_style(theme.title.container.clone()),
|
||||
)
|
||||
.with_child(render_visibility(channel.id, channel.visibility, theme, cx))
|
||||
.with_child(Flex::row().with_children([
|
||||
render_mode_button::<InviteMembers>(
|
||||
Mode::InviteMembers,
|
||||
"Invite members",
|
||||
mode,
|
||||
theme,
|
||||
cx,
|
||||
),
|
||||
render_mode_button::<ManageMembers>(
|
||||
Mode::ManageMembers,
|
||||
"Manage members",
|
||||
mode,
|
||||
theme,
|
||||
cx,
|
||||
),
|
||||
]))
|
||||
.expanded()
|
||||
.contained()
|
||||
.with_style(theme.header),
|
||||
)
|
||||
.with_child(
|
||||
ChildView::new(&self.picker, cx)
|
||||
.contained()
|
||||
.with_style(theme.body),
|
||||
)
|
||||
.constrained()
|
||||
.with_max_height(theme.max_height)
|
||||
.with_max_width(theme.max_width)
|
||||
.contained()
|
||||
.with_style(theme.modal)
|
||||
.into_any()
|
||||
}
|
||||
|
||||
fn focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||
self.has_focus = true;
|
||||
if cx.is_self_focused() {
|
||||
cx.focus(&self.picker)
|
||||
}
|
||||
}
|
||||
|
||||
fn focus_out(&mut self, _: gpui::AnyViewHandle, _: &mut ViewContext<Self>) {
|
||||
self.has_focus = false;
|
||||
impl FocusableView for ChannelModal {
|
||||
fn focus_handle(&self, cx: &AppContext) -> gpui::FocusHandle {
|
||||
self.picker.focus_handle(cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl Modal for ChannelModal {
|
||||
fn has_focus(&self) -> bool {
|
||||
self.has_focus
|
||||
impl Render for ChannelModal {
|
||||
type Element = Div;
|
||||
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||
v_stack().min_w_96().child(self.picker.clone())
|
||||
// let theme = &theme::current(cx).collab_panel.tabbed_modal;
|
||||
|
||||
// let mode = self.picker.read(cx).delegate().mode;
|
||||
// let Some(channel) = self.channel_store.read(cx).channel_for_id(self.channel_id) else {
|
||||
// return Empty::new().into_any();
|
||||
// };
|
||||
|
||||
// enum InviteMembers {}
|
||||
// enum ManageMembers {}
|
||||
|
||||
// fn render_mode_button<T: 'static>(
|
||||
// mode: Mode,
|
||||
// text: &'static str,
|
||||
// current_mode: Mode,
|
||||
// theme: &theme::TabbedModal,
|
||||
// cx: &mut ViewContext<ChannelModal>,
|
||||
// ) -> AnyElement<ChannelModal> {
|
||||
// let active = mode == current_mode;
|
||||
// MouseEventHandler::new::<T, _>(0, cx, move |state, _| {
|
||||
// let contained_text = theme.tab_button.style_for(active, state);
|
||||
// Label::new(text, contained_text.text.clone())
|
||||
// .contained()
|
||||
// .with_style(contained_text.container.clone())
|
||||
// })
|
||||
// .on_click(MouseButton::Left, move |_, this, cx| {
|
||||
// if !active {
|
||||
// this.set_mode(mode, cx);
|
||||
// }
|
||||
// })
|
||||
// .with_cursor_style(CursorStyle::PointingHand)
|
||||
// .into_any()
|
||||
// }
|
||||
|
||||
// fn render_visibility(
|
||||
// channel_id: ChannelId,
|
||||
// visibility: ChannelVisibility,
|
||||
// theme: &theme::TabbedModal,
|
||||
// cx: &mut ViewContext<ChannelModal>,
|
||||
// ) -> AnyElement<ChannelModal> {
|
||||
// enum TogglePublic {}
|
||||
|
||||
// if visibility == ChannelVisibility::Members {
|
||||
// return Flex::row()
|
||||
// .with_child(
|
||||
// MouseEventHandler::new::<TogglePublic, _>(0, cx, move |state, _| {
|
||||
// let style = theme.visibility_toggle.style_for(state);
|
||||
// Label::new(format!("{}", "Public access: OFF"), style.text.clone())
|
||||
// .contained()
|
||||
// .with_style(style.container.clone())
|
||||
// })
|
||||
// .on_click(MouseButton::Left, move |_, this, cx| {
|
||||
// this.channel_store
|
||||
// .update(cx, |channel_store, cx| {
|
||||
// channel_store.set_channel_visibility(
|
||||
// channel_id,
|
||||
// ChannelVisibility::Public,
|
||||
// cx,
|
||||
// )
|
||||
// })
|
||||
// .detach_and_log_err(cx);
|
||||
// })
|
||||
// .with_cursor_style(CursorStyle::PointingHand),
|
||||
// )
|
||||
// .into_any();
|
||||
// }
|
||||
|
||||
// Flex::row()
|
||||
// .with_child(
|
||||
// MouseEventHandler::new::<TogglePublic, _>(0, cx, move |state, _| {
|
||||
// let style = theme.visibility_toggle.style_for(state);
|
||||
// Label::new(format!("{}", "Public access: ON"), style.text.clone())
|
||||
// .contained()
|
||||
// .with_style(style.container.clone())
|
||||
// })
|
||||
// .on_click(MouseButton::Left, move |_, this, cx| {
|
||||
// this.channel_store
|
||||
// .update(cx, |channel_store, cx| {
|
||||
// channel_store.set_channel_visibility(
|
||||
// channel_id,
|
||||
// ChannelVisibility::Members,
|
||||
// cx,
|
||||
// )
|
||||
// })
|
||||
// .detach_and_log_err(cx);
|
||||
// })
|
||||
// .with_cursor_style(CursorStyle::PointingHand),
|
||||
// )
|
||||
// .with_spacing(14.0)
|
||||
// .with_child(
|
||||
// MouseEventHandler::new::<TogglePublic, _>(1, cx, move |state, _| {
|
||||
// let style = theme.channel_link.style_for(state);
|
||||
// Label::new(format!("{}", "copy link"), style.text.clone())
|
||||
// .contained()
|
||||
// .with_style(style.container.clone())
|
||||
// })
|
||||
// .on_click(MouseButton::Left, move |_, this, cx| {
|
||||
// if let Some(channel) =
|
||||
// this.channel_store.read(cx).channel_for_id(channel_id)
|
||||
// {
|
||||
// let item = ClipboardItem::new(channel.link());
|
||||
// cx.write_to_clipboard(item);
|
||||
// }
|
||||
// })
|
||||
// .with_cursor_style(CursorStyle::PointingHand),
|
||||
// )
|
||||
// .into_any()
|
||||
// }
|
||||
|
||||
// Flex::column()
|
||||
// .with_child(
|
||||
// Flex::column()
|
||||
// .with_child(
|
||||
// Label::new(format!("#{}", channel.name), theme.title.text.clone())
|
||||
// .contained()
|
||||
// .with_style(theme.title.container.clone()),
|
||||
// )
|
||||
// .with_child(render_visibility(channel.id, channel.visibility, theme, cx))
|
||||
// .with_child(Flex::row().with_children([
|
||||
// render_mode_button::<InviteMembers>(
|
||||
// Mode::InviteMembers,
|
||||
// "Invite members",
|
||||
// mode,
|
||||
// theme,
|
||||
// cx,
|
||||
// ),
|
||||
// render_mode_button::<ManageMembers>(
|
||||
// Mode::ManageMembers,
|
||||
// "Manage members",
|
||||
// mode,
|
||||
// theme,
|
||||
// cx,
|
||||
// ),
|
||||
// ]))
|
||||
// .expanded()
|
||||
// .contained()
|
||||
// .with_style(theme.header),
|
||||
// )
|
||||
// .with_child(
|
||||
// ChildView::new(&self.picker, cx)
|
||||
// .contained()
|
||||
// .with_style(theme.body),
|
||||
// )
|
||||
// .constrained()
|
||||
// .with_max_height(theme.max_height)
|
||||
// .with_max_width(theme.max_width)
|
||||
// .contained()
|
||||
// .with_style(theme.modal)
|
||||
// .into_any()
|
||||
}
|
||||
|
||||
fn dismiss_on_event(event: &Self::Event) -> bool {
|
||||
match event {
|
||||
PickerEvent::Dismiss => true,
|
||||
}
|
||||
}
|
||||
// fn focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||
// self.has_focus = true;
|
||||
// if cx.is_self_focused() {
|
||||
// cx.focus(&self.picker)
|
||||
// }
|
||||
// }
|
||||
|
||||
// fn focus_out(&mut self, _: gpui::AnyViewHandle, _: &mut ViewContext<Self>) {
|
||||
// self.has_focus = false;
|
||||
// }
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
|
@ -337,19 +321,22 @@ pub enum Mode {
|
|||
}
|
||||
|
||||
pub struct ChannelModalDelegate {
|
||||
channel_modal: WeakView<ChannelModal>,
|
||||
matching_users: Vec<Arc<User>>,
|
||||
matching_member_indices: Vec<usize>,
|
||||
user_store: ModelHandle<UserStore>,
|
||||
channel_store: ModelHandle<ChannelStore>,
|
||||
user_store: Model<UserStore>,
|
||||
channel_store: Model<ChannelStore>,
|
||||
channel_id: ChannelId,
|
||||
selected_index: usize,
|
||||
mode: Mode,
|
||||
match_candidates: Vec<StringMatchCandidate>,
|
||||
members: Vec<ChannelMembership>,
|
||||
context_menu: ViewHandle<ContextMenu>,
|
||||
// context_menu: ViewHandle<ContextMenu>,
|
||||
}
|
||||
|
||||
impl PickerDelegate for ChannelModalDelegate {
|
||||
type ListItem = Div;
|
||||
|
||||
fn placeholder_text(&self) -> Arc<str> {
|
||||
"Search collaborator by username...".into()
|
||||
}
|
||||
|
@ -382,19 +369,19 @@ impl PickerDelegate for ChannelModalDelegate {
|
|||
}
|
||||
}));
|
||||
|
||||
let matches = cx.background().block(match_strings(
|
||||
let matches = cx.background_executor().block(match_strings(
|
||||
&self.match_candidates,
|
||||
&query,
|
||||
true,
|
||||
usize::MAX,
|
||||
&Default::default(),
|
||||
cx.background().clone(),
|
||||
cx.background_executor().clone(),
|
||||
));
|
||||
|
||||
cx.spawn(|picker, mut cx| async move {
|
||||
picker
|
||||
.update(&mut cx, |picker, cx| {
|
||||
let delegate = picker.delegate_mut();
|
||||
let delegate = &mut picker.delegate;
|
||||
delegate.matching_member_indices.clear();
|
||||
delegate
|
||||
.matching_member_indices
|
||||
|
@ -412,8 +399,7 @@ impl PickerDelegate for ChannelModalDelegate {
|
|||
async {
|
||||
let users = search_users.await?;
|
||||
picker.update(&mut cx, |picker, cx| {
|
||||
let delegate = picker.delegate_mut();
|
||||
delegate.matching_users = users;
|
||||
picker.delegate.matching_users = users;
|
||||
cx.notify();
|
||||
})?;
|
||||
anyhow::Ok(())
|
||||
|
@ -445,138 +431,142 @@ impl PickerDelegate for ChannelModalDelegate {
|
|||
}
|
||||
|
||||
fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
|
||||
cx.emit(PickerEvent::Dismiss);
|
||||
self.channel_modal
|
||||
.update(cx, |_, cx| {
|
||||
cx.emit(DismissEvent);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
|
||||
fn render_match(
|
||||
&self,
|
||||
ix: usize,
|
||||
mouse_state: &mut MouseState,
|
||||
selected: bool,
|
||||
cx: &gpui::AppContext,
|
||||
) -> AnyElement<Picker<Self>> {
|
||||
let full_theme = &theme::current(cx);
|
||||
let theme = &full_theme.collab_panel.channel_modal;
|
||||
let tabbed_modal = &full_theme.collab_panel.tabbed_modal;
|
||||
let (user, role) = self.user_at_index(ix).unwrap();
|
||||
let request_status = self.member_status(user.id, cx);
|
||||
cx: &mut ViewContext<Picker<Self>>,
|
||||
) -> Option<Self::ListItem> {
|
||||
None
|
||||
// let full_theme = &theme::current(cx);
|
||||
// let theme = &full_theme.collab_panel.channel_modal;
|
||||
// let tabbed_modal = &full_theme.collab_panel.tabbed_modal;
|
||||
// let (user, role) = self.user_at_index(ix).unwrap();
|
||||
// let request_status = self.member_status(user.id, cx);
|
||||
|
||||
let style = tabbed_modal
|
||||
.picker
|
||||
.item
|
||||
.in_state(selected)
|
||||
.style_for(mouse_state);
|
||||
// let style = tabbed_modal
|
||||
// .picker
|
||||
// .item
|
||||
// .in_state(selected)
|
||||
// .style_for(mouse_state);
|
||||
|
||||
let in_manage = matches!(self.mode, Mode::ManageMembers);
|
||||
// let in_manage = matches!(self.mode, Mode::ManageMembers);
|
||||
|
||||
let mut result = Flex::row()
|
||||
.with_children(user.avatar.clone().map(|avatar| {
|
||||
Image::from_data(avatar)
|
||||
.with_style(theme.contact_avatar)
|
||||
.aligned()
|
||||
.left()
|
||||
}))
|
||||
.with_child(
|
||||
Label::new(user.github_login.clone(), style.label.clone())
|
||||
.contained()
|
||||
.with_style(theme.contact_username)
|
||||
.aligned()
|
||||
.left(),
|
||||
)
|
||||
.with_children({
|
||||
(in_manage && request_status == Some(proto::channel_member::Kind::Invitee)).then(
|
||||
|| {
|
||||
Label::new("Invited", theme.member_tag.text.clone())
|
||||
.contained()
|
||||
.with_style(theme.member_tag.container)
|
||||
.aligned()
|
||||
.left()
|
||||
},
|
||||
)
|
||||
})
|
||||
.with_children(if in_manage && role == Some(ChannelRole::Admin) {
|
||||
Some(
|
||||
Label::new("Admin", theme.member_tag.text.clone())
|
||||
.contained()
|
||||
.with_style(theme.member_tag.container)
|
||||
.aligned()
|
||||
.left(),
|
||||
)
|
||||
} else if in_manage && role == Some(ChannelRole::Guest) {
|
||||
Some(
|
||||
Label::new("Guest", theme.member_tag.text.clone())
|
||||
.contained()
|
||||
.with_style(theme.member_tag.container)
|
||||
.aligned()
|
||||
.left(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.with_children({
|
||||
let svg = match self.mode {
|
||||
Mode::ManageMembers => Some(
|
||||
Svg::new("icons/ellipsis.svg")
|
||||
.with_color(theme.member_icon.color)
|
||||
.constrained()
|
||||
.with_width(theme.member_icon.icon_width)
|
||||
.aligned()
|
||||
.constrained()
|
||||
.with_width(theme.member_icon.button_width)
|
||||
.with_height(theme.member_icon.button_width)
|
||||
.contained()
|
||||
.with_style(theme.member_icon.container),
|
||||
),
|
||||
Mode::InviteMembers => match request_status {
|
||||
Some(proto::channel_member::Kind::Member) => Some(
|
||||
Svg::new("icons/check.svg")
|
||||
.with_color(theme.member_icon.color)
|
||||
.constrained()
|
||||
.with_width(theme.member_icon.icon_width)
|
||||
.aligned()
|
||||
.constrained()
|
||||
.with_width(theme.member_icon.button_width)
|
||||
.with_height(theme.member_icon.button_width)
|
||||
.contained()
|
||||
.with_style(theme.member_icon.container),
|
||||
),
|
||||
Some(proto::channel_member::Kind::Invitee) => Some(
|
||||
Svg::new("icons/check.svg")
|
||||
.with_color(theme.invitee_icon.color)
|
||||
.constrained()
|
||||
.with_width(theme.invitee_icon.icon_width)
|
||||
.aligned()
|
||||
.constrained()
|
||||
.with_width(theme.invitee_icon.button_width)
|
||||
.with_height(theme.invitee_icon.button_width)
|
||||
.contained()
|
||||
.with_style(theme.invitee_icon.container),
|
||||
),
|
||||
Some(proto::channel_member::Kind::AncestorMember) | None => None,
|
||||
},
|
||||
};
|
||||
// let mut result = Flex::row()
|
||||
// .with_children(user.avatar.clone().map(|avatar| {
|
||||
// Image::from_data(avatar)
|
||||
// .with_style(theme.contact_avatar)
|
||||
// .aligned()
|
||||
// .left()
|
||||
// }))
|
||||
// .with_child(
|
||||
// Label::new(user.github_login.clone(), style.label.clone())
|
||||
// .contained()
|
||||
// .with_style(theme.contact_username)
|
||||
// .aligned()
|
||||
// .left(),
|
||||
// )
|
||||
// .with_children({
|
||||
// (in_manage && request_status == Some(proto::channel_member::Kind::Invitee)).then(
|
||||
// || {
|
||||
// Label::new("Invited", theme.member_tag.text.clone())
|
||||
// .contained()
|
||||
// .with_style(theme.member_tag.container)
|
||||
// .aligned()
|
||||
// .left()
|
||||
// },
|
||||
// )
|
||||
// })
|
||||
// .with_children(if in_manage && role == Some(ChannelRole::Admin) {
|
||||
// Some(
|
||||
// Label::new("Admin", theme.member_tag.text.clone())
|
||||
// .contained()
|
||||
// .with_style(theme.member_tag.container)
|
||||
// .aligned()
|
||||
// .left(),
|
||||
// )
|
||||
// } else if in_manage && role == Some(ChannelRole::Guest) {
|
||||
// Some(
|
||||
// Label::new("Guest", theme.member_tag.text.clone())
|
||||
// .contained()
|
||||
// .with_style(theme.member_tag.container)
|
||||
// .aligned()
|
||||
// .left(),
|
||||
// )
|
||||
// } else {
|
||||
// None
|
||||
// })
|
||||
// .with_children({
|
||||
// let svg = match self.mode {
|
||||
// Mode::ManageMembers => Some(
|
||||
// Svg::new("icons/ellipsis.svg")
|
||||
// .with_color(theme.member_icon.color)
|
||||
// .constrained()
|
||||
// .with_width(theme.member_icon.icon_width)
|
||||
// .aligned()
|
||||
// .constrained()
|
||||
// .with_width(theme.member_icon.button_width)
|
||||
// .with_height(theme.member_icon.button_width)
|
||||
// .contained()
|
||||
// .with_style(theme.member_icon.container),
|
||||
// ),
|
||||
// Mode::InviteMembers => match request_status {
|
||||
// Some(proto::channel_member::Kind::Member) => Some(
|
||||
// Svg::new("icons/check.svg")
|
||||
// .with_color(theme.member_icon.color)
|
||||
// .constrained()
|
||||
// .with_width(theme.member_icon.icon_width)
|
||||
// .aligned()
|
||||
// .constrained()
|
||||
// .with_width(theme.member_icon.button_width)
|
||||
// .with_height(theme.member_icon.button_width)
|
||||
// .contained()
|
||||
// .with_style(theme.member_icon.container),
|
||||
// ),
|
||||
// Some(proto::channel_member::Kind::Invitee) => Some(
|
||||
// Svg::new("icons/check.svg")
|
||||
// .with_color(theme.invitee_icon.color)
|
||||
// .constrained()
|
||||
// .with_width(theme.invitee_icon.icon_width)
|
||||
// .aligned()
|
||||
// .constrained()
|
||||
// .with_width(theme.invitee_icon.button_width)
|
||||
// .with_height(theme.invitee_icon.button_width)
|
||||
// .contained()
|
||||
// .with_style(theme.invitee_icon.container),
|
||||
// ),
|
||||
// Some(proto::channel_member::Kind::AncestorMember) | None => None,
|
||||
// },
|
||||
// };
|
||||
|
||||
svg.map(|svg| svg.aligned().flex_float().into_any())
|
||||
})
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
.constrained()
|
||||
.with_height(tabbed_modal.row_height)
|
||||
.into_any();
|
||||
// svg.map(|svg| svg.aligned().flex_float().into_any())
|
||||
// })
|
||||
// .contained()
|
||||
// .with_style(style.container)
|
||||
// .constrained()
|
||||
// .with_height(tabbed_modal.row_height)
|
||||
// .into_any();
|
||||
|
||||
if selected {
|
||||
result = Stack::new()
|
||||
.with_child(result)
|
||||
.with_child(
|
||||
ChildView::new(&self.context_menu, cx)
|
||||
.aligned()
|
||||
.top()
|
||||
.right(),
|
||||
)
|
||||
.into_any();
|
||||
}
|
||||
// if selected {
|
||||
// result = Stack::new()
|
||||
// .with_child(result)
|
||||
// .with_child(
|
||||
// ChildView::new(&self.context_menu, cx)
|
||||
// .aligned()
|
||||
// .top()
|
||||
// .right(),
|
||||
// )
|
||||
// .into_any();
|
||||
// }
|
||||
|
||||
result
|
||||
// result
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -623,7 +613,7 @@ impl ChannelModalDelegate {
|
|||
cx.spawn(|picker, mut cx| async move {
|
||||
update.await?;
|
||||
picker.update(&mut cx, |picker, cx| {
|
||||
let this = picker.delegate_mut();
|
||||
let this = &mut picker.delegate;
|
||||
if let Some(member) = this.members.iter_mut().find(|m| m.user.id == user.id) {
|
||||
member.role = new_role;
|
||||
}
|
||||
|
@ -644,7 +634,7 @@ impl ChannelModalDelegate {
|
|||
cx.spawn(|picker, mut cx| async move {
|
||||
update.await?;
|
||||
picker.update(&mut cx, |picker, cx| {
|
||||
let this = picker.delegate_mut();
|
||||
let this = &mut picker.delegate;
|
||||
if let Some(ix) = this.members.iter_mut().position(|m| m.user.id == user_id) {
|
||||
this.members.remove(ix);
|
||||
this.matching_member_indices.retain_mut(|member_ix| {
|
||||
|
@ -683,7 +673,7 @@ impl ChannelModalDelegate {
|
|||
kind: proto::channel_member::Kind::Invitee,
|
||||
role: ChannelRole::Member,
|
||||
};
|
||||
let members = &mut this.delegate_mut().members;
|
||||
let members = &mut this.delegate.members;
|
||||
match members.binary_search_by_key(&new_member.sort_key(), |k| k.sort_key()) {
|
||||
Ok(ix) | Err(ix) => members.insert(ix, new_member),
|
||||
}
|
||||
|
@ -695,23 +685,23 @@ impl ChannelModalDelegate {
|
|||
}
|
||||
|
||||
fn show_context_menu(&mut self, role: ChannelRole, cx: &mut ViewContext<Picker<Self>>) {
|
||||
self.context_menu.update(cx, |context_menu, cx| {
|
||||
context_menu.show(
|
||||
Default::default(),
|
||||
AnchorCorner::TopRight,
|
||||
vec![
|
||||
ContextMenuItem::action("Remove", RemoveMember),
|
||||
ContextMenuItem::action(
|
||||
if role == ChannelRole::Admin {
|
||||
"Make non-admin"
|
||||
} else {
|
||||
"Make admin"
|
||||
},
|
||||
ToggleMemberAdmin,
|
||||
),
|
||||
],
|
||||
cx,
|
||||
)
|
||||
})
|
||||
// self.context_menu.update(cx, |context_menu, cx| {
|
||||
// context_menu.show(
|
||||
// Default::default(),
|
||||
// AnchorCorner::TopRight,
|
||||
// vec![
|
||||
// ContextMenuItem::action("Remove", RemoveMember),
|
||||
// ContextMenuItem::action(
|
||||
// if role == ChannelRole::Admin {
|
||||
// "Make non-admin"
|
||||
// } else {
|
||||
// "Make admin"
|
||||
// },
|
||||
// ToggleMemberAdmin,
|
||||
// ),
|
||||
// ],
|
||||
// cx,
|
||||
// )
|
||||
// })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ impl Render for CopilotButton {
|
|||
|
||||
if let Status::Error(e) = status {
|
||||
return div().child(
|
||||
IconButton::new("github-copilot", icon)
|
||||
IconButton::new("copilot-error", icon)
|
||||
.on_click(cx.listener(move |this, _, cx| {
|
||||
if let Some(workspace) = cx.window_handle().downcast::<Workspace>() {
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
|
@ -98,7 +98,7 @@ impl Render for CopilotButton {
|
|||
let this = cx.view().clone();
|
||||
|
||||
div().child(
|
||||
popover_menu("github-copilot")
|
||||
popover_menu("copilot")
|
||||
.menu(move |cx| match status {
|
||||
Status::Authorized => this.update(cx, |this, cx| this.build_copilot_menu(cx)),
|
||||
_ => this.update(cx, |this, cx| this.build_copilot_start_menu(cx)),
|
||||
|
|
|
@ -178,6 +178,15 @@ impl<D: PickerDelegate> Picker<D> {
|
|||
}
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
pub fn query(&self, cx: &AppContext) -> String {
|
||||
self.editor.read(cx).text(cx)
|
||||
}
|
||||
|
||||
pub fn set_query(&self, query: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
|
||||
self.editor
|
||||
.update(cx, |editor, cx| editor.set_text(query, cx));
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: PickerDelegate> Render for Picker<D> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue