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 { pub enum Event {
NotifyIncomingRequest(Arc<User>), ContactRequested(Arc<User>),
ContactRequestCancelled(Arc<User>),
} }
impl Entity for UserStore { impl Entity for UserStore {
@ -225,12 +226,18 @@ impl UserStore {
} }
// Remove incoming contact requests // Remove incoming contact requests
this.incoming_contact_requests this.incoming_contact_requests.retain(|user| {
.retain(|user| !removed_incoming_requests.contains(&user.id)); if removed_incoming_requests.contains(&user.id) {
cx.emit(Event::ContactRequestCancelled(user.clone()));
false
} else {
true
}
});
// Update existing incoming requests and insert new ones // Update existing incoming requests and insert new ones
for (user, should_notify) in incoming_requests { for (user, should_notify) in incoming_requests {
if should_notify { if should_notify {
cx.emit(Event::NotifyIncomingRequest(user.clone())); cx.emit(Event::ContactRequested(user.clone()));
} }
match this 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 contact_finder;
mod notifications; mod contact_notifications;
use client::{Contact, User, UserStore}; use client::{Contact, User, UserStore};
use contact_notifications::IncomingRequestNotification;
use editor::{Cancel, Editor}; use editor::{Cancel, Editor};
use fuzzy::{match_strings, StringMatchCandidate}; use fuzzy::{match_strings, StringMatchCandidate};
use gpui::{ use gpui::{
@ -12,7 +13,6 @@ use gpui::{
Element, ElementBox, Entity, LayoutContext, ModelHandle, MutableAppContext, RenderContext, Element, ElementBox, Entity, LayoutContext, ModelHandle, MutableAppContext, RenderContext,
Subscription, View, ViewContext, ViewHandle, WeakViewHandle, Subscription, View, ViewContext, ViewHandle, WeakViewHandle,
}; };
use notifications::IncomingRequestNotification;
use serde::Deserialize; use serde::Deserialize;
use settings::Settings; use settings::Settings;
use std::sync::Arc; use std::sync::Arc;
@ -86,14 +86,15 @@ impl ContactsPanel {
cx.subscribe(&app_state.user_store, { cx.subscribe(&app_state.user_store, {
let user_store = app_state.user_store.clone(); let user_store = app_state.user_store.clone();
move |_, _, event, cx| match event { move |_, _, event, cx| match event {
client::Event::NotifyIncomingRequest(user) => { client::Event::ContactRequested(user) => {
if let Some(workspace) = workspace.upgrade(cx) { if let Some(workspace) = workspace.upgrade(cx) {
workspace.update(cx, |workspace, cx| { workspace.update(cx, |workspace, cx| {
workspace.show_notification( workspace.show_notification(
cx.add_view(|_| { cx.add_view(|cx| {
IncomingRequestNotification::new( IncomingRequestNotification::new(
user.clone(), user.clone(),
user_store.clone(), user_store.clone(),
cx,
) )
}), }),
cx, cx,
@ -101,6 +102,7 @@ impl ContactsPanel {
}) })
} }
} }
_ => {}
} }
}) })
.detach(); .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 { pub trait NotificationHandle {
fn id(&self) -> usize;
fn to_any(&self) -> AnyViewHandle; fn to_any(&self) -> AnyViewHandle;
} }
impl<T: Notification> NotificationHandle for ViewHandle<T> { impl<T: Notification> NotificationHandle for ViewHandle<T> {
fn id(&self) -> usize {
self.id()
}
fn to_any(&self) -> AnyViewHandle { fn to_any(&self) -> AnyViewHandle {
self.into() self.into()
} }
@ -996,10 +1003,27 @@ impl Workspace {
notification: ViewHandle<V>, notification: ViewHandle<V>,
cx: &mut ViewContext<Self>, 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)); self.notifications.push(Box::new(notification));
cx.notify(); 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>( pub fn items<'a>(
&'a self, &'a self,
cx: &'a AppContext, cx: &'a AppContext,