From f776c742b4811ef2c2d5175acaa794807b44310b Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Sat, 29 Apr 2023 12:30:40 -0300 Subject: [PATCH] update android impl --- Cargo.lock | 1 + plugins/notification/Cargo.toml | 1 + .../android/src/main/java/Notification.kt | 55 +++++------------- .../src/main/java/NotificationPlugin.kt | 56 ++++++++++++++----- .../src/main/java/NotificationStorage.kt | 4 +- .../src/main/java/TauriNotificationManager.kt | 52 ++++++++--------- plugins/notification/src/lib.rs | 8 ++- plugins/notification/src/mobile.rs | 9 ++- 8 files changed, 96 insertions(+), 90 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 365ada67..840d45f6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4927,6 +4927,7 @@ version = "0.1.0" dependencies = [ "log", "notify-rust", + "rand 0.8.5", "serde", "serde_json", "tauri", diff --git a/plugins/notification/Cargo.toml b/plugins/notification/Cargo.toml index 57d5c149..cbdb1830 100644 --- a/plugins/notification/Cargo.toml +++ b/plugins/notification/Cargo.toml @@ -16,6 +16,7 @@ serde_json.workspace = true tauri.workspace = true log.workspace = true thiserror.workspace = true +rand = "0.8" [target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies] notify-rust = "4.5" diff --git a/plugins/notification/android/src/main/java/Notification.kt b/plugins/notification/android/src/main/java/Notification.kt index ad4facb3..28a58834 100644 --- a/plugins/notification/android/src/main/java/Notification.kt +++ b/plugins/notification/android/src/main/java/Notification.kt @@ -17,7 +17,7 @@ class Notification { var body: String? = null var largeBody: String? = null var summary: String? = null - var id: Int? = null + var id: Int = 0 private var sound: String? = null private var smallIcon: String? = null private var largeIcon: String? = null @@ -136,7 +136,7 @@ class Notification { if (if (title != null) title != that.title else that.title != null) return false if (if (body != null) body != that.body else that.body != null) return false if (if (largeBody != null) largeBody != that.largeBody else that.largeBody != null) return false - if (if (id != null) id != that.id else that.id != null) return false + if (id != that.id) return false if (if (sound != null) sound != that.sound else that.sound != null) return false if (if (smallIcon != null) smallIcon != that.smallIcon else that.smallIcon != null) return false if (if (largeIcon != null) largeIcon != that.largeIcon else that.largeIcon != null) return false @@ -155,7 +155,7 @@ class Notification { override fun hashCode(): Int { var result = if (title != null) title.hashCode() else 0 result = 31 * result + if (body != null) body.hashCode() else 0 - result = 31 * result + if (id != null) id.hashCode() else 0 + result = 31 * result + id.hashCode() result = 31 * result + if (sound != null) sound.hashCode() else 0 result = 31 * result + if (smallIcon != null) smallIcon.hashCode() else 0 result = 31 * result + if (iconColor != null) iconColor.hashCode() else 0 @@ -180,50 +180,23 @@ class Notification { } companion object { - /** - * Build list of the notifications from invoke payload - */ - fun buildNotificationList(invoke: Invoke): List? { - val notificationArray = invoke.getArray("notifications") - if (notificationArray == null) { - invoke.reject("Must provide notifications array as notifications option") - return null - } - val resultNotifications: MutableList = - ArrayList(notificationArray.length()) - val notificationsJson: List = try { - notificationArray.toList() - } catch (e: JSONException) { - invoke.reject("Provided notification format is invalid") - return null - } - for (jsonNotification in notificationsJson) { - val notification: JSObject = try { - val identifier = jsonNotification.getLong("id") - if (identifier > Int.MAX_VALUE || identifier < Int.MIN_VALUE) { - invoke.reject("The identifier should be a Java int") - return null - } - JSObject.fromJSONObject(jsonNotification) - } catch (e: JSONException) { - invoke.reject("Invalid JSON object sent to Notification plugin", e) - return null - } - try { - val activeNotification = buildNotificationFromJSObject(notification) - resultNotifications.add(activeNotification) - } catch (e: ParseException) { - invoke.reject("Invalid date format sent to Notification plugin", e) - return null + fun fromJson(jsonNotification: JSONObject): Notification { + val notification: JSObject = try { + val identifier = jsonNotification.getLong("id") + if (identifier > Int.MAX_VALUE || identifier < Int.MIN_VALUE) { + throw Exception("The notification identifier should be a 32-bit integer") } + JSObject.fromJSONObject(jsonNotification) + } catch (e: JSONException) { + throw Exception("Invalid notification JSON object", e) } - return resultNotifications + return fromJSObject(notification) } - fun buildNotificationFromJSObject(jsonObject: JSObject): Notification { + fun fromJSObject(jsonObject: JSObject): Notification { val notification = Notification() notification.source = jsonObject.toString() - notification.id = jsonObject.getInteger("id") + notification.id = jsonObject.getInteger("id") ?: throw Exception("Missing notification identifier") notification.body = jsonObject.getString("body") notification.largeBody = jsonObject.getString("largeBody") notification.summary = jsonObject.getString("summary") diff --git a/plugins/notification/android/src/main/java/NotificationPlugin.kt b/plugins/notification/android/src/main/java/NotificationPlugin.kt index 99e04694..aa6a3531 100644 --- a/plugins/notification/android/src/main/java/NotificationPlugin.kt +++ b/plugins/notification/android/src/main/java/NotificationPlugin.kt @@ -62,25 +62,51 @@ class NotificationPlugin(private val activity: Activity): Plugin(activity) { } }*/ + @Command + fun show(invoke: Invoke) { + val notification = Notification.fromJSObject(invoke.data) + val id = manager!!.schedule(notification) + + val returnVal = JSObject().put("id", id) + invoke.resolve(returnVal) + } + @Command fun batch(invoke: Invoke) { - val localNotifications = Notification.buildNotificationList(invoke) - ?: return - val ids = manager!!.schedule(invoke, localNotifications) - if (ids != null) { - notificationStorage?.appendNotifications(localNotifications) - val result = JSObject() - val jsArray = JSArray() - for (i in 0 until ids.length()) { - try { - val notification = JSObject().put("id", ids.getInt(i)) - jsArray.put(notification) - } catch (_: Exception) { - } + val notificationArray = invoke.getArray("notifications") + if (notificationArray == null) { + invoke.reject("Missing `notifications` argument") + return + } + + val notifications: MutableList = + ArrayList(notificationArray.length()) + val notificationsInput: List = try { + notificationArray.toList() + } catch (e: JSONException) { + invoke.reject("Provided notification format is invalid") + return + } + + for (jsonNotification in notificationsInput) { + val notification = Notification.fromJson(jsonNotification) + notifications.add(notification) + } + + val ids = manager!!.schedule(notifications) + notificationStorage?.appendNotifications(notifications) + + val result = JSObject() + val jsArray = JSArray() + for (id in ids) { + try { + val notification = JSObject().put("id", id) + jsArray.put(notification) + } catch (_: Exception) { } - result.put("notifications", jsArray) - invoke.resolve(result) } + result.put("notifications", jsArray) + invoke.resolve(result) } @Command diff --git a/plugins/notification/android/src/main/java/NotificationStorage.kt b/plugins/notification/android/src/main/java/NotificationStorage.kt index 60385358..4512ee29 100644 --- a/plugins/notification/android/src/main/java/NotificationStorage.kt +++ b/plugins/notification/android/src/main/java/NotificationStorage.kt @@ -47,7 +47,7 @@ class NotificationStorage(private val context: Context) { if (jsNotification != null) { try { val notification = - Notification.buildNotificationFromJSObject(jsNotification) + Notification.fromJSObject(jsNotification) notifications.add(notification) } catch (_: ParseException) { } @@ -89,7 +89,7 @@ class NotificationStorage(private val context: Context) { fun getSavedNotification(key: String?): Notification? { val jsNotification = getSavedNotificationAsJSObject(key) ?: return null val notification = try { - Notification.buildNotificationFromJSObject(jsNotification) + Notification.fromJSObject(jsNotification) } catch (ex: ParseException) { return null } diff --git a/plugins/notification/android/src/main/java/TauriNotificationManager.kt b/plugins/notification/android/src/main/java/TauriNotificationManager.kt index b95d4151..88a4406d 100644 --- a/plugins/notification/android/src/main/java/TauriNotificationManager.kt +++ b/plugins/notification/android/src/main/java/TauriNotificationManager.kt @@ -116,27 +116,28 @@ class TauriNotificationManager( } } - fun schedule(invoke: Invoke?, notifications: List): JSONArray? { - val ids = JSONArray() - val notificationManager = NotificationManagerCompat.from( - context - ) - val notificationsEnabled = notificationManager.areNotificationsEnabled() - if (!notificationsEnabled) { - invoke?.reject("Notifications not enabled on this device") - return null - } + private fun trigger(notificationManager: NotificationManagerCompat, notification: Notification): Int { + dismissVisibleNotification(notification.id) + cancelTimerForNotification(notification.id) + buildNotification(notificationManager, notification) + + return notification.id + } + + fun schedule(notification: Notification): Int { + val notificationManager = NotificationManagerCompat.from(context) + return trigger(notificationManager, notification) + } + + fun schedule(notifications: List): List { + val ids = mutableListOf() + val notificationManager = NotificationManagerCompat.from(context) + for (notification in notifications) { - val id = notification.id - if (id == null) { - invoke?.reject("Notification missing identifier") - return null - } - dismissVisibleNotification(id) - cancelTimerForNotification(id) - buildNotification(notificationManager, notification, invoke) - ids.put(id) + val id = trigger(notificationManager, notification) + ids.add(id) } + return ids } @@ -152,12 +153,8 @@ class TauriNotificationManager( private fun buildNotification( notificationManager: NotificationManagerCompat, notification: Notification, - invoke: Invoke? ) { - var channelId = DEFAULT_NOTIFICATION_CHANNEL_ID - if (notification.channelId != null) { - channelId = notification.channelId!! - } + val channelId = notification.channelId ?: DEFAULT_NOTIFICATION_CHANNEL_ID val mBuilder = NotificationCompat.Builder( context, channelId ) @@ -213,8 +210,7 @@ class TauriNotificationManager( try { mBuilder.color = Color.parseColor(iconColor) } catch (ex: IllegalArgumentException) { - invoke?.reject("Invalid color provided. Must be a hex string (ex: #ff0000") - return + throw Exception("Invalid color provided. Must be a hex string (ex: #ff0000") } } createActionIntents(notification, mBuilder) @@ -427,9 +423,7 @@ class TauriNotificationManager( } fun areNotificationsEnabled(): Boolean { - val notificationManager = NotificationManagerCompat.from( - context - ) + val notificationManager = NotificationManagerCompat.from(context) return notificationManager.areNotificationsEnabled() } diff --git a/plugins/notification/src/lib.rs b/plugins/notification/src/lib.rs index a0429a74..228578dc 100644 --- a/plugins/notification/src/lib.rs +++ b/plugins/notification/src/lib.rs @@ -33,8 +33,8 @@ use mobile::Notification; #[derive(Debug, Default, Serialize, Deserialize)] struct NotificationData { /// Notification id. - #[serde(default)] - id: usize, + #[serde(default = "default_id")] + id: i32, /// The notification title. title: Option, /// The notification body. @@ -43,6 +43,10 @@ struct NotificationData { icon: Option, } +fn default_id() -> i32 { + rand::random() +} + /// The notification builder. #[derive(Debug)] pub struct NotificationBuilder { diff --git a/plugins/notification/src/mobile.rs b/plugins/notification/src/mobile.rs index 1379470a..287d8ceb 100644 --- a/plugins/notification/src/mobile.rs +++ b/plugins/notification/src/mobile.rs @@ -31,7 +31,8 @@ pub fn init( impl crate::NotificationBuilder { pub fn show(self) -> crate::Result<()> { self.handle - .run_mobile_plugin("show", self.data) + .run_mobile_plugin::("show", self.data) + .map(|_| ()) .map_err(Into::into) } } @@ -59,6 +60,12 @@ impl Notification { } } +#[derive(Deserialize)] +struct ShowResponse { + #[allow(dead_code)] + id: i32, +} + #[derive(Deserialize)] #[serde(rename_all = "camelCase")] struct PermissionResponse {