use std::sync::Arc; use crate::notifications::render_user_notification; use client::{ContactEventKind, User, UserStore}; use gpui::{ elements::*, impl_internal_actions, AppContext, Entity, ModelHandle, View, ViewContext, }; use workspace::notifications::Notification; impl_internal_actions!(contact_notifications, [Dismiss, RespondToContactRequest]); pub fn init(cx: &mut AppContext) { cx.add_action(ContactNotification::dismiss); cx.add_action(ContactNotification::respond_to_contact_request); } 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."), Dismiss(self.user.id), vec![ ( "Decline", Box::new(RespondToContactRequest { user_id: self.user.id, accept: false, }), ), ( "Accept", Box::new(RespondToContactRequest { user_id: self.user.id, accept: true, }), ), ], cx, ), ContactEventKind::Accepted => render_user_notification( self.user.clone(), "accepted your contact request", None, Dismiss(self.user.id), 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, _: &Dismiss, 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, action: &RespondToContactRequest, cx: &mut ViewContext, ) { self.user_store .update(cx, |store, cx| { store.respond_to_contact_request(action.user_id, action.accept, cx) }) .detach(); } }