Add filtering support

This commit is contained in:
Conrad Irwin 2023-11-29 20:57:45 -07:00
parent 4c27f4453c
commit 012543052b

View file

@ -17,7 +17,7 @@ mod contact_finder;
// Client, Contact, User, UserStore, // Client, Contact, User, UserStore,
// }; // };
use contact_finder::ContactFinder; use contact_finder::ContactFinder;
use menu::Confirm; use menu::{Cancel, Confirm, SelectNext, SelectPrev};
use rpc::proto; use rpc::proto;
use theme::{ActiveTheme, ThemeSettings}; use theme::{ActiveTheme, ThemeSettings};
// use context_menu::{ContextMenu, ContextMenuItem}; // use context_menu::{ContextMenu, ContextMenuItem};
@ -170,10 +170,10 @@ use feature_flags::{ChannelsAlpha, FeatureFlagAppExt, FeatureFlagViewExt};
use fuzzy::{match_strings, StringMatchCandidate}; use fuzzy::{match_strings, StringMatchCandidate};
use gpui::{ use gpui::{
actions, div, img, overlay, prelude::*, px, rems, serde_json, Action, AppContext, actions, div, img, overlay, prelude::*, px, rems, serde_json, Action, AppContext,
AsyncWindowContext, ClipboardItem, DismissEvent, Div, EventEmitter, FocusHandle, Focusable, AsyncWindowContext, Bounds, ClipboardItem, DismissEvent, Div, EventEmitter, FocusHandle,
FocusableView, InteractiveElement, IntoElement, Model, MouseDownEvent, ParentElement, Pixels, Focusable, FocusableView, InteractiveElement, IntoElement, Model, MouseDownEvent,
Point, PromptLevel, Render, RenderOnce, SharedString, Stateful, Styled, Subscription, Task, ParentElement, Pixels, Point, PromptLevel, Render, RenderOnce, SharedString, Stateful, Styled,
View, ViewContext, VisualContext, WeakView, Subscription, Task, View, ViewContext, VisualContext, WeakView,
}; };
use project::{Fs, Project}; use project::{Fs, Project};
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
@ -399,28 +399,28 @@ impl CollabPanel {
editor editor
}); });
// cx.subscribe(&filter_editor, |this, _, event, cx| { cx.subscribe(&filter_editor, |this: &mut Self, _, event, cx| {
// if let editor::Event::BufferEdited = event { if let editor::EditorEvent::BufferEdited = event {
// let query = this.filter_editor.read(cx).text(cx); let query = this.filter_editor.read(cx).text(cx);
// if !query.is_empty() { if !query.is_empty() {
// this.selection.take(); this.selection.take();
// } }
// this.update_entries(true, cx); this.update_entries(true, cx);
// if !query.is_empty() { if !query.is_empty() {
// this.selection = this this.selection = this
// .entries .entries
// .iter() .iter()
// .position(|entry| !matches!(entry, ListEntry::Header(_))); .position(|entry| !matches!(entry, ListEntry::Header(_)));
// } }
// } else if let editor::Event::Blurred = event { } else if let editor::EditorEvent::Blurred = event {
// let query = this.filter_editor.read(cx).text(cx); let query = this.filter_editor.read(cx).text(cx);
// if query.is_empty() { if query.is_empty() {
// this.selection.take(); this.selection.take();
// this.update_entries(true, cx); this.update_entries(true, cx);
// } }
// } }
// }) })
// .detach(); .detach();
let channel_name_editor = cx.build_view(|cx| Editor::single_line(cx)); let channel_name_editor = cx.build_view(|cx| Editor::single_line(cx));
@ -1786,26 +1786,27 @@ impl CollabPanel {
cx.notify(); cx.notify();
} }
// fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) { fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
// if self.take_editing_state(cx) { if self.take_editing_state(cx) {
// cx.focus(&self.filter_editor); cx.focus_view(&self.filter_editor);
// } else { } else {
// self.filter_editor.update(cx, |editor, cx| { self.filter_editor.update(cx, |editor, cx| {
// if editor.buffer().read(cx).len(cx) > 0 { if editor.buffer().read(cx).len(cx) > 0 {
// editor.set_text("", cx); editor.set_text("", cx);
// } }
// }); });
// } }
// self.update_entries(false, cx); self.update_entries(false, cx);
// } }
// fn select_next(&mut self, _: &SelectNext, cx: &mut ViewContext<Self>) { fn select_next(&mut self, _: &SelectNext, cx: &mut ViewContext<Self>) {
// let ix = self.selection.map_or(0, |ix| ix + 1); let ix = self.selection.map_or(0, |ix| ix + 1);
// if ix < self.entries.len() { if ix < self.entries.len() {
// self.selection = Some(ix); self.selection = Some(ix);
// } }
// todo!()
// self.list_state.reset(self.entries.len()); // self.list_state.reset(self.entries.len());
// if let Some(ix) = self.selection { // if let Some(ix) = self.selection {
// self.list_state.scroll_to(ListOffset { // self.list_state.scroll_to(ListOffset {
@ -1813,15 +1814,16 @@ impl CollabPanel {
// offset_in_item: 0., // offset_in_item: 0.,
// }); // });
// } // }
// cx.notify(); cx.notify();
// } }
// fn select_prev(&mut self, _: &SelectPrev, cx: &mut ViewContext<Self>) { fn select_prev(&mut self, _: &SelectPrev, cx: &mut ViewContext<Self>) {
// let ix = self.selection.take().unwrap_or(0); let ix = self.selection.take().unwrap_or(0);
// if ix > 0 { if ix > 0 {
// self.selection = Some(ix - 1); self.selection = Some(ix - 1);
// } }
// todo!()
// self.list_state.reset(self.entries.len()); // self.list_state.reset(self.entries.len());
// if let Some(ix) = self.selection { // if let Some(ix) = self.selection {
// self.list_state.scroll_to(ListOffset { // self.list_state.scroll_to(ListOffset {
@ -1829,33 +1831,33 @@ impl CollabPanel {
// offset_in_item: 0., // offset_in_item: 0.,
// }); // });
// } // }
// cx.notify(); cx.notify();
// } }
fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) { fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) {
if self.confirm_channel_edit(cx) { if self.confirm_channel_edit(cx) {
return; return;
} }
// if let Some(selection) = self.selection { if let Some(selection) = self.selection {
// if let Some(entry) = self.entries.get(selection) { if let Some(entry) = self.entries.get(selection) {
// match entry { match entry {
// ListEntry::Header(section) => match section { ListEntry::Header(section) => match section {
// Section::ActiveCall => Self::leave_call(cx), Section::ActiveCall => Self::leave_call(cx),
// Section::Channels => self.new_root_channel(cx), Section::Channels => self.new_root_channel(cx),
// Section::Contacts => self.toggle_contact_finder(cx), Section::Contacts => self.toggle_contact_finder(cx),
// Section::ContactRequests Section::ContactRequests
// | Section::Online | Section::Online
// | Section::Offline | Section::Offline
// | Section::ChannelInvites => { | Section::ChannelInvites => {
// self.toggle_section_expanded(*section, cx); self.toggle_section_expanded(*section, cx);
// } }
// }, },
// ListEntry::Contact { contact, calling } => { ListEntry::Contact { contact, calling } => {
// if contact.online && !contact.busy && !calling { if contact.online && !contact.busy && !calling {
// self.call(contact.user.id, Some(self.project.clone()), cx); self.call(contact.user.id, cx);
// } }
// } }
// ListEntry::ParticipantProject { // ListEntry::ParticipantProject {
// project_id, // project_id,
// host_user_id, // host_user_id,
@ -1882,33 +1884,28 @@ impl CollabPanel {
// }); // });
// } // }
// } // }
// ListEntry::Channel { channel, .. } => { ListEntry::Channel { channel, .. } => {
// let is_active = maybe!({ let is_active = maybe!({
// let call_channel = ActiveCall::global(cx) let call_channel = ActiveCall::global(cx)
// .read(cx) .read(cx)
// .room()? .room()?
// .read(cx) .read(cx)
// .channel_id()?; .channel_id()?;
// Some(call_channel == channel.id) Some(call_channel == channel.id)
// }) })
// .unwrap_or(false); .unwrap_or(false);
// if is_active { if is_active {
// self.open_channel_notes( self.open_channel_notes(channel.id, cx)
// &OpenChannelNotes { } else {
// channel_id: channel.id, self.join_channel(channel.id, cx)
// }, }
// cx, }
// ) ListEntry::ContactPlaceholder => self.toggle_contact_finder(cx),
// } else { _ => {}
// self.join_channel(channel.id, cx) }
// } }
// } }
// ListEntry::ContactPlaceholder => self.toggle_contact_finder(cx),
// _ => {}
// }
// }
// }
} }
fn insert_space(&mut self, _: &InsertSpace, cx: &mut ViewContext<Self>) { fn insert_space(&mut self, _: &InsertSpace, cx: &mut ViewContext<Self>) {
@ -1975,33 +1972,33 @@ impl CollabPanel {
self.update_entries(false, cx); self.update_entries(false, cx);
} }
// fn collapse_selected_channel( fn collapse_selected_channel(
// &mut self, &mut self,
// _: &CollapseSelectedChannel, _: &CollapseSelectedChannel,
// cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
// ) { ) {
// let Some(channel_id) = self.selected_channel().map(|channel| channel.id) else { let Some(channel_id) = self.selected_channel().map(|channel| channel.id) else {
// return; return;
// }; };
// if self.is_channel_collapsed(channel_id) { if self.is_channel_collapsed(channel_id) {
// return; return;
// } }
// self.toggle_channel_collapsed(channel_id, cx); self.toggle_channel_collapsed(channel_id, cx);
// } }
// fn expand_selected_channel(&mut self, _: &ExpandSelectedChannel, cx: &mut ViewContext<Self>) { fn expand_selected_channel(&mut self, _: &ExpandSelectedChannel, cx: &mut ViewContext<Self>) {
// let Some(id) = self.selected_channel().map(|channel| channel.id) else { let Some(id) = self.selected_channel().map(|channel| channel.id) else {
// return; return;
// }; };
// if !self.is_channel_collapsed(id) { if !self.is_channel_collapsed(id) {
// return; return;
// } }
// self.toggle_channel_collapsed(id, cx) self.toggle_channel_collapsed(id, cx)
// } }
// fn toggle_channel_collapsed_action( // fn toggle_channel_collapsed_action(
// &mut self, // &mut self,
@ -2030,11 +2027,11 @@ impl CollabPanel {
self.collapsed_channels.binary_search(&channel_id).is_ok() self.collapsed_channels.binary_search(&channel_id).is_ok()
} }
// fn leave_call(cx: &mut ViewContext<Self>) { fn leave_call(cx: &mut ViewContext<Self>) {
// ActiveCall::global(cx) ActiveCall::global(cx)
// .update(cx, |call, cx| call.hang_up(cx)) .update(cx, |call, cx| call.hang_up(cx))
// .detach_and_log_err(cx); .detach_and_log_err(cx);
// } }
fn toggle_contact_finder(&mut self, cx: &mut ViewContext<Self>) { fn toggle_contact_finder(&mut self, cx: &mut ViewContext<Self>) {
if let Some(workspace) = self.workspace.upgrade() { if let Some(workspace) = self.workspace.upgrade() {
@ -2154,13 +2151,13 @@ impl CollabPanel {
} }
} }
// fn show_inline_context_menu(&mut self, _: &menu::ShowContextMenu, cx: &mut ViewContext<Self>) { fn show_inline_context_menu(&mut self, _: &menu::ShowContextMenu, cx: &mut ViewContext<Self>) {
// let Some(channel) = self.selected_channel() else { let Some(channel) = self.selected_channel() else {
// return; return;
// }; };
// self.deploy_channel_context_menu(None, &channel.clone(), self.selection.unwrap(), cx); self.deploy_channel_context_menu(todo!(), channel.id, self.selection.unwrap(), cx);
// } }
fn selected_channel(&self) -> Option<&Arc<Channel>> { fn selected_channel(&self) -> Option<&Arc<Channel>> {
self.selection self.selection
@ -2350,15 +2347,19 @@ impl CollabPanel {
) )
} }
fn render_signed_in(&mut self, cx: &mut ViewContext<Self>) -> List { fn render_signed_in(&mut self, cx: &mut ViewContext<Self>) -> Div {
let is_selected = false; // todo!() this.selection == Some(ix); div()
.child(
List::new().children( div()
self.entries .m_2()
.clone() .rounded(px(2.0))
.into_iter() .child(self.filter_editor.clone()),
.enumerate() )
.map(|(ix, entry)| match entry { .child(
List::new().children(self.entries.clone().into_iter().enumerate().map(
|(ix, entry)| {
let is_selected = self.selection == Some(ix);
match entry {
ListEntry::Header(section) => { ListEntry::Header(section) => {
let is_collapsed = self.collapsed_sections.contains(&section); let is_collapsed = self.collapsed_sections.contains(&section);
self.render_header(section, is_selected, is_collapsed, cx) self.render_header(section, is_selected, is_collapsed, cx)
@ -2386,7 +2387,9 @@ impl CollabPanel {
ListEntry::ChannelEditor { depth } => { ListEntry::ChannelEditor { depth } => {
self.render_channel_editor(depth, cx).into_any_element() self.render_channel_editor(depth, cx).into_any_element()
} }
}), }
},
)),
) )
} }
@ -2494,6 +2497,7 @@ impl CollabPanel {
el.child( el.child(
ListItem::new(text.clone()) ListItem::new(text.clone())
.child(div().w_full().child(Label::new(text))) .child(div().w_full().child(Label::new(text)))
.selected(is_selected)
.toggle(Some(!is_collapsed)) .toggle(Some(!is_collapsed))
.on_click(cx.listener(move |this, _, cx| { .on_click(cx.listener(move |this, _, cx| {
this.toggle_section_expanded(section, cx) this.toggle_section_expanded(section, cx)
@ -3214,23 +3218,36 @@ impl CollabPanel {
// } // }
impl Render for CollabPanel { impl Render for CollabPanel {
type Element = Focusable<Stateful<Div>>; type Element = Focusable<Div>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element { fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
div() v_stack()
.id("collab-panel")
.key_context("CollabPanel") .key_context("CollabPanel")
.on_action(cx.listener(CollabPanel::cancel))
.on_action(cx.listener(CollabPanel::select_next))
.on_action(cx.listener(CollabPanel::select_prev))
.on_action(cx.listener(CollabPanel::confirm))
.on_action(cx.listener(CollabPanel::insert_space))
// .on_action(cx.listener(CollabPanel::remove))
.on_action(cx.listener(CollabPanel::remove_selected_channel))
.on_action(cx.listener(CollabPanel::show_inline_context_menu))
// .on_action(cx.listener(CollabPanel::new_subchannel))
// .on_action(cx.listener(CollabPanel::invite_members))
// .on_action(cx.listener(CollabPanel::manage_members))
.on_action(cx.listener(CollabPanel::rename_selected_channel))
// .on_action(cx.listener(CollabPanel::rename_channel))
// .on_action(cx.listener(CollabPanel::toggle_channel_collapsed_action))
.on_action(cx.listener(CollabPanel::collapse_selected_channel))
.on_action(cx.listener(CollabPanel::expand_selected_channel))
// .on_action(cx.listener(CollabPanel::open_channel_notes))
// .on_action(cx.listener(CollabPanel::join_channel_chat))
// .on_action(cx.listener(CollabPanel::copy_channel_link))
.track_focus(&self.focus_handle) .track_focus(&self.focus_handle)
.size_full() .size_full()
.overflow_scroll() .child(if self.user_store.read(cx).current_user().is_none() {
.on_action(cx.listener(Self::confirm)) self.render_signed_out(cx)
.on_action(cx.listener(Self::insert_space))
.map(|el| {
if self.user_store.read(cx).current_user().is_none() {
el.child(self.render_signed_out(cx))
} else { } else {
el.child(self.render_signed_in(cx)) self.render_signed_in(cx)
}
}) })
.children(self.context_menu.as_ref().map(|(menu, position, _)| { .children(self.context_menu.as_ref().map(|(menu, position, _)| {
overlay() overlay()
@ -3392,8 +3409,8 @@ impl Panel for CollabPanel {
} }
impl FocusableView for CollabPanel { impl FocusableView for CollabPanel {
fn focus_handle(&self, _cx: &AppContext) -> gpui::FocusHandle { fn focus_handle(&self, cx: &AppContext) -> gpui::FocusHandle {
self.focus_handle.clone() self.filter_editor.focus_handle(cx).clone()
} }
} }