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