contact_notification.rs

  1use std::sync::Arc;
  2
  3use crate::notifications::render_user_notification;
  4use client::{ContactEventKind, User, UserStore};
  5use gpui::{
  6    elements::*, impl_internal_actions, Entity, ModelHandle, MutableAppContext, RenderContext,
  7    View, ViewContext,
  8};
  9use workspace::notifications::Notification;
 10
 11impl_internal_actions!(contact_notifications, [Dismiss, RespondToContactRequest]);
 12
 13pub fn init(cx: &mut MutableAppContext) {
 14    cx.add_action(ContactNotification::dismiss);
 15    cx.add_action(ContactNotification::respond_to_contact_request);
 16}
 17
 18pub struct ContactNotification {
 19    user_store: ModelHandle<UserStore>,
 20    user: Arc<User>,
 21    kind: client::ContactEventKind,
 22}
 23
 24#[derive(Clone, PartialEq)]
 25struct Dismiss(u64);
 26
 27#[derive(Clone, PartialEq)]
 28pub struct RespondToContactRequest {
 29    pub user_id: u64,
 30    pub accept: bool,
 31}
 32
 33pub enum Event {
 34    Dismiss,
 35}
 36
 37impl Entity for ContactNotification {
 38    type Event = Event;
 39}
 40
 41impl View for ContactNotification {
 42    fn ui_name() -> &'static str {
 43        "ContactNotification"
 44    }
 45
 46    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
 47        match self.kind {
 48            ContactEventKind::Requested => render_user_notification(
 49                self.user.clone(),
 50                "wants to add you as a contact",
 51                Some("They won't know if you decline."),
 52                Dismiss(self.user.id),
 53                vec![
 54                    (
 55                        "Decline",
 56                        Box::new(RespondToContactRequest {
 57                            user_id: self.user.id,
 58                            accept: false,
 59                        }),
 60                    ),
 61                    (
 62                        "Accept",
 63                        Box::new(RespondToContactRequest {
 64                            user_id: self.user.id,
 65                            accept: true,
 66                        }),
 67                    ),
 68                ],
 69                cx,
 70            ),
 71            ContactEventKind::Accepted => render_user_notification(
 72                self.user.clone(),
 73                "accepted your contact request",
 74                None,
 75                Dismiss(self.user.id),
 76                vec![],
 77                cx,
 78            ),
 79            _ => unreachable!(),
 80        }
 81    }
 82}
 83
 84impl Notification for ContactNotification {
 85    fn should_dismiss_notification_on_event(&self, event: &<Self as Entity>::Event) -> bool {
 86        matches!(event, Event::Dismiss)
 87    }
 88}
 89
 90impl ContactNotification {
 91    pub fn new(
 92        user: Arc<User>,
 93        kind: client::ContactEventKind,
 94        user_store: ModelHandle<UserStore>,
 95        cx: &mut ViewContext<Self>,
 96    ) -> Self {
 97        cx.subscribe(&user_store, move |this, _, event, cx| {
 98            if let client::Event::Contact {
 99                kind: ContactEventKind::Cancelled,
100                user,
101            } = event
102            {
103                if user.id == this.user.id {
104                    cx.emit(Event::Dismiss);
105                }
106            }
107        })
108        .detach();
109
110        Self {
111            user,
112            kind,
113            user_store,
114        }
115    }
116
117    fn dismiss(&mut self, _: &Dismiss, cx: &mut ViewContext<Self>) {
118        self.user_store.update(cx, |store, cx| {
119            store
120                .dismiss_contact_request(self.user.id, cx)
121                .detach_and_log_err(cx);
122        });
123        cx.emit(Event::Dismiss);
124    }
125
126    fn respond_to_contact_request(
127        &mut self,
128        action: &RespondToContactRequest,
129        cx: &mut ViewContext<Self>,
130    ) {
131        self.user_store
132            .update(cx, |store, cx| {
133                store.respond_to_contact_request(action.user_id, action.accept, cx)
134            })
135            .detach();
136    }
137}