Structure the contact finder more similarly to the channel modal
Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
parent
b6f3dd51a0
commit
2bb9f7929d
10 changed files with 351 additions and 232 deletions
|
@ -7,7 +7,7 @@ use call::ActiveCall;
|
|||
use client::{
|
||||
proto::PeerId, Channel, ChannelEvent, ChannelId, ChannelStore, Client, Contact, User, UserStore,
|
||||
};
|
||||
use contact_finder::build_contact_finder;
|
||||
|
||||
use context_menu::{ContextMenu, ContextMenuItem};
|
||||
use db::kvp::KEY_VALUE_STORE;
|
||||
use editor::{Cancel, Editor};
|
||||
|
@ -46,6 +46,8 @@ use workspace::{
|
|||
use crate::face_pile::FacePile;
|
||||
use channel_modal::ChannelModal;
|
||||
|
||||
use self::contact_finder::ContactFinder;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
struct RemoveChannel {
|
||||
channel_id: u64,
|
||||
|
@ -1945,7 +1947,7 @@ impl CollabPanel {
|
|||
workspace.update(cx, |workspace, cx| {
|
||||
workspace.toggle_modal(cx, |_, cx| {
|
||||
cx.add_view(|cx| {
|
||||
let finder = build_contact_finder(self.user_store.clone(), cx);
|
||||
let mut finder = ContactFinder::new(self.user_store.clone(), cx);
|
||||
finder.set_query(self.filter_editor.read(cx).text(cx), cx);
|
||||
finder
|
||||
})
|
||||
|
|
|
@ -66,7 +66,7 @@ impl ChannelModal {
|
|||
},
|
||||
cx,
|
||||
)
|
||||
.with_theme(|theme| theme.collab_panel.channel_modal.picker.clone())
|
||||
.with_theme(|theme| theme.collab_panel.tabbed_modal.picker.clone())
|
||||
});
|
||||
|
||||
cx.subscribe(&picker, |_, _, e, cx| cx.emit(*e)).detach();
|
||||
|
@ -143,7 +143,7 @@ impl View for ChannelModal {
|
|||
}
|
||||
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
||||
let theme = &theme::current(cx).collab_panel.channel_modal;
|
||||
let theme = &theme::current(cx).collab_panel.tabbed_modal;
|
||||
|
||||
let mode = self.picker.read(cx).delegate().mode;
|
||||
let Some(channel) = self
|
||||
|
@ -160,12 +160,12 @@ impl View for ChannelModal {
|
|||
mode: Mode,
|
||||
text: &'static str,
|
||||
current_mode: Mode,
|
||||
theme: &theme::ChannelModal,
|
||||
theme: &theme::TabbedModal,
|
||||
cx: &mut ViewContext<ChannelModal>,
|
||||
) -> AnyElement<ChannelModal> {
|
||||
let active = mode == current_mode;
|
||||
MouseEventHandler::<T, _>::new(0, cx, move |state, _| {
|
||||
let contained_text = theme.mode_button.style_for(active, 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())
|
||||
|
@ -367,11 +367,17 @@ impl PickerDelegate for ChannelModalDelegate {
|
|||
selected: bool,
|
||||
cx: &gpui::AppContext,
|
||||
) -> AnyElement<Picker<Self>> {
|
||||
let theme = &theme::current(cx).collab_panel.channel_modal;
|
||||
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, admin) = self.user_at_index(ix).unwrap();
|
||||
let request_status = self.member_status(user.id, cx);
|
||||
|
||||
let style = theme.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);
|
||||
|
||||
|
@ -448,7 +454,7 @@ impl PickerDelegate for ChannelModalDelegate {
|
|||
.contained()
|
||||
.with_style(style.container)
|
||||
.constrained()
|
||||
.with_height(theme.row_height)
|
||||
.with_height(tabbed_modal.row_height)
|
||||
.into_any();
|
||||
|
||||
if selected {
|
||||
|
|
|
@ -1,28 +1,127 @@
|
|||
use client::{ContactRequestStatus, User, UserStore};
|
||||
use gpui::{elements::*, AppContext, ModelHandle, MouseState, Task, ViewContext};
|
||||
use gpui::{
|
||||
elements::*, AppContext, Entity, ModelHandle, MouseState, Task, View, ViewContext, ViewHandle,
|
||||
};
|
||||
use picker::{Picker, PickerDelegate, PickerEvent};
|
||||
use std::sync::Arc;
|
||||
use util::TryFutureExt;
|
||||
use workspace::Modal;
|
||||
|
||||
pub fn init(cx: &mut AppContext) {
|
||||
Picker::<ContactFinderDelegate>::init(cx);
|
||||
}
|
||||
|
||||
pub type ContactFinder = Picker<ContactFinderDelegate>;
|
||||
pub struct ContactFinder {
|
||||
picker: ViewHandle<Picker<ContactFinderDelegate>>,
|
||||
has_focus: bool,
|
||||
}
|
||||
|
||||
pub fn build_contact_finder(
|
||||
user_store: ModelHandle<UserStore>,
|
||||
cx: &mut ViewContext<ContactFinder>,
|
||||
) -> ContactFinder {
|
||||
Picker::new(
|
||||
ContactFinderDelegate {
|
||||
user_store,
|
||||
potential_contacts: Arc::from([]),
|
||||
selected_index: 0,
|
||||
},
|
||||
cx,
|
||||
)
|
||||
.with_theme(|theme| theme.picker.clone())
|
||||
impl ContactFinder {
|
||||
pub fn new(user_store: ModelHandle<UserStore>, cx: &mut ViewContext<Self>) -> Self {
|
||||
let picker = cx.add_view(|cx| {
|
||||
Picker::new(
|
||||
ContactFinderDelegate {
|
||||
user_store,
|
||||
potential_contacts: Arc::from([]),
|
||||
selected_index: 0,
|
||||
},
|
||||
cx,
|
||||
)
|
||||
.with_theme(|theme| theme.collab_panel.tabbed_modal.picker.clone())
|
||||
});
|
||||
|
||||
cx.subscribe(&picker, |_, _, e, cx| cx.emit(*e)).detach();
|
||||
|
||||
Self {
|
||||
picker,
|
||||
has_focus: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_query(&mut self, query: String, cx: &mut ViewContext<Self>) {
|
||||
self.picker.update(cx, |picker, cx| {
|
||||
picker.set_query(query, cx);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl Entity for ContactFinder {
|
||||
type Event = PickerEvent;
|
||||
}
|
||||
|
||||
impl View for ContactFinder {
|
||||
fn ui_name() -> &'static str {
|
||||
"ContactFinder"
|
||||
}
|
||||
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
||||
let full_theme = &theme::current(cx);
|
||||
let theme = &full_theme.collab_panel.tabbed_modal;
|
||||
|
||||
fn render_mode_button(
|
||||
text: &'static str,
|
||||
theme: &theme::TabbedModal,
|
||||
_cx: &mut ViewContext<ContactFinder>,
|
||||
) -> AnyElement<ContactFinder> {
|
||||
let contained_text = &theme.tab_button.active_state().default;
|
||||
Label::new(text, contained_text.text.clone())
|
||||
.contained()
|
||||
.with_style(contained_text.container.clone())
|
||||
.into_any()
|
||||
}
|
||||
|
||||
Flex::column()
|
||||
.with_child(
|
||||
Flex::column()
|
||||
.with_child(
|
||||
Label::new("Contacts", theme.title.text.clone())
|
||||
.contained()
|
||||
.with_style(theme.title.container.clone()),
|
||||
)
|
||||
.with_child(Flex::row().with_children([render_mode_button(
|
||||
"Invite new contacts",
|
||||
&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 Modal for ContactFinder {
|
||||
fn has_focus(&self) -> bool {
|
||||
self.has_focus
|
||||
}
|
||||
|
||||
fn dismiss_on_event(event: &Self::Event) -> bool {
|
||||
match event {
|
||||
PickerEvent::Dismiss => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ContactFinderDelegate {
|
||||
|
@ -97,7 +196,9 @@ impl PickerDelegate for ContactFinderDelegate {
|
|||
selected: bool,
|
||||
cx: &gpui::AppContext,
|
||||
) -> AnyElement<Picker<Self>> {
|
||||
let theme = &theme::current(cx).contact_finder;
|
||||
let full_theme = &theme::current(cx);
|
||||
let theme = &full_theme.collab_panel.contact_finder;
|
||||
let tabbed_modal = &full_theme.collab_panel.tabbed_modal;
|
||||
let user = &self.potential_contacts[ix];
|
||||
let request_status = self.user_store.read(cx).contact_request_status(user);
|
||||
|
||||
|
@ -113,7 +214,11 @@ impl PickerDelegate for ContactFinderDelegate {
|
|||
} else {
|
||||
&theme.contact_button
|
||||
};
|
||||
let style = theme.picker.item.in_state(selected).style_for(mouse_state);
|
||||
let style = tabbed_modal
|
||||
.picker
|
||||
.item
|
||||
.in_state(selected)
|
||||
.style_for(mouse_state);
|
||||
Flex::row()
|
||||
.with_children(user.avatar.clone().map(|avatar| {
|
||||
Image::from_data(avatar)
|
||||
|
@ -145,7 +250,7 @@ impl PickerDelegate for ContactFinderDelegate {
|
|||
.contained()
|
||||
.with_style(style.container)
|
||||
.constrained()
|
||||
.with_height(theme.row_height)
|
||||
.with_height(tabbed_modal.row_height)
|
||||
.into_any()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue