From b7e17741cd0e2c5b0b1a0486b4347d130d436234 Mon Sep 17 00:00:00 2001 From: Swift Kim Date: Mon, 14 Nov 2022 18:29:52 +0900 Subject: [PATCH 1/5] [tizen_notification] Bump version to 0.2.0 --- packages/tizen_notification/CHANGELOG.md | 10 + packages/tizen_notification/README.md | 4 +- .../tizen_notification/example/lib/main.dart | 20 +- .../tizen_notification/lib/src/enums.dart | 27 - .../tizen_notification/lib/src/types.dart | 197 +++-- .../lib/tizen_notification.dart | 103 +-- packages/tizen_notification/pubspec.yaml | 4 +- .../tizen/src/tizen_notification_plugin.cc | 698 ++++++++---------- 8 files changed, 492 insertions(+), 571 deletions(-) delete mode 100644 packages/tizen_notification/lib/src/enums.dart diff --git a/packages/tizen_notification/CHANGELOG.md b/packages/tizen_notification/CHANGELOG.md index cc0f2b202..7c8c635e5 100644 --- a/packages/tizen_notification/CHANGELOG.md +++ b/packages/tizen_notification/CHANGELOG.md @@ -1,3 +1,13 @@ +## 0.2.0 + +* Clean up the API. + * Rename `NotificationImage` to `NotificationIcons`. + * Rename `Property` to `NotificationProperty`. + * Rename `DisplayApplist` to `NotificationStyle`. + * Rename some members of the above classes. +* Update the documentation. +* Code refactoring and bug fixes. + ## 0.1.1 * Update the example app. diff --git a/packages/tizen_notification/README.md b/packages/tizen_notification/README.md index 745925f4d..e0c418df1 100644 --- a/packages/tizen_notification/README.md +++ b/packages/tizen_notification/README.md @@ -6,11 +6,11 @@ Tizen notification APIs. Used to show and delete notifications on a Tizen device ## Usage -To use this plugin, add `tizen_notification` as a dependency in your pubspec.yaml file: +To use this plugin, add `tizen_notification` as a dependency in your `pubspec.yaml` file: ```yaml dependencies: - tizen_notification: ^0.1.1 + tizen_notification: ^0.2.0 ``` Then you can import `tizen_notification` in your Dart code: diff --git a/packages/tizen_notification/example/lib/main.dart b/packages/tizen_notification/example/lib/main.dart index c121dbe17..7a7ade91b 100644 --- a/packages/tizen_notification/example/lib/main.dart +++ b/packages/tizen_notification/example/lib/main.dart @@ -16,25 +16,26 @@ class MyApp extends StatelessWidget { final TizenNotificationPlugin _tizenNotificationPlugin = TizenNotificationPlugin(); - final int notificationId = 1; + final int _notificationId = 1; Future _showNotification() async { final TizenNotificationDetails details = TizenNotificationDetails( - image: NotificationImage(iconPath: 'test.png'), - properties: Property.disableAutoDelete | Property.disableAppLaunch, - vibration: NotificationVibration(type: VibrationType.builtIn), + icons: NotificationIcons(icon: 'test.png'), sound: NotificationSound(type: SoundType.builtIn), + vibration: NotificationVibration(type: VibrationType.builtIn), + properties: NotificationProperty.disableAutoDelete, + appControl: AppControl(appId: 'org.tizen.tizen_notification_example'), ); await _tizenNotificationPlugin.show( - notificationId, - title: 'show Notification Title', - body: 'show Notification Body', + _notificationId, + title: 'Notification title', + body: 'Notification body', notificationDetails: details, ); } Future _cancelNotification() async { - await _tizenNotificationPlugin.cancel(notificationId); + await _tizenNotificationPlugin.cancel(_notificationId); } Future _cancelAllNotifications() async { @@ -45,6 +46,7 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) { return MaterialApp( home: Scaffold( + appBar: AppBar(title: const Text('Tizen Notification Example')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -53,10 +55,12 @@ class MyApp extends StatelessWidget { onPressed: _showNotification, child: const Text('Show notification'), ), + const SizedBox(height: 10), ElevatedButton( onPressed: _cancelNotification, child: const Text('Cancel notification'), ), + const SizedBox(height: 10), ElevatedButton( onPressed: _cancelAllNotifications, child: const Text('Cancel all notifications'), diff --git a/packages/tizen_notification/lib/src/enums.dart b/packages/tizen_notification/lib/src/enums.dart deleted file mode 100644 index 328d269b6..000000000 --- a/packages/tizen_notification/lib/src/enums.dart +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2021 Samsung Electronics Co., Ltd. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/// The type of sound. -enum SoundType { - /// No sound. - none, - - /// Default sound. - builtIn, - - /// User sound data. - userData, -} - -/// The type of vibration. -enum VibrationType { - /// No vibration. - none, - - /// Default vibrate pattern. - builtIn, - - /// User vibration data. - userData, -} diff --git a/packages/tizen_notification/lib/src/types.dart b/packages/tizen_notification/lib/src/types.dart index 2e6acf212..845d5928e 100644 --- a/packages/tizen_notification/lib/src/types.dart +++ b/packages/tizen_notification/lib/src/types.dart @@ -2,102 +2,189 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// ignore_for_file: public_member_api_docs +import 'package:tizen_app_control/tizen_app_control.dart'; -import 'enums.dart'; +export 'package:tizen_app_control/tizen_app_control.dart'; -/// Properties that configure how the system handles notification at -/// certain scenarios. -class Property { - /// Display only SIM card inserted. - static const int displayOnlySimMode = 1 << 0; +/// How the system handles the notification in certain scenarios. +class NotificationProperty { + /// Display only if a SIM card is inserted. + static const int onlySimMode = 1 << 0; - /// Disable application launch when notification is selected. + /// Do not perform any operation when the notification is clicked. static const int disableAppLaunch = 1 << 1; - /// Disable auto delete when notification is selected. + /// Do not dismiss the notification when clicked. static const int disableAutoDelete = 1 << 2; - /// Delete notification when device is rebooted. - static const int volatileDisplay = 1 << 8; + /// Dismiss the notification when the device is rebooted. + static const int volatile = 1 << 8; } -/// The destination app that displays notification. -class DisplayApplist { - /// Notification Tray(Quickpanel). +/// Where and how the notification should be presented. +class NotificationStyle { + /// Display in the notification area of the quick panel. static const int tray = 1 << 0; - /// Ticker notification. - static const int ticker = 1 << 1; - - /// Lock screen. + /// Display in the lock screen. static const int lock = 1 << 2; - /// Indicator. - static const int indicator = 1 << 3; + /// Display in the indicator area (the top of the screen). + static const int indicator = 1 << 1 | 1 << 3; - /// All display application. + /// All of the above. static const int all = (1 << 4) - 1; } -class NotificationImage { - /// [NotificationImage] specifies image options for notifications. - NotificationImage({ - this.iconPath, - this.indicatorPath, - this.lockPath, +/// A set of icons to be shown in the notification layouts. +class NotificationIcons { + /// Creates a [NotificationIcons] with the given icon paths. + NotificationIcons({ + this.icon, + this.indicatorIcon, + this.lockIcon, }); - /// The path of icon. - final String? iconPath; + /// The path to the icon file. + final String? icon; - /// The path of indicator icon. - final String? indicatorPath; + /// The path to the indicator icon file. + final String? indicatorIcon; - /// The path of lock screen icon. - final String? lockPath; + /// The path to the lock screen icon file. + final String? lockIcon; - /// Returns [NotificationImage] member fields in a map format. - Map toMap() => { - 'icon': iconPath, - 'iconForIndicator': indicatorPath, - 'iconForLock': lockPath, + /// Converts to a map. + Map toMap() => { + 'icon': icon, + 'iconForIndicator': indicatorIcon, + 'iconForLock': lockIcon, }; } +/// The type of sound. +enum SoundType { + /// No sound. + none, + + /// Default sound. + builtIn, + + /// User sound data. + userData, +} + +/// The sound to play when the notification is presented. class NotificationSound { - /// [NotificationSound] specifies sound options for notifications. - /// - /// [path] refers to a file path to custom sound data played on notification, - /// this value is ignored When [type] is not [SoundType.userData]. - NotificationSound({ - required this.type, - this.path, - }); + /// Creates a [NotificationSound] with the given [type] and [path]. + NotificationSound({required this.type, this.path}); + /// The type of sound. final SoundType type; + + /// The path to the user sound data file. + /// + /// Only applicable if the [type] is [SoundType.userData]. String? path; - /// Returns [NotificationSound] member fields in a map format. - Map toMap() => { + /// Converts to a map. + Map toMap() => { 'type': type.name, 'path': path, }; } +/// The type of vibration. +enum VibrationType { + /// No vibration. + none, + + /// Default vibration pattern. + builtIn, + + /// User vibration data. + userData, +} + +/// The notification vibration options. class NotificationVibration { - /// [NotificationVibration] specifies vibration options for notifications. - NotificationVibration({ - required this.type, - this.path, - }); + /// Creates a [NotificationVibration] with the given [type] and [path]. + NotificationVibration({required this.type, this.path}); + /// The type of vibration. final VibrationType type; + + /// The path to the user vibration data file. + /// + /// Only applicable if the [type] is [VibrationType.userData]. String? path; - /// Returns [NotificationVibration] member fields in a map format. - Map toMap() => { + /// Converts to a map. + Map toMap() => { 'type': type.name, 'path': path, }; } + +/// The notification details. +class TizenNotificationDetails { + /// Constructs a [TizenNotificationDetails] from the given properties. + const TizenNotificationDetails({ + this.icons, + this.sound, + this.vibration, + this.properties = 0, + this.style = NotificationStyle.all, + this.ongoing = false, + this.appControl, + }); + + /// A set of icons to be shown in the notification layouts. + final NotificationIcons? icons; + + /// The sound to play when the notification is presented. + final NotificationSound? sound; + + /// The notification vibration options. + final NotificationVibration? vibration; + + /// Specifies how the system handles the notification in certain scenarios. + /// + /// Multiple [NotificationProperty] values can be set using the bitwise OR + /// operator (|). + final int properties; + + /// Specifies where and how the notification should be presented. + /// + /// Multiple [NotificationStyle] values can be set using the bitwise OR + /// operator (|). + final int style; + + /// Whether the notification can be dismissed by user. + /// + /// Only supported on Raspberry Pi (common profile) devices. + final bool ongoing; + + /// A control message to be sent when the notification is clicked. + final AppControl? appControl; + + /// Converts to a map. + Map toMap() => { + 'image': icons?.toMap(), + 'sound': sound?.toMap(), + 'vibration': vibration?.toMap(), + 'properties': appControl != null + ? properties + : properties | NotificationProperty.disableAppLaunch, + 'displayApplist': style, + 'ongoing': ongoing, + if (appControl != null) + 'appControl': { + 'appId': appControl!.appId, + 'operation': appControl!.operation, + 'uri': appControl!.uri, + 'mime': appControl!.mime, + 'extraData': appControl!.extraData, + }, + }; +} diff --git a/packages/tizen_notification/lib/tizen_notification.dart b/packages/tizen_notification/lib/tizen_notification.dart index 6e1341437..e1c8bd4bf 100644 --- a/packages/tizen_notification/lib/tizen_notification.dart +++ b/packages/tizen_notification/lib/tizen_notification.dart @@ -3,103 +3,36 @@ // found in the LICENSE file. import 'package:flutter/services.dart'; -import 'package:tizen_app_control/tizen_app_control.dart'; import 'src/types.dart'; -export 'package:tizen_app_control/tizen_app_control.dart'; - -export 'src/enums.dart'; export 'src/types.dart'; -/// Contains detailed information about a notification being sent. -class TizenNotificationDetails { - /// Constructs a [TizenNotificationDetails] from the given properties. - /// - /// The properties are all optional. - const TizenNotificationDetails({ - this.image, - this.appControl, - this.vibration, - this.sound, - this.properties = 0, - this.displayApplist = DisplayApplist.all, - this.ongoing = false, - }); - - /// [NotificationImage] refers to any image shown on the notification panel. - final NotificationImage? image; - - /// A set of information used by app control to launch other applications. - final AppControl? appControl; - - /// The vibration triggered when a notification is received. - final NotificationVibration? vibration; - - /// The sound played when a notification is received. - final NotificationSound? sound; - - /// Properties that configure how the system handles notification at - /// certain scenarios. - /// - /// [properties] can have multiple [Property] values with the bitwise OR operator. - /// For example, [Property.disableAppLaunch] | [Property.volatileDisplay]. - final int properties; - - /// The destination app that displays notification. - /// - /// The notification can be sent to multiple apps by listing values with the - /// bitwise OR operator. - /// For example, [DisplayApplist.tray] | [DisplayApplist.indicator]. - final int displayApplist; - - /// If [ongoing] is true, the user is not able to delete the notification. - /// - /// Currently, only the common profile supports this operation. - final bool ongoing; - - /// Returns [TizenNotificationDetails] member fields in a map format. - Map toMap() => { - 'displayApplist': displayApplist, - 'properties': properties, - 'vibration': vibration?.toMap(), - 'sound': sound?.toMap(), - 'image': image?.toMap(), - 'ongoing': ongoing, - 'appControl': { - 'appId': appControl?.appId, - 'operation': appControl?.operation, - 'uri': appControl?.uri, - 'mime': appControl?.mime, - 'extraData': appControl?.extraData, - }, - }; -} - -const MethodChannel _channel = MethodChannel('tizen/notification'); - -/// A handle for sending notifications to Tizen. +/// Provides functionality for displaying notifications. class TizenNotificationPlugin { - /// Removes a notification with [id]. - Future cancel(int id) => _channel.invokeMethod('cancel', id.toString()); - - /// Removes all notifications sent. - Future cancelAll() => _channel.invokeMethod('cancelAll'); + final MethodChannel _channel = const MethodChannel('tizen/notification'); - /// Sends the notification with [id], [title], and [body]. [id] is the identifier - /// of the notification which can later be passed to [cancel] to erase the - /// notification. + /// Displays a notification with the given properties. + /// + /// [id] is the identifier of the notification which can later be used to + /// remove the notification. Future show( int id, { - String? title, - String? body, + String title = '', + String body = '', TizenNotificationDetails? notificationDetails, }) { - final Map details = - notificationDetails?.toMap() ?? {}; + final Map details = + notificationDetails?.toMap() ?? {}; details['id'] = id.toString(); - details['title'] = title ?? ''; - details['body'] = body ?? ''; + details['title'] = title; + details['body'] = body; return _channel.invokeMethod('show', details); } + + /// Removes a notification with the specified [id]. + Future cancel(int id) => _channel.invokeMethod('cancel', id.toString()); + + /// Removes all notifications. + Future cancelAll() => _channel.invokeMethod('cancelAll'); } diff --git a/packages/tizen_notification/pubspec.yaml b/packages/tizen_notification/pubspec.yaml index 3d00f7121..81fda8007 100644 --- a/packages/tizen_notification/pubspec.yaml +++ b/packages/tizen_notification/pubspec.yaml @@ -2,7 +2,7 @@ name: tizen_notification description: Tizen notification APIs. Used to show and delete notifications on a Tizen device. homepage: https://github.com/flutter-tizen/plugins repository: https://github.com/flutter-tizen/plugins/tree/master/packages/tizen_notification -version: 0.1.1 +version: 0.2.0 environment: sdk: ">=2.12.0 <3.0.0" @@ -11,7 +11,7 @@ environment: dependencies: flutter: sdk: flutter - tizen_app_control: ^0.2.0 + tizen_app_control: ^0.2.2 flutter: plugin: diff --git a/packages/tizen_notification/tizen/src/tizen_notification_plugin.cc b/packages/tizen_notification/tizen/src/tizen_notification_plugin.cc index 3f47df422..b2d32d0b6 100644 --- a/packages/tizen_notification/tizen/src/tizen_notification_plugin.cc +++ b/packages/tizen_notification/tizen/src/tizen_notification_plugin.cc @@ -11,8 +11,11 @@ #include #include +#include #include #include +#include +#include #include "log.h" @@ -40,478 +43,389 @@ class TizenNotificationPlugin : public flutter::Plugin { private: template - bool GetValueFromArgs(const flutter::EncodableValue *args, const char *key, - T &out) { - if (std::holds_alternative(*args)) { - flutter::EncodableMap map = std::get(*args); - if (map.find(flutter::EncodableValue(key)) != map.end()) { - flutter::EncodableValue value = map[flutter::EncodableValue(key)]; - if (std::holds_alternative(value)) { - out = std::get(value); - return true; - } - } - } - return false; - } - - bool GetEncodableValueFromArgs(const flutter::EncodableValue *args, - const char *key, - flutter::EncodableValue &out) { - if (std::holds_alternative(*args)) { - flutter::EncodableMap map = std::get(*args); - if (map.find(flutter::EncodableValue(key)) != map.end()) { - out = map[flutter::EncodableValue(key)]; + static bool GetValueFromEncodableMap(const flutter::EncodableMap *map, + const char *key, T &out) { + auto iter = map->find(flutter::EncodableValue(key)); + if (iter != map->end() && !iter->second.IsNull()) { + if (auto *value = std::get_if(&iter->second)) { + out = *value; return true; } } return false; } - void FreeNotification(notification_h ¬i) { - int ret = notification_free(noti); + void FreeNotification(notification_h handle) { + int ret = notification_free(handle); if (ret != NOTIFICATION_ERROR_NONE) { - LOG_ERROR("notification_free failed : %s", get_error_message(ret)); + LOG_ERROR("notification_free failed: %s", get_error_message(ret)); } } - void DestroyAppControl(app_control_h &app_control) { + void DestroyAppControl(app_control_h app_control) { int ret = app_control_destroy(app_control); if (ret != APP_CONTROL_ERROR_NONE) { - LOG_ERROR("app_control_destroy failed : %s", get_error_message(ret)); + LOG_ERROR("app_control_destroy failed: %s", get_error_message(ret)); } } - notification_sound_type_e StringToSoundType(std::string sound_str) { - notification_sound_type_e ret = NOTIFICATION_SOUND_TYPE_NONE; - if (sound_str.compare("none") == 0) { - ret = NOTIFICATION_SOUND_TYPE_NONE; - } else if (sound_str.compare("builtIn") == 0) { - ret = NOTIFICATION_SOUND_TYPE_DEFAULT; - } else if (sound_str.compare("userData") == 0) { - ret = NOTIFICATION_SOUND_TYPE_USER_DATA; + notification_image_type_e StringToImageType(const std::string &type) { + if (type == "icon") { + return NOTIFICATION_IMAGE_TYPE_ICON; + } else if (type == "iconForIndicator") { + return NOTIFICATION_IMAGE_TYPE_ICON_FOR_INDICATOR; + } else if (type == "iconForLock") { + return NOTIFICATION_IMAGE_TYPE_ICON_FOR_LOCK; } - return ret; + return NOTIFICATION_IMAGE_TYPE_ICON; } - notification_vibration_type_e StringToVibrationType( - std::string vibration_str) { - notification_vibration_type_e ret = NOTIFICATION_VIBRATION_TYPE_NONE; - if (vibration_str.compare("none") == 0) { - ret = NOTIFICATION_VIBRATION_TYPE_NONE; - } else if (vibration_str.compare("builtIn") == 0) { - ret = NOTIFICATION_VIBRATION_TYPE_DEFAULT; - } else if (vibration_str.compare("userData") == 0) { - ret = NOTIFICATION_VIBRATION_TYPE_USER_DATA; + notification_sound_type_e StringToSoundType(const std::string &type) { + if (type == "none") { + return NOTIFICATION_SOUND_TYPE_NONE; + } else if (type == "builtIn") { + return NOTIFICATION_SOUND_TYPE_DEFAULT; + } else if (type == "userData") { + return NOTIFICATION_SOUND_TYPE_USER_DATA; } - return ret; + return NOTIFICATION_SOUND_TYPE_NONE; } - notification_image_type_e StringToImageType(std::string image_type) { - notification_image_type_e ret = NOTIFICATION_IMAGE_TYPE_ICON; - if (image_type.compare("icon") == 0) { - ret = NOTIFICATION_IMAGE_TYPE_ICON; - } else if (image_type.compare("iconForIndicator") == 0) { - ret = NOTIFICATION_IMAGE_TYPE_ICON_FOR_INDICATOR; - } else if (image_type.compare("iconForLock") == 0) { - ret = NOTIFICATION_IMAGE_TYPE_ICON_FOR_LOCK; + notification_vibration_type_e StringToVibrationType(const std::string &type) { + if (type == "none") { + return NOTIFICATION_VIBRATION_TYPE_NONE; + } else if (type == "builtIn") { + return NOTIFICATION_VIBRATION_TYPE_DEFAULT; + } else if (type == "userData") { + return NOTIFICATION_VIBRATION_TYPE_USER_DATA; } - return ret; + return NOTIFICATION_VIBRATION_TYPE_NONE; + } + + std::string ToAbsolutePath(const std::string &path) { + std::filesystem::path filesystem_path(path); + if (filesystem_path.is_absolute()) { + return path; + } + char *res_path = app_get_shared_resource_path(); + std::string result = std::string(res_path) + path; + free(res_path); + return result; } void HandleMethodCall( const flutter::MethodCall &method_call, std::unique_ptr> result) { - if (method_call.method_name().compare("show") == 0) { - if (method_call.arguments()) { - const flutter::EncodableValue *arguments = method_call.arguments(); - notification_h noti_handle = nullptr; - app_control_h app_control = nullptr; + const auto &method_name = method_call.method_name(); - int ret = NOTIFICATION_ERROR_NONE; - std::string id; - std::string title; - std::string body; - flutter::EncodableValue app_control_data; - - if (GetValueFromArgs(arguments, "id", id)) { - noti_handle = notification_load_by_tag(id.c_str()); - if (noti_handle) { - ret = notification_delete(noti_handle); - if (ret != NOTIFICATION_ERROR_NONE) { - LOG_ERROR("notification_delete failed : %s", - get_error_message(ret)); - result->Error("notification_delete failed", - std::string(get_error_message(ret))); - return; - } - } + if (method_name == "show") { + const auto *arguments = + std::get_if(method_call.arguments()); + if (!arguments) { + result->Error("Invalid argument", "The argument must be a map."); + } - bool ongoing; - if (GetValueFromArgs(arguments, "ongoing", ongoing)) { - if (ongoing) { - noti_handle = notification_create(NOTIFICATION_TYPE_ONGOING); - if (!noti_handle) { - LOG_ERROR( - "notification_create failed : Fail to create notification"); - result->Error("notification_create failed", - "Fail to create notification"); - return; - } - ret = notification_set_layout(noti_handle, - NOTIFICATION_LY_ONGOING_EVENT); - if (ret != NOTIFICATION_ERROR_NONE) { - FreeNotification(noti_handle); - LOG_ERROR("notification_set_layout failed : %s", - get_error_message(ret)); - result->Error("notification_set_layout failed", - std::string(get_error_message(ret))); - return; - } - } else { - noti_handle = notification_create(NOTIFICATION_TYPE_NOTI); - if (!noti_handle) { - LOG_ERROR( - "notification_create failed : Fail to create notification"); - result->Error("notification_create failed", - "Fail to create notification"); - return; - } - } - } - ret = notification_set_tag(noti_handle, id.c_str()); - if (ret != NOTIFICATION_ERROR_NONE) { - FreeNotification(noti_handle); - LOG_ERROR("notification_set_tag failed : %s", - get_error_message(ret)); - result->Error("notification_set_tag failed", - std::string(get_error_message(ret))); - return; - } - } + std::string id; + if (!GetValueFromEncodableMap(arguments, "id", id)) { + result->Error("Invalid argument", "No id provided."); + return; + } - if (GetValueFromArgs(arguments, "title", title)) { - ret = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_TITLE, - title.c_str(), nullptr, - NOTIFICATION_VARIABLE_TYPE_NONE); - if (ret != NOTIFICATION_ERROR_NONE) { - FreeNotification(noti_handle); - LOG_ERROR("notification_set_text failed : %s", - get_error_message(ret)); - result->Error("notification_set_text failed", - std::string(get_error_message(ret))); - return; - } + notification_h handle = notification_load_by_tag(id.c_str()); + if (handle) { + // The notification with the ID already exists. Delete it. + int ret = notification_delete(handle); + if (ret != NOTIFICATION_ERROR_NONE) { + result->Error("notification_delete failed", get_error_message(ret)); + return; } + } - if (GetValueFromArgs(arguments, "body", body)) { - ret = notification_set_text( - noti_handle, NOTIFICATION_TEXT_TYPE_CONTENT, body.c_str(), - nullptr, NOTIFICATION_VARIABLE_TYPE_NONE); - if (ret != NOTIFICATION_ERROR_NONE) { - FreeNotification(noti_handle); - LOG_ERROR("notification_set_text failed : %s", - get_error_message(ret)); - result->Error("notification_set_text failed", - std::string(get_error_message(ret))); - return; - } + bool ongoing = false; + GetValueFromEncodableMap(arguments, "ongoing", ongoing); + if (ongoing) { + handle = notification_create(NOTIFICATION_TYPE_ONGOING); + if (!handle) { + result->Error("notification_create failed", + "Failed to create an ongoing notification."); + return; } - - flutter::EncodableMap images; - if (GetValueFromArgs(arguments, "image", images)) { - for (const auto &image : images) { - std::string type; - std::string path; - char *resource_path = app_get_shared_resource_path(); - if (std::holds_alternative(image.first)) { - type = std::get(image.first); - } - if (std::holds_alternative(image.second)) { - path = std::get(image.second); - path = std::string(resource_path) + path; - } - ret = notification_set_image(noti_handle, StringToImageType(type), - path.c_str()); - free(resource_path); - if (ret != NOTIFICATION_ERROR_NONE) { - FreeNotification(noti_handle); - LOG_ERROR("notification_set_image failed : %s", + int ret = + notification_set_layout(handle, NOTIFICATION_LY_ONGOING_EVENT); + if (ret != NOTIFICATION_ERROR_NONE) { + FreeNotification(handle); + result->Error("notification_set_layout failed", get_error_message(ret)); - result->Error("notification_set_image failed", - std::string(get_error_message(ret))); - return; - } - } + return; } + } else { + handle = notification_create(NOTIFICATION_TYPE_NOTI); + if (!handle) { + result->Error("notification_create failed", + "Failed to create a notification."); + return; + } + } - int32_t display_applist; - if (GetValueFromArgs(arguments, "displayApplist", display_applist)) { - ret = notification_set_display_applist(noti_handle, display_applist); - if (ret != NOTIFICATION_ERROR_NONE) { - FreeNotification(noti_handle); - LOG_ERROR("notification_set_display_applist failed : %s", - get_error_message(ret)); - result->Error("notification_set_display_applist failed", - std::string(get_error_message(ret))); - return; - } + int ret = notification_set_tag(handle, id.c_str()); + if (ret != NOTIFICATION_ERROR_NONE) { + FreeNotification(handle); + result->Error("notification_set_tag failed", get_error_message(ret)); + return; + } + + std::string title; + if (GetValueFromEncodableMap(arguments, "title", title)) { + ret = notification_set_text(handle, NOTIFICATION_TEXT_TYPE_TITLE, + title.c_str(), nullptr, + NOTIFICATION_VARIABLE_TYPE_NONE); + if (ret != NOTIFICATION_ERROR_NONE) { + FreeNotification(handle); + result->Error("notification_set_text failed", get_error_message(ret)); + return; + } + } + + std::string body; + if (GetValueFromEncodableMap(arguments, "body", body)) { + ret = notification_set_text(handle, NOTIFICATION_TEXT_TYPE_CONTENT, + body.c_str(), nullptr, + NOTIFICATION_VARIABLE_TYPE_NONE); + if (ret != NOTIFICATION_ERROR_NONE) { + FreeNotification(handle); + result->Error("notification_set_text failed", get_error_message(ret)); + return; } + } - int32_t properties; - if (GetValueFromArgs(arguments, "properties", properties)) { - ret = notification_set_property(noti_handle, properties); + flutter::EncodableMap images; + if (GetValueFromEncodableMap(arguments, "image", images)) { + for (const auto &image : images) { + std::string type; + if (std::holds_alternative(image.first)) { + type = std::get(image.first); + } + std::string path; + if (std::holds_alternative(image.second)) { + path = ToAbsolutePath(std::get(image.second)); + } + ret = notification_set_image(handle, StringToImageType(type), + path.c_str()); if (ret != NOTIFICATION_ERROR_NONE) { - FreeNotification(noti_handle); - LOG_ERROR("notification_set_property failed : %s", - get_error_message(ret)); - result->Error("notification_set_property failed", - std::string(get_error_message(ret))); + FreeNotification(handle); + result->Error("notification_set_image failed", + get_error_message(ret)); return; } } + } - flutter::EncodableValue sound; - if (GetEncodableValueFromArgs(arguments, "sound", sound)) { - std::string type; - if (GetValueFromArgs(&sound, "type", type)) { - std::string path; - char *resource_path = app_get_shared_resource_path(); - if (GetValueFromArgs(&sound, "path", path)) { - path = std::string(resource_path) + path; - } - ret = notification_set_sound(noti_handle, StringToSoundType(type), - path.c_str()); - free(resource_path); - if (ret != NOTIFICATION_ERROR_NONE) { - FreeNotification(noti_handle); - LOG_ERROR("notification_set_sound failed : %s", + int32_t display_applist = 0; + if (GetValueFromEncodableMap(arguments, "displayApplist", + display_applist)) { + ret = notification_set_display_applist(handle, display_applist); + if (ret != NOTIFICATION_ERROR_NONE) { + FreeNotification(handle); + result->Error("notification_set_display_applist failed", get_error_message(ret)); - result->Error("notification_set_sound failed", - std::string(get_error_message(ret))); - return; - } - } + return; } + } - flutter::EncodableValue vibration; - if (GetEncodableValueFromArgs(arguments, "vibration", vibration)) { - std::string type; - if (GetValueFromArgs(&vibration, "type", type)) { - std::string path; - char *resource_path = app_get_shared_resource_path(); - if (GetValueFromArgs(&vibration, "path", path)) { - path = std::string(resource_path) + path; - } - ret = notification_set_vibration( - noti_handle, StringToVibrationType(type), path.c_str()); - free(resource_path); - if (ret != NOTIFICATION_ERROR_NONE) { - FreeNotification(noti_handle); - LOG_ERROR("notification_set_vibration failed : %s", + int32_t properties = 0; + if (GetValueFromEncodableMap(arguments, "properties", properties)) { + ret = notification_set_property(handle, properties); + if (ret != NOTIFICATION_ERROR_NONE) { + FreeNotification(handle); + result->Error("notification_set_property failed", get_error_message(ret)); - result->Error("notification_set_vibration failed", - std::string(get_error_message(ret))); - return; - } - } + return; } + } - if (GetEncodableValueFromArgs(arguments, "appControl", - app_control_data)) { - std::string app_id; - if (GetValueFromArgs(&app_control_data, "appId", app_id)) { - std::string operation; - std::string uri; - std::string category; - std::string mime; - flutter::EncodableMap extras; - flutter::EncodableValue extra_value; - std::string key; - ret = app_control_create(&app_control); - if (ret != APP_CONTROL_ERROR_NONE) { - FreeNotification(noti_handle); - LOG_ERROR("app_control_create failed : %s", + flutter::EncodableMap sound; + if (GetValueFromEncodableMap(arguments, "sound", sound)) { + std::string type; + GetValueFromEncodableMap(&sound, "type", type); + std::string path; + if (GetValueFromEncodableMap(&sound, "path", path)) { + path = ToAbsolutePath(path); + } + ret = notification_set_sound(handle, StringToSoundType(type), + path.c_str()); + if (ret != NOTIFICATION_ERROR_NONE) { + FreeNotification(handle); + result->Error("notification_set_sound failed", get_error_message(ret)); - result->Error("app_control_create failed", - std::string(get_error_message(ret))); - return; - } + return; + } + } - ret = app_control_set_app_id(app_control, app_id.c_str()); - if (ret != APP_CONTROL_ERROR_NONE) { - DestroyAppControl(app_control); - FreeNotification(noti_handle); - LOG_ERROR("app_control_set_app_id failed : %s", + flutter::EncodableMap vibration; + if (GetValueFromEncodableMap(arguments, "vibration", vibration)) { + std::string type; + GetValueFromEncodableMap(&vibration, "type", type); + std::string path; + if (GetValueFromEncodableMap(&vibration, "path", path)) { + path = ToAbsolutePath(path); + } + ret = notification_set_vibration(handle, StringToVibrationType(type), + path.c_str()); + if (ret != NOTIFICATION_ERROR_NONE) { + FreeNotification(handle); + result->Error("notification_set_vibration failed", get_error_message(ret)); - result->Error("app_control_set_app_id failed", - std::string(get_error_message(ret))); - return; - } + return; + } + } - if (GetValueFromArgs(&app_control_data, "operation", operation)) { - ret = app_control_set_operation(app_control, operation.c_str()); - if (ret != APP_CONTROL_ERROR_NONE) { - DestroyAppControl(app_control); - FreeNotification(noti_handle); - LOG_ERROR("app_control_set_operation failed : %s", - get_error_message(ret)); - result->Error("app_control_set_operation failed", - std::string(get_error_message(ret))); - return; - } - } + flutter::EncodableMap app_control_data; + if (GetValueFromEncodableMap(arguments, "appControl", app_control_data)) { + app_control_h app_control = nullptr; + ret = app_control_create(&app_control); + if (ret != APP_CONTROL_ERROR_NONE) { + FreeNotification(handle); + result->Error("app_control_create failed", get_error_message(ret)); + return; + } - if (GetValueFromArgs(&app_control_data, "uri", uri)) { - ret = app_control_set_uri(app_control, uri.c_str()); - if (ret != APP_CONTROL_ERROR_NONE) { - DestroyAppControl(app_control); - FreeNotification(noti_handle); - LOG_ERROR("app_control_set_uri failed : %s", + std::string app_id; + if (GetValueFromEncodableMap(&app_control_data, "appId", app_id)) { + ret = app_control_set_app_id(app_control, app_id.c_str()); + if (ret != APP_CONTROL_ERROR_NONE) { + DestroyAppControl(app_control); + FreeNotification(handle); + result->Error("app_control_set_app_id failed", get_error_message(ret)); - result->Error("app_control_set_uri failed", - std::string(get_error_message(ret))); - return; - } - } + return; + } + } - if (GetValueFromArgs(&app_control_data, "category", category)) { - ret = app_control_set_category(app_control, category.c_str()); - if (ret != APP_CONTROL_ERROR_NONE) { - DestroyAppControl(app_control); - FreeNotification(noti_handle); - LOG_ERROR("app_control_set_category failed : %s", + std::string operation; + if (GetValueFromEncodableMap(&app_control_data, "operation", + operation)) { + ret = app_control_set_operation(app_control, operation.c_str()); + if (ret != APP_CONTROL_ERROR_NONE) { + DestroyAppControl(app_control); + FreeNotification(handle); + result->Error("app_control_set_operation failed", get_error_message(ret)); - result->Error("app_control_set_category failed", - std::string(get_error_message(ret))); - return; - } - } + return; + } + } - if (GetValueFromArgs(&app_control_data, "mime", mime)) { - ret = app_control_set_mime(app_control, mime.c_str()); - if (ret != APP_CONTROL_ERROR_NONE) { - DestroyAppControl(app_control); - FreeNotification(noti_handle); - LOG_ERROR("app_control_set_mime failed : %s", - get_error_message(ret)); - result->Error("app_control_set_mime failed", - std::string(get_error_message(ret))); - return; - } - } + std::string uri; + if (GetValueFromEncodableMap(&app_control_data, "uri", uri)) { + ret = app_control_set_uri(app_control, uri.c_str()); + if (ret != APP_CONTROL_ERROR_NONE) { + DestroyAppControl(app_control); + FreeNotification(handle); + result->Error("app_control_set_uri failed", get_error_message(ret)); + return; + } + } - if (GetValueFromArgs(&app_control_data, "extraData", extras)) { - extra_value = extras; - for (const auto &extra : extras) { - std::string map_key; - if (std::holds_alternative(extra.first)) { - map_key = std::get(extra.first); - flutter::EncodableList value_list; - std::vector values; - std::vector dummy; - std::string value; - if (GetValueFromArgs(&extra_value, map_key.c_str(), - value_list)) { - for (size_t i = 0; i < value_list.size(); i++) { - dummy.push_back(std::get(value_list[i])); - } - for (size_t i = 0; i < value_list.size(); i++) { - values.push_back(dummy[i].c_str()); - } - app_control_add_extra_data_array( - app_control, map_key.c_str(), values.data(), - values.size()); - } else if (GetValueFromArgs(&extra_value, map_key.c_str(), - value)) { - app_control_add_extra_data(app_control, map_key.c_str(), - value.c_str()); - } - } - } - ret = notification_set_launch_option( - noti_handle, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL, - (void *)app_control); - if (ret != NOTIFICATION_ERROR_NONE) { - FreeNotification(noti_handle); - DestroyAppControl(app_control); - LOG_ERROR("notification_set_launch_option failed : %s", + std::string category; + if (GetValueFromEncodableMap(&app_control_data, "category", category)) { + ret = app_control_set_category(app_control, category.c_str()); + if (ret != APP_CONTROL_ERROR_NONE) { + DestroyAppControl(app_control); + FreeNotification(handle); + result->Error("app_control_set_category failed", get_error_message(ret)); - result->Error("notification_set_launch_option failed", - std::string(get_error_message(ret))); - return; - } - } + return; } } - if (app_control) { - ret = app_control_destroy(app_control); + std::string mime; + if (GetValueFromEncodableMap(&app_control_data, "mime", mime)) { + ret = app_control_set_mime(app_control, mime.c_str()); if (ret != APP_CONTROL_ERROR_NONE) { - FreeNotification(noti_handle); - LOG_ERROR("app_control_destroy failed : %s", - get_error_message(ret)); - result->Error("app_control_destroy failed", - std::string(get_error_message(ret))); + DestroyAppControl(app_control); + FreeNotification(handle); + result->Error("app_control_set_mime failed", + get_error_message(ret)); return; } } - ret = notification_post(noti_handle); - if (ret != NOTIFICATION_ERROR_NONE) { - FreeNotification(noti_handle); - LOG_ERROR("notification_post failed : %s", get_error_message(ret)); - result->Error("notification_post failed", - std::string(get_error_message(ret))); - return; + + flutter::EncodableMap extras; + if (GetValueFromEncodableMap(&app_control_data, "extraData", extras)) { + for (const auto &extra : extras) { + if (std::holds_alternative(extra.first)) { + const std::string &key = std::get(extra.first); + flutter::EncodableList value_list; + std::string value; + if (GetValueFromEncodableMap(&extras, key.c_str(), value_list)) { + std::vector dummy; + for (const flutter::EncodableValue &value : value_list) { + dummy.push_back(std::get(value)); + } + std::vector values; + for (const std::string &value : dummy) { + values.push_back(value.c_str()); + } + app_control_add_extra_data_array(app_control, key.c_str(), + values.data(), values.size()); + } else if (GetValueFromEncodableMap(&extras, key.c_str(), + value)) { + app_control_add_extra_data(app_control, key.c_str(), + value.c_str()); + } + } + } } - ret = notification_free(noti_handle); + + ret = notification_set_launch_option( + handle, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL, app_control); if (ret != NOTIFICATION_ERROR_NONE) { - LOG_ERROR("notification_free failed : %s", get_error_message(ret)); - result->Error("notification_free failed", - std::string(get_error_message(ret))); + FreeNotification(handle); + DestroyAppControl(app_control); + result->Error("notification_set_launch_option failed", + get_error_message(ret)); return; } - result->Success(); + DestroyAppControl(app_control); + } + + ret = notification_post(handle); + if (ret != NOTIFICATION_ERROR_NONE) { + FreeNotification(handle); + result->Error("notification_post failed", get_error_message(ret)); return; } - result->Error("InvalidArguments", "Please check 'show'"); - } else if (method_call.method_name().compare("cancel") == 0) { - const flutter::EncodableValue *arguments = method_call.arguments(); - if (arguments != nullptr && - std::holds_alternative(*arguments)) { - std::string id = std::get(*arguments); - notification_h noti_handle = nullptr; - noti_handle = notification_load_by_tag(id.c_str()); - if (noti_handle != nullptr) { - int ret = notification_delete(noti_handle); - if (ret != NOTIFICATION_ERROR_NONE) { - LOG_ERROR("notification_delete failed : %s", - get_error_message(ret)); - result->Error("notification_delete failed", - std::string(get_error_message(ret))); - return; - } - } - result->Success(); + FreeNotification(handle); + + result->Success(); + } else if (method_name == "cancel") { + const auto *id = std::get_if(method_call.arguments()); + if (!id) { + result->Error("Invalid argument", "The argument must be a string."); + } + + notification_h handle = notification_load_by_tag(id->c_str()); + if (!handle) { + result->Error("Invalid argument", + "No notification found with the given ID."); return; } - result->Error("InvalidArguments", "Please check 'cancel'"); - } else if (method_call.method_name().compare("cancelAll") == 0) { - int ret = NOTIFICATION_ERROR_NONE; - ret = notification_delete_all(NOTIFICATION_TYPE_NOTI); + + int ret = notification_delete(handle); if (ret != NOTIFICATION_ERROR_NONE) { - LOG_ERROR("notification_delete_all failed : %s", - get_error_message(ret)); - result->Error("notification_delete_all failed", - std::string(get_error_message(ret))); + result->Error(std::to_string(ret), get_error_message(ret)); return; } + result->Success(); + } else if (method_name == "cancelAll") { + int ret = notification_delete_all(NOTIFICATION_TYPE_NOTI); + if (ret != NOTIFICATION_ERROR_NONE) { + result->Error(std::to_string(ret), get_error_message(ret)); + return; + } + ret = notification_delete_all(NOTIFICATION_TYPE_ONGOING); if (ret != NOTIFICATION_ERROR_NONE) { - LOG_ERROR("notification_delete_all failed : %s", - get_error_message(ret)); - result->Error("notification_delete_all failed", - std::string(get_error_message(ret))); + result->Error(std::to_string(ret), get_error_message(ret)); return; } result->Success(); From 2b71f1da9cf4a26baf9b5e7c59b919a4baae510d Mon Sep 17 00:00:00 2001 From: Swift Kim Date: Fri, 18 Nov 2022 16:52:25 +0900 Subject: [PATCH 2/5] Enclose with a namespace --- .../tizen/src/tizen_notification_plugin.cc | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/packages/tizen_notification/tizen/src/tizen_notification_plugin.cc b/packages/tizen_notification/tizen/src/tizen_notification_plugin.cc index b2d32d0b6..fcaab0150 100644 --- a/packages/tizen_notification/tizen/src/tizen_notification_plugin.cc +++ b/packages/tizen_notification/tizen/src/tizen_notification_plugin.cc @@ -19,6 +19,21 @@ #include "log.h" +namespace { + +template +static bool GetValueFromEncodableMap(const flutter::EncodableMap *map, + const char *key, T &out) { + auto iter = map->find(flutter::EncodableValue(key)); + if (iter != map->end() && !iter->second.IsNull()) { + if (auto *value = std::get_if(&iter->second)) { + out = *value; + return true; + } + } + return false; +} + class TizenNotificationPlugin : public flutter::Plugin { public: static void RegisterWithRegistrar(flutter::PluginRegistrar *registrar) { @@ -42,19 +57,6 @@ class TizenNotificationPlugin : public flutter::Plugin { virtual ~TizenNotificationPlugin() {} private: - template - static bool GetValueFromEncodableMap(const flutter::EncodableMap *map, - const char *key, T &out) { - auto iter = map->find(flutter::EncodableValue(key)); - if (iter != map->end() && !iter->second.IsNull()) { - if (auto *value = std::get_if(&iter->second)) { - out = *value; - return true; - } - } - return false; - } - void FreeNotification(notification_h handle) { int ret = notification_free(handle); if (ret != NOTIFICATION_ERROR_NONE) { @@ -435,6 +437,8 @@ class TizenNotificationPlugin : public flutter::Plugin { } }; +} // namespace + void TizenNotificationPluginRegisterWithRegistrar( FlutterDesktopPluginRegistrarRef registrar) { TizenNotificationPlugin::RegisterWithRegistrar( From 0d30a0115f44d2a9b41956dc0122154d76e4fdee Mon Sep 17 00:00:00 2001 From: Swift Kim Date: Fri, 18 Nov 2022 17:27:16 +0900 Subject: [PATCH 3/5] Do not use the bitwise shift operator for constants --- .../tizen_notification/lib/src/types.dart | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/packages/tizen_notification/lib/src/types.dart b/packages/tizen_notification/lib/src/types.dart index 845d5928e..508231632 100644 --- a/packages/tizen_notification/lib/src/types.dart +++ b/packages/tizen_notification/lib/src/types.dart @@ -8,32 +8,40 @@ export 'package:tizen_app_control/tizen_app_control.dart'; /// How the system handles the notification in certain scenarios. class NotificationProperty { + // The constants below are originally defined in notification_type.h as + // the enum type _notification_property. + NotificationProperty._(); + /// Display only if a SIM card is inserted. - static const int onlySimMode = 1 << 0; + static const int onlySimMode = 0x00000001; /// Do not perform any operation when the notification is clicked. - static const int disableAppLaunch = 1 << 1; + static const int disableAppLaunch = 0x00000002; /// Do not dismiss the notification when clicked. - static const int disableAutoDelete = 1 << 2; + static const int disableAutoDelete = 0x00000004; /// Dismiss the notification when the device is rebooted. - static const int volatile = 1 << 8; + static const int volatile = 0x00000100; } /// Where and how the notification should be presented. class NotificationStyle { + // The constants below are originally defined in notification_type.h as + // the enum type _notification_display_applist. + NotificationStyle._(); + /// Display in the notification area of the quick panel. - static const int tray = 1 << 0; + static const int tray = 0x00000001; /// Display in the lock screen. - static const int lock = 1 << 2; + static const int lock = 0x00000004; /// Display in the indicator area (the top of the screen). - static const int indicator = 1 << 1 | 1 << 3; + static const int indicator = 0x00000002 | 0x00000008; /// All of the above. - static const int all = (1 << 4) - 1; + static const int all = tray | lock | indicator; } /// A set of icons to be shown in the notification layouts. From 6743c31420092959ea8c93ab1002a2b3f9c54743 Mon Sep 17 00:00:00 2001 From: Swift Kim Date: Fri, 18 Nov 2022 17:48:56 +0900 Subject: [PATCH 4/5] Do not implicitly set disableAppLaunch in toMap() --- .../tizen_notification/lib/src/types.dart | 36 +++++++++---------- .../lib/tizen_notification.dart | 8 +++++ 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/packages/tizen_notification/lib/src/types.dart b/packages/tizen_notification/lib/src/types.dart index 508231632..ec34f90b3 100644 --- a/packages/tizen_notification/lib/src/types.dart +++ b/packages/tizen_notification/lib/src/types.dart @@ -54,16 +54,16 @@ class NotificationIcons { }); /// The path to the icon file. - final String? icon; + String? icon; /// The path to the indicator icon file. - final String? indicatorIcon; + String? indicatorIcon; /// The path to the lock screen icon file. - final String? lockIcon; + String? lockIcon; /// Converts to a map. - Map toMap() => { + Map toMap() => { 'icon': icon, 'iconForIndicator': indicatorIcon, 'iconForLock': lockIcon, @@ -88,7 +88,7 @@ class NotificationSound { NotificationSound({required this.type, this.path}); /// The type of sound. - final SoundType type; + SoundType type; /// The path to the user sound data file. /// @@ -96,7 +96,7 @@ class NotificationSound { String? path; /// Converts to a map. - Map toMap() => { + Map toMap() => { 'type': type.name, 'path': path, }; @@ -120,7 +120,7 @@ class NotificationVibration { NotificationVibration({required this.type, this.path}); /// The type of vibration. - final VibrationType type; + VibrationType type; /// The path to the user vibration data file. /// @@ -128,7 +128,7 @@ class NotificationVibration { String? path; /// Converts to a map. - Map toMap() => { + Map toMap() => { 'type': type.name, 'path': path, }; @@ -137,7 +137,7 @@ class NotificationVibration { /// The notification details. class TizenNotificationDetails { /// Constructs a [TizenNotificationDetails] from the given properties. - const TizenNotificationDetails({ + TizenNotificationDetails({ this.icons, this.sound, this.vibration, @@ -148,42 +148,40 @@ class TizenNotificationDetails { }); /// A set of icons to be shown in the notification layouts. - final NotificationIcons? icons; + NotificationIcons? icons; /// The sound to play when the notification is presented. - final NotificationSound? sound; + NotificationSound? sound; /// The notification vibration options. - final NotificationVibration? vibration; + NotificationVibration? vibration; /// Specifies how the system handles the notification in certain scenarios. /// /// Multiple [NotificationProperty] values can be set using the bitwise OR /// operator (|). - final int properties; + int properties; /// Specifies where and how the notification should be presented. /// /// Multiple [NotificationStyle] values can be set using the bitwise OR /// operator (|). - final int style; + int style; /// Whether the notification can be dismissed by user. /// /// Only supported on Raspberry Pi (common profile) devices. - final bool ongoing; + bool ongoing; /// A control message to be sent when the notification is clicked. - final AppControl? appControl; + AppControl? appControl; /// Converts to a map. Map toMap() => { 'image': icons?.toMap(), 'sound': sound?.toMap(), 'vibration': vibration?.toMap(), - 'properties': appControl != null - ? properties - : properties | NotificationProperty.disableAppLaunch, + 'properties': properties, 'displayApplist': style, 'ongoing': ongoing, if (appControl != null) diff --git a/packages/tizen_notification/lib/tizen_notification.dart b/packages/tizen_notification/lib/tizen_notification.dart index e1c8bd4bf..3555a66b7 100644 --- a/packages/tizen_notification/lib/tizen_notification.dart +++ b/packages/tizen_notification/lib/tizen_notification.dart @@ -27,6 +27,14 @@ class TizenNotificationPlugin { details['id'] = id.toString(); details['title'] = title; details['body'] = body; + + // Set disableAppLaunch automatically if appControl is unset. + if (notificationDetails?.appControl == null) { + final int properties = details['properties']! as int; + details['properties'] = + properties | NotificationProperty.disableAppLaunch; + } + return _channel.invokeMethod('show', details); } From 14b11bcc61f1b7883e6faa373be0c61e5835ec2c Mon Sep 17 00:00:00 2001 From: Swift Kim Date: Fri, 18 Nov 2022 18:14:14 +0900 Subject: [PATCH 5/5] Implement AppControl.toMap() --- .../tizen_notification/lib/src/types.dart | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/tizen_notification/lib/src/types.dart b/packages/tizen_notification/lib/src/types.dart index ec34f90b3..8548cc6b8 100644 --- a/packages/tizen_notification/lib/src/types.dart +++ b/packages/tizen_notification/lib/src/types.dart @@ -134,6 +134,17 @@ class NotificationVibration { }; } +extension _AppControlToMap on AppControl { + /// Converts to a map. + Map toMap() => { + 'appId': appId, + 'operation': operation, + 'uri': uri, + 'mime': mime, + 'extraData': extraData, + }; +} + /// The notification details. class TizenNotificationDetails { /// Constructs a [TizenNotificationDetails] from the given properties. @@ -184,13 +195,6 @@ class TizenNotificationDetails { 'properties': properties, 'displayApplist': style, 'ongoing': ongoing, - if (appControl != null) - 'appControl': { - 'appId': appControl!.appId, - 'operation': appControl!.operation, - 'uri': appControl!.uri, - 'mime': appControl!.mime, - 'extraData': appControl!.extraData, - }, + 'appControl': appControl?.toMap(), }; }