Dismiss contact request notification if request is cancelled

This commit is contained in:
Nathan Sobo 2022-05-10 18:50:18 -06:00
parent 3bca1c29e2
commit fe89de8b11
5 changed files with 100 additions and 45 deletions

View file

@ -55,7 +55,8 @@ pub struct UserStore {
}
pub enum Event {
NotifyIncomingRequest(Arc<User>),
ContactRequested(Arc<User>),
ContactRequestCancelled(Arc<User>),
}
impl Entity for UserStore {
@ -225,12 +226,18 @@ impl UserStore {
}
// Remove incoming contact requests
this.incoming_contact_requests
.retain(|user| !removed_incoming_requests.contains(&user.id));
this.incoming_contact_requests.retain(|user| {
if removed_incoming_requests.contains(&user.id) {
cx.emit(Event::ContactRequestCancelled(user.clone()));
false
} else {
true
}
});
// Update existing incoming requests and insert new ones
for (user, should_notify) in incoming_requests {
if should_notify {
cx.emit(Event::NotifyIncomingRequest(user.clone()));
cx.emit(Event::ContactRequested(user.clone()));
}
match this

View file

@ -0,0 +1,58 @@
use client::{User, UserStore};
use gpui::{color::Color, elements::*, Entity, ModelHandle, View, ViewContext};
use std::sync::Arc;
use workspace::Notification;
pub struct IncomingRequestNotification {
user: Arc<User>,
user_store: ModelHandle<UserStore>,
}
pub enum Event {
Dismiss,
}
impl Entity for IncomingRequestNotification {
type Event = Event;
}
impl View for IncomingRequestNotification {
fn ui_name() -> &'static str {
"IncomingRequestNotification"
}
fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> ElementBox {
Empty::new()
.constrained()
.with_height(200.)
.contained()
.with_background_color(Color::red())
.boxed()
}
}
impl Notification for IncomingRequestNotification {
fn should_dismiss_notification_on_event(&self, event: &<Self as Entity>::Event) -> bool {
matches!(event, Event::Dismiss)
}
}
impl IncomingRequestNotification {
pub fn new(
user: Arc<User>,
user_store: ModelHandle<UserStore>,
cx: &mut ViewContext<Self>,
) -> Self {
let user_id = user.id;
cx.subscribe(&user_store, move |_, _, event, cx| {
if let client::Event::ContactRequestCancelled(user) = event {
if user.id == user_id {
cx.emit(Event::Dismiss);
}
}
})
.detach();
Self { user, user_store }
}
}

View file

@ -1,7 +1,8 @@
mod contact_finder;
mod notifications;
mod contact_notifications;
use client::{Contact, User, UserStore};
use contact_notifications::IncomingRequestNotification;
use editor::{Cancel, Editor};
use fuzzy::{match_strings, StringMatchCandidate};
use gpui::{
@ -12,7 +13,6 @@ use gpui::{
Element, ElementBox, Entity, LayoutContext, ModelHandle, MutableAppContext, RenderContext,
Subscription, View, ViewContext, ViewHandle, WeakViewHandle,
};
use notifications::IncomingRequestNotification;
use serde::Deserialize;
use settings::Settings;
use std::sync::Arc;
@ -86,14 +86,15 @@ impl ContactsPanel {
cx.subscribe(&app_state.user_store, {
let user_store = app_state.user_store.clone();
move |_, _, event, cx| match event {
client::Event::NotifyIncomingRequest(user) => {
client::Event::ContactRequested(user) => {
if let Some(workspace) = workspace.upgrade(cx) {
workspace.update(cx, |workspace, cx| {
workspace.show_notification(
cx.add_view(|_| {
cx.add_view(|cx| {
IncomingRequestNotification::new(
user.clone(),
user_store.clone(),
cx,
)
}),
cx,
@ -101,6 +102,7 @@ impl ContactsPanel {
})
}
}
_ => {}
}
})
.detach();

View file

@ -1,36 +0,0 @@
use client::{User, UserStore};
use gpui::{color::Color, elements::*, Entity, ModelHandle, View};
use std::sync::Arc;
use workspace::Notification;
pub struct IncomingRequestNotification {
user: Arc<User>,
user_store: ModelHandle<UserStore>,
}
impl Entity for IncomingRequestNotification {
type Event = ();
}
impl View for IncomingRequestNotification {
fn ui_name() -> &'static str {
"IncomingRequestNotification"
}
fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> ElementBox {
Empty::new()
.constrained()
.with_height(200.)
.contained()
.with_background_color(Color::red())
.boxed()
}
}
impl Notification for IncomingRequestNotification {}
impl IncomingRequestNotification {
pub fn new(user: Arc<User>, user_store: ModelHandle<UserStore>) -> Self {
Self { user, user_store }
}
}

View file

@ -604,13 +604,20 @@ impl<T: Item> WeakItemHandle for WeakViewHandle<T> {
}
}
pub trait Notification: View {}
pub trait Notification: View {
fn should_dismiss_notification_on_event(&self, event: &<Self as Entity>::Event) -> bool;
}
pub trait NotificationHandle {
fn id(&self) -> usize;
fn to_any(&self) -> AnyViewHandle;
}
impl<T: Notification> NotificationHandle for ViewHandle<T> {
fn id(&self) -> usize {
self.id()
}
fn to_any(&self) -> AnyViewHandle {
self.into()
}
@ -996,10 +1003,27 @@ impl Workspace {
notification: ViewHandle<V>,
cx: &mut ViewContext<Self>,
) {
cx.subscribe(&notification, |this, handle, event, cx| {
if handle.read(cx).should_dismiss_notification_on_event(event) {
this.dismiss_notification(handle.id(), cx);
}
})
.detach();
self.notifications.push(Box::new(notification));
cx.notify();
}
fn dismiss_notification(&mut self, id: usize, cx: &mut ViewContext<Self>) {
self.notifications.retain(|handle| {
if handle.id() == id {
cx.notify();
false
} else {
true
}
});
}
pub fn items<'a>(
&'a self,
cx: &'a AppContext,