diff --git a/crates/client/src/channel_store.rs b/crates/client/src/channel_store.rs index 13510a1e1c..317fbd1189 100644 --- a/crates/client/src/channel_store.rs +++ b/crates/client/src/channel_store.rs @@ -127,17 +127,21 @@ impl ChannelStore { cx.notify(); let client = self.client.clone(); cx.spawn(|this, mut cx| async move { - client + let result = client .request(proto::InviteChannelMember { channel_id, user_id, admin, }) - .await?; + .await; + this.update(&mut cx, |this, cx| { this.outgoing_invites.remove(&(channel_id, user_id)); cx.notify(); }); + + result?; + Ok(()) }) } @@ -155,16 +159,18 @@ impl ChannelStore { cx.notify(); let client = self.client.clone(); cx.spawn(|this, mut cx| async move { - client + let result = client .request(proto::RemoveChannelMember { channel_id, user_id, }) - .await?; + .await; + this.update(&mut cx, |this, cx| { this.outgoing_invites.remove(&(channel_id, user_id)); cx.notify(); }); + result?; Ok(()) }) } @@ -183,17 +189,20 @@ impl ChannelStore { cx.notify(); let client = self.client.clone(); cx.spawn(|this, mut cx| async move { - client + let result = client .request(proto::SetChannelMemberAdmin { channel_id, user_id, admin, }) - .await?; + .await; + this.update(&mut cx, |this, cx| { this.outgoing_invites.remove(&(channel_id, user_id)); cx.notify(); }); + + result?; Ok(()) }) } diff --git a/crates/collab_ui/src/collab_panel/channel_modal.rs b/crates/collab_ui/src/collab_panel/channel_modal.rs index 0671eee8af..fc1b86354f 100644 --- a/crates/collab_ui/src/collab_panel/channel_modal.rs +++ b/crates/collab_ui/src/collab_panel/channel_modal.rs @@ -45,15 +45,7 @@ impl ChannelModal { user_store: user_store.clone(), channel_store: channel_store.clone(), channel_id, - match_candidates: members - .iter() - .enumerate() - .map(|(id, member)| StringMatchCandidate { - id, - string: member.user.github_login.clone(), - char_bag: member.user.github_login.chars().collect(), - }) - .collect(), + match_candidates: Vec::new(), members, mode, selected_column: None, @@ -256,7 +248,7 @@ pub struct ChannelModalDelegate { selected_index: usize, mode: Mode, selected_column: Option, - match_candidates: Arc<[StringMatchCandidate]>, + match_candidates: Vec, members: Vec, } @@ -287,30 +279,36 @@ impl PickerDelegate for ChannelModalDelegate { fn update_matches(&mut self, query: String, cx: &mut ViewContext>) -> Task<()> { match self.mode { Mode::ManageMembers => { - let match_candidates = self.match_candidates.clone(); + self.match_candidates.clear(); + self.match_candidates + .extend(self.members.iter().enumerate().map(|(id, member)| { + StringMatchCandidate { + id, + string: member.user.github_login.clone(), + char_bag: member.user.github_login.chars().collect(), + } + })); + + let matches = cx.background().block(match_strings( + &self.match_candidates, + &query, + true, + usize::MAX, + &Default::default(), + cx.background().clone(), + )); + cx.spawn(|picker, mut cx| async move { - async move { - let matches = match_strings( - &match_candidates, - &query, - true, - usize::MAX, - &Default::default(), - cx.background().clone(), - ) - .await; - picker.update(&mut cx, |picker, cx| { + picker + .update(&mut cx, |picker, cx| { let delegate = picker.delegate_mut(); delegate.matching_member_indices.clear(); delegate .matching_member_indices .extend(matches.into_iter().map(|m| m.candidate_id)); cx.notify(); - })?; - anyhow::Ok(()) - } - .log_err() - .await; + }) + .ok(); }) } Mode::InviteMembers => { @@ -346,11 +344,7 @@ impl PickerDelegate for ChannelModalDelegate { } } Some(proto::channel_member::Kind::AncestorMember) | None => { - self.channel_store - .update(cx, |store, cx| { - store.invite_member(self.channel_id, selected_user.id, false, cx) - }) - .detach(); + self.invite_member(selected_user, cx) } } } @@ -386,41 +380,24 @@ impl PickerDelegate for ChannelModalDelegate { .aligned() .left(), ) - .with_children(admin.map(|admin| { - let member_style = theme.admin_toggle_part.in_state(!admin); - let admin_style = theme.admin_toggle_part.in_state(admin); - Flex::row() - .with_child( - Label::new("member", member_style.text.clone()) - .contained() - .with_style(member_style.container), - ) - .with_child( - Label::new("admin", admin_style.text.clone()) - .contained() - .with_style(admin_style.container), - ) + .with_children(admin.map(|_| { + Label::new("admin", theme.admin_toggle.text.clone()) .contained() - .with_style(theme.admin_toggle) + .with_style(theme.admin_toggle.container) .aligned() - .flex_float() })) .with_children({ match self.mode { Mode::ManageMembers => match request_status { - Some(proto::channel_member::Kind::Member) => Some( - Label::new("remove member", theme.remove_member_button.text.clone()) - .contained() - .with_style(theme.remove_member_button.container) - .into_any(), - ), Some(proto::channel_member::Kind::Invitee) => Some( Label::new("cancel invite", theme.cancel_invite_button.text.clone()) .contained() .with_style(theme.cancel_invite_button.container) .into_any(), ), - Some(proto::channel_member::Kind::AncestorMember) | None => None, + Some(proto::channel_member::Kind::Member) + | Some(proto::channel_member::Kind::AncestorMember) + | None => None, }, Mode::InviteMembers => { let svg = match request_status { @@ -466,11 +443,12 @@ impl ChannelModalDelegate { self.members .iter() .find_map(|membership| (membership.user.id == user_id).then_some(membership.kind)) - .or(self - .channel_store - .read(cx) - .has_pending_channel_invite(self.channel_id, user_id) - .then_some(proto::channel_member::Kind::Invitee)) + .or_else(|| { + self.channel_store + .read(cx) + .has_pending_channel_invite(self.channel_id, user_id) + .then_some(proto::channel_member::Kind::Invitee) + }) } fn user_at_index(&self, ix: usize) -> Option<(Arc, Option)> { @@ -517,4 +495,25 @@ impl ChannelModalDelegate { }) .detach_and_log_err(cx); } + + fn invite_member(&mut self, user: Arc, cx: &mut ViewContext>) { + let invite_member = self.channel_store.update(cx, |store, cx| { + store.invite_member(self.channel_id, user.id, false, cx) + }); + + cx.spawn(|this, mut cx| async move { + invite_member.await?; + + this.update(&mut cx, |this, cx| { + let delegate_mut = this.delegate_mut(); + delegate_mut.members.push(ChannelMembership { + user, + kind: proto::channel_member::Kind::Invitee, + admin: false, + }); + cx.notify(); + }) + }) + .detach_and_log_err(cx); + } } diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index 8bd673d1b3..c778b5fc88 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -261,8 +261,7 @@ pub struct ChannelModal { pub cancel_invite_button: ContainedText, pub member_icon: Icon, pub invitee_icon: Icon, - pub admin_toggle: ContainerStyle, - pub admin_toggle_part: Toggleable, + pub admin_toggle: ContainedText, } #[derive(Deserialize, Default, JsonSchema)] diff --git a/styles/src/style_tree/channel_modal.ts b/styles/src/style_tree/channel_modal.ts index 8dc9e79967..40fd497458 100644 --- a/styles/src/style_tree/channel_modal.ts +++ b/styles/src/style_tree/channel_modal.ts @@ -76,21 +76,8 @@ export default function channel_modal(): any { ...text(theme.middle, "sans", { size: "xs" }), background: background(theme.middle), }, - admin_toggle_part: toggleable({ - base: { - ...text(theme.middle, "sans", { size: "xs" }), - padding: { - left: 7, - right: 7, - }, - }, - state: { - active: { - background: background(theme.middle, "on"), - } - } - }), admin_toggle: { + ...text(theme.middle, "sans", { size: "xs" }), border: border(theme.middle, "active"), background: background(theme.middle), margin: {