Tune UX for context menus
Co-authored-by: max <max@zed.dev>
This commit is contained in:
parent
bedf60b6b2
commit
fa71de8842
3 changed files with 56 additions and 21 deletions
|
@ -165,17 +165,29 @@ impl UserStore {
|
||||||
});
|
});
|
||||||
|
|
||||||
current_user_tx.send(user).await.ok();
|
current_user_tx.send(user).await.ok();
|
||||||
|
|
||||||
|
this.update(&mut cx, |_, cx| {
|
||||||
|
cx.notify();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Status::SignedOut => {
|
Status::SignedOut => {
|
||||||
current_user_tx.send(None).await.ok();
|
current_user_tx.send(None).await.ok();
|
||||||
if let Some(this) = this.upgrade(&cx) {
|
if let Some(this) = this.upgrade(&cx) {
|
||||||
this.update(&mut cx, |this, _| this.clear_contacts()).await;
|
this.update(&mut cx, |this, cx| {
|
||||||
|
cx.notify();
|
||||||
|
this.clear_contacts()
|
||||||
|
})
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Status::ConnectionLost => {
|
Status::ConnectionLost => {
|
||||||
if let Some(this) = this.upgrade(&cx) {
|
if let Some(this) = this.upgrade(&cx) {
|
||||||
this.update(&mut cx, |this, _| this.clear_contacts()).await;
|
this.update(&mut cx, |this, cx| {
|
||||||
|
cx.notify();
|
||||||
|
this.clear_contacts()
|
||||||
|
})
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -4,7 +4,7 @@ mod panel_settings;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use call::ActiveCall;
|
use call::ActiveCall;
|
||||||
use client::{proto::PeerId, Channel, ChannelStore, Client, Contact, User, UserStore};
|
use client::{proto::PeerId, Channel, ChannelId, ChannelStore, Client, Contact, User, UserStore};
|
||||||
use contact_finder::build_contact_finder;
|
use contact_finder::build_contact_finder;
|
||||||
use context_menu::{ContextMenu, ContextMenuItem};
|
use context_menu::{ContextMenu, ContextMenuItem};
|
||||||
use db::kvp::KEY_VALUE_STORE;
|
use db::kvp::KEY_VALUE_STORE;
|
||||||
|
@ -55,13 +55,21 @@ struct NewChannel {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
struct AddMember {
|
struct InviteMembers {
|
||||||
|
channel_id: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
|
struct ManageMembers {
|
||||||
channel_id: u64,
|
channel_id: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
actions!(collab_panel, [ToggleFocus]);
|
actions!(collab_panel, [ToggleFocus]);
|
||||||
|
|
||||||
impl_actions!(collab_panel, [RemoveChannel, NewChannel, AddMember]);
|
impl_actions!(
|
||||||
|
collab_panel,
|
||||||
|
[RemoveChannel, NewChannel, InviteMembers, ManageMembers]
|
||||||
|
);
|
||||||
|
|
||||||
const CHANNELS_PANEL_KEY: &'static str = "ChannelsPanel";
|
const CHANNELS_PANEL_KEY: &'static str = "ChannelsPanel";
|
||||||
|
|
||||||
|
@ -76,7 +84,8 @@ pub fn init(_client: Arc<Client>, cx: &mut AppContext) {
|
||||||
cx.add_action(CollabPanel::confirm);
|
cx.add_action(CollabPanel::confirm);
|
||||||
cx.add_action(CollabPanel::remove_channel);
|
cx.add_action(CollabPanel::remove_channel);
|
||||||
cx.add_action(CollabPanel::new_subchannel);
|
cx.add_action(CollabPanel::new_subchannel);
|
||||||
cx.add_action(CollabPanel::add_member);
|
cx.add_action(CollabPanel::invite_members);
|
||||||
|
cx.add_action(CollabPanel::manage_members);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
@ -325,6 +334,7 @@ impl CollabPanel {
|
||||||
client: workspace.app_state().client.clone(),
|
client: workspace.app_state().client.clone(),
|
||||||
list_state,
|
list_state,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.update_entries(cx);
|
this.update_entries(cx);
|
||||||
|
|
||||||
// Update the dock position when the setting changes.
|
// Update the dock position when the setting changes.
|
||||||
|
@ -1549,7 +1559,8 @@ impl CollabPanel {
|
||||||
vec![
|
vec![
|
||||||
ContextMenuItem::action("New Channel", NewChannel { channel_id }),
|
ContextMenuItem::action("New Channel", NewChannel { channel_id }),
|
||||||
ContextMenuItem::action("Remove Channel", RemoveChannel { channel_id }),
|
ContextMenuItem::action("Remove Channel", RemoveChannel { channel_id }),
|
||||||
ContextMenuItem::action("Add member", AddMember { channel_id }),
|
ContextMenuItem::action("Manage members", ManageMembers { channel_id }),
|
||||||
|
ContextMenuItem::action("Invite members", InviteMembers { channel_id }),
|
||||||
],
|
],
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
|
@ -1710,8 +1721,20 @@ impl CollabPanel {
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_member(&mut self, action: &AddMember, cx: &mut ViewContext<Self>) {
|
fn invite_members(&mut self, action: &InviteMembers, cx: &mut ViewContext<Self>) {
|
||||||
let channel_id = action.channel_id;
|
self.show_channel_modal(action.channel_id, channel_modal::Mode::InviteMembers, cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn manage_members(&mut self, action: &ManageMembers, cx: &mut ViewContext<Self>) {
|
||||||
|
self.show_channel_modal(action.channel_id, channel_modal::Mode::ManageMembers, cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show_channel_modal(
|
||||||
|
&mut self,
|
||||||
|
channel_id: ChannelId,
|
||||||
|
mode: channel_modal::Mode,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) {
|
||||||
let workspace = self.workspace.clone();
|
let workspace = self.workspace.clone();
|
||||||
let user_store = self.user_store.clone();
|
let user_store = self.user_store.clone();
|
||||||
let channel_store = self.channel_store.clone();
|
let channel_store = self.channel_store.clone();
|
||||||
|
@ -1728,7 +1751,7 @@ impl CollabPanel {
|
||||||
user_store.clone(),
|
user_store.clone(),
|
||||||
channel_store.clone(),
|
channel_store.clone(),
|
||||||
channel_id,
|
channel_id,
|
||||||
channel_modal::Mode::InviteMembers,
|
mode,
|
||||||
members,
|
members,
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
|
@ -1879,12 +1902,8 @@ impl View for CollabPanel {
|
||||||
})
|
})
|
||||||
.on_click(MouseButton::Left, |_, this, cx| {
|
.on_click(MouseButton::Left, |_, this, cx| {
|
||||||
let client = this.client.clone();
|
let client = this.client.clone();
|
||||||
cx.spawn(|this, mut cx| async move {
|
cx.spawn(|_, cx| async move {
|
||||||
client.authenticate_and_connect(true, &cx).await.log_err();
|
client.authenticate_and_connect(true, &cx).await.log_err();
|
||||||
|
|
||||||
this.update(&mut cx, |_, cx| {
|
|
||||||
cx.notify();
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
})
|
})
|
||||||
|
|
|
@ -337,7 +337,7 @@ impl PickerDelegate for ChannelModalDelegate {
|
||||||
Mode::ManageMembers => self.show_context_menu(admin.unwrap_or(false), cx),
|
Mode::ManageMembers => self.show_context_menu(admin.unwrap_or(false), cx),
|
||||||
Mode::InviteMembers => match self.member_status(selected_user.id, cx) {
|
Mode::InviteMembers => match self.member_status(selected_user.id, cx) {
|
||||||
Some(proto::channel_member::Kind::Invitee) => {
|
Some(proto::channel_member::Kind::Invitee) => {
|
||||||
self.remove_member(selected_user.id, cx);
|
self.remove_selected_member(cx);
|
||||||
}
|
}
|
||||||
Some(proto::channel_member::Kind::AncestorMember) | None => {
|
Some(proto::channel_member::Kind::AncestorMember) | None => {
|
||||||
self.invite_member(selected_user, cx)
|
self.invite_member(selected_user, cx)
|
||||||
|
@ -502,6 +502,7 @@ impl ChannelModalDelegate {
|
||||||
if let Some(member) = this.members.iter_mut().find(|m| m.user.id == user.id) {
|
if let Some(member) = this.members.iter_mut().find(|m| m.user.id == user.id) {
|
||||||
member.admin = admin;
|
member.admin = admin;
|
||||||
}
|
}
|
||||||
|
cx.focus_self();
|
||||||
cx.notify();
|
cx.notify();
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -511,11 +512,7 @@ impl ChannelModalDelegate {
|
||||||
|
|
||||||
fn remove_selected_member(&mut self, cx: &mut ViewContext<Picker<Self>>) -> Option<()> {
|
fn remove_selected_member(&mut self, cx: &mut ViewContext<Picker<Self>>) -> Option<()> {
|
||||||
let (user, _) = self.user_at_index(self.selected_index)?;
|
let (user, _) = self.user_at_index(self.selected_index)?;
|
||||||
self.remove_member(user.id, cx);
|
let user_id = user.id;
|
||||||
Some(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remove_member(&mut self, user_id: u64, cx: &mut ViewContext<Picker<Self>>) {
|
|
||||||
let update = self.channel_store.update(cx, |store, cx| {
|
let update = self.channel_store.update(cx, |store, cx| {
|
||||||
store.remove_member(self.channel_id, user_id, cx)
|
store.remove_member(self.channel_id, user_id, cx)
|
||||||
});
|
});
|
||||||
|
@ -534,10 +531,17 @@ impl ChannelModalDelegate {
|
||||||
true
|
true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.selected_index = this
|
||||||
|
.selected_index
|
||||||
|
.min(this.matching_member_indices.len() - 1);
|
||||||
|
|
||||||
|
cx.focus_self();
|
||||||
cx.notify();
|
cx.notify();
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.detach_and_log_err(cx);
|
.detach_and_log_err(cx);
|
||||||
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn invite_member(&mut self, user: Arc<User>, cx: &mut ViewContext<Picker<Self>>) {
|
fn invite_member(&mut self, user: Arc<User>, cx: &mut ViewContext<Picker<Self>>) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue