Seregon/StratoSDK

StratoSDK is a framework with a declarative approach similar to Flutter/React, written and designed entirely for Rust.

Rust/27.3 KB/No license
crates/strato-ui-core/src/notification.rs
StratoSDK / crates / strato-ui-core / src / notification.rs
1/// At the UI framework level, we have structs for interacting with
2/// platform-level notification data (mostly in the form of strings).
3/// Similar structs are available at the app level, which are more
4/// specific to the data we make use of.
5use chrono::NaiveDateTime;
6use serde::Serialize;
7 
8/// Content to be sent as a notification to the user. Includes `data` that is sent back to
9/// application when the notification is clicked--see `NotificationResponse` for more details.
10#[derive(Clone, Debug)]
11pub struct UserNotification {
12 title: String,
13 body: String,
14 // Arbitrary data associated with the notification.
15 data: Option<String>,
16 // Whether to play sound with the notification.
17 play_sound: bool,
18}
19 
20impl UserNotification {
21 /// These limits were discovered experimentally, by testing with example
22 /// commands/outputs and ensuring the text was not truncated in most cases.
23 /// The official MacOS docs do not mention specific byte/char constraints.
24 /// In reality, the strings are limited by the sum of width of the chars,
25 /// which is dependent on the string itself (e.g. 'W' is much wider than ' ').
26 pub const MAX_TITLE_LENGTH: usize = 40;
27 pub const MAX_BODY_LENGTH: usize = 120;
28 
29 pub fn new(title: String, body: String, data: Option<String>) -> Self {
30 Self {
31 title,
32 body,
33 data,
34 play_sound: true,
35 }
36 }
37 
38 pub fn new_with_sound(
39 title: String,
40 body: String,
41 data: Option<String>,
42 play_sound: bool,
43 ) -> Self {
44 Self {
45 title,
46 body,
47 data,
48 play_sound,
49 }
50 }
51 
52 pub fn with_data(mut self, data: impl Into<String>) -> Self {
53 self.data = Some(data.into());
54 self
55 }
56 
57 pub fn title(&self) -> &str {
58 self.title.as_str()
59 }
60 
61 pub fn body(&self) -> &str {
62 self.body.as_str()
63 }
64 
65 pub fn data(&self) -> Option<&str> {
66 self.data.as_deref()
67 }
68 
69 pub fn play_sound(&self) -> bool {
70 self.play_sound
71 }
72}
73 
74/// A response sent when a notification sent by the app was clicked.
75#[derive(Debug)]
76pub struct NotificationResponse {
77 // Time the notification was sent.
78 sent_date: NaiveDateTime,
79 
80 /// The data associated with the notification, if any. This matches the data included in the
81 /// `NotificationContent` when the notification was sent.
82 data: Option<String>,
83}
84 
85impl NotificationResponse {
86 pub fn new(sent_date: NaiveDateTime, data: Option<String>) -> Self {
87 NotificationResponse { sent_date, data }
88 }
89 
90 pub fn sent_date(&self) -> NaiveDateTime {
91 self.sent_date
92 }
93 
94 pub fn data(&self) -> Option<&str> {
95 self.data.as_deref()
96 }
97}
98 
99#[derive(Clone, Debug, Serialize)]
100pub enum NotificationSendError {
101 /// App does not have permissions to send notifications.
102 PermissionsDenied,
103 
104 /// On web, there's a difference between permissions being default and being denied. While they are still default,
105 /// we should prompt the user to accept or block notifications, since they haven't chosen yet.
106 PermissionsNotYetGranted,
107 
108 /// Some unknown error occurred when sending the a notification.
109 Other { error_message: String },
110}
111 
112impl NotificationSendError {
113 pub fn notifications_error_banner_title(&self) -> &str {
114 match self {
115 NotificationSendError::PermissionsDenied | NotificationSendError::PermissionsNotYetGranted => "Warp tried to send you a notification for the last block but does not have permission.",
116 NotificationSendError::Other { .. } => "Warp tried to send you a notification for the last block, but something went wrong.",
117 }
118 }
119}
120 
121#[derive(Clone, Debug, Serialize)]
122pub enum RequestPermissionsOutcome {
123 /// User accepted the request for permissions.
124 Accepted,
125 /// User explicitly denied permissions.
126 PermissionsDenied,
127 /// Some unknown error occurred when requesting permissions.
128 OtherError { error_message: String },
129}
130