use std::sync::Arc; use crate::notifications::render_user_notification; use client::{ContactEventKind, User, UserStore}; use gpui::{elements::*, Entity, ModelHandle, View, ViewContext}; use workspace::notifications::Notification; pub struct ContactNotification { user_store: ModelHandle, user: Arc, kind: client::ContactEventKind, } #[derive(Clone, PartialEq)] struct Dismiss(u64); #[derive(Clone, PartialEq)] pub struct RespondToContactRequest { pub user_id: u64, pub accept: bool, } pub enum Event { Dismiss, } impl Entity for ContactNotification { type Event = Event; } impl View for ContactNotification { fn ui_name() -> &'static str { "ContactNotification" } fn render(&mut self, cx: &mut ViewContext) -> AnyElement { match self.kind { ContactEventKind::Requested => render_user_notification( self.user.clone(), "wants to add you as a contact", Some("They won't be alerted if you decline."), |notification, cx| notification.dismiss(cx), vec![ ( "Decline", Box::new(|notification, cx| { notification.respond_to_contact_request(false, cx) }), ), ( "Accept", Box::new(|notification, cx| { notification.respond_to_contact_request(true, cx) }), ), ], cx, ), ContactEventKind::Accepted => render_user_notification( self.user.clone(), "accepted your contact request", None, |notification, cx| notification.dismiss(cx), vec![], cx, ), _ => unreachable!(), } } } impl Notification for ContactNotification { fn should_dismiss_notification_on_event(&self, event: &::Event) -> bool { matches!(event, Event::Dismiss) } } impl ContactNotification { pub fn new( user: Arc, kind: client::ContactEventKind, user_store: ModelHandle, cx: &mut ViewContext, ) -> Self { cx.subscribe(&user_store, move |this, _, event, cx| { if let client::Event::Contact { kind: ContactEventKind::Cancelled, user, } = event { if user.id == this.user.id { cx.emit(Event::Dismiss); } } }) .detach(); Self { user, kind, user_store, } } fn dismiss(&mut self, cx: &mut ViewContext) { self.user_store.update(cx, |store, cx| { store .dismiss_contact_request(self.user.id, cx) .detach_and_log_err(cx); }); cx.emit(Event::Dismiss); } fn respond_to_contact_request(&mut self, accept: bool, cx: &mut ViewContext) { self.user_store .update(cx, |store, cx| { store.respond_to_contact_request(self.user.id, accept, cx) }) .detach(); } }