From: Marcin Bialek Date: Mon, 3 Jan 2022 09:40:45 +0000 (+0100) Subject: [Notification] Add API for using buttons and a text input in a notification and getti... X-Git-Tag: submit/tizen/20220223.080409~7^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F26%2F268826%2F6;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [Notification] Add API for using buttons and a text input in a notification and getting block state To add buttons tizen.NotificationButton can be used. It allows setting text, an image and an action. An array of buttons can be provided as a value for "buttons" key in InputInitDict. To use a text input, an object with proper values can be provided as a value for "textInput" key. To get notifications block state, tizen.notification.getBlockState() function can be used. [ACR] https://code.sec.samsung.net/jira/browse/TWDAPI-284 [Verification] Features have been tested with an example application which uses new API. Change-Id: I0d3d2110b3cf37d17e4cf632d18263f493606653 --- diff --git a/src/notification/common_notification.cc b/src/notification/common_notification.cc index dbf904db..cee40841 100644 --- a/src/notification/common_notification.cc +++ b/src/notification/common_notification.cc @@ -54,6 +54,15 @@ const ImageEnumMap CommonNotification::buttons_icon_paths_map_ = { {2, NOTIFICATION_IMAGE_TYPE_BUTTON_3}, {3, NOTIFICATION_IMAGE_TYPE_BUTTON_4}, {4, NOTIFICATION_IMAGE_TYPE_BUTTON_5}, {5, NOTIFICATION_IMAGE_TYPE_BUTTON_6}}; +const ButtonIndexEnumMap CommonNotification::buttons_index_map_ = { + {0, NOTIFICATION_BUTTON_1}, {1, NOTIFICATION_BUTTON_2}, {2, NOTIFICATION_BUTTON_3}, + {3, NOTIFICATION_BUTTON_4}, {4, NOTIFICATION_BUTTON_5}, {5, NOTIFICATION_BUTTON_6}}; + +const EventTypeEnumMap CommonNotification::buttons_events_map_ = { + {0, NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1}, {1, NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_2}, + {2, NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_3}, {3, NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_4}, + {4, NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_5}, {5, NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_6}}; + CommonNotification::CommonNotification() { } @@ -688,6 +697,95 @@ PlatformResult CommonNotification::SetAppControl(notification_h noti_handle, return PlatformResult(ErrorCode::NO_ERROR); } +PlatformResult CommonNotification::AddButton(notification_h noti_handle, + notification_button_index_e index) { + ScopeLogger(); + int ret = notification_add_button(noti_handle, index); + + if (NOTIFICATION_ERROR_NONE != ret) { + return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Notification add button error", + ("Notification add button error: %d", ret)); + } + + return PlatformResult(ErrorCode::NO_ERROR); +} + +PlatformResult CommonNotification::GetDisplayApplist(notification_h noti_handle, int* applist) { + ScopeLogger(); + int flags = 0; + int ret = notification_get_display_applist(noti_handle, &flags); + + if (NOTIFICATION_ERROR_NONE != ret) { + return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, + "Notification get display applist error", + ("Notification get display applist error: %d", ret)); + } + + if (applist) { + *applist = flags; + } + + return PlatformResult(ErrorCode::NO_ERROR); +} + +PlatformResult CommonNotification::SetDisplayApplist(notification_h noti_handle, int applist) { + ScopeLogger(); + int ret = notification_set_display_applist(noti_handle, applist); + + if (NOTIFICATION_ERROR_NONE != ret) { + return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, + "Notification set display applist error", + ("Notification set display applist error: %d", ret)); + } + + return PlatformResult(ErrorCode::NO_ERROR); +} + +PlatformResult CommonNotification::GetEventHandler(notification_h noti_handle, + notification_event_type_e event_type, + app_control_h* event_handler) { + ScopeLogger(); + app_control_h handler; + int ret = notification_get_event_handler(noti_handle, event_type, &handler); + + if (NOTIFICATION_ERROR_NONE != ret) { + return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Notification get event handler error", + ("Notification get event handler error: %d", ret)); + } + + if (event_handler) { + *event_handler = handler; + } + + return PlatformResult(ErrorCode::NO_ERROR); +} + +PlatformResult CommonNotification::SetEventHandler(notification_h noti_handle, + notification_event_type_e event_type, + app_control_h event_handler) { + ScopeLogger(); + int ret = notification_set_event_handler(noti_handle, event_type, event_handler); + + if (NOTIFICATION_ERROR_NONE != ret) { + return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Notification set event handler error", + ("Notification set event handler error: %d", ret)); + } + + return PlatformResult(ErrorCode::NO_ERROR); +} + +PlatformResult CommonNotification::SetTextInput(notification_h noti_handle, int max_length) { + ScopeLogger(); + int ret = notification_set_text_input(noti_handle, max_length); + + if (NOTIFICATION_ERROR_NONE != ret) { + return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Notification set text input error", + ("Notification set text input error: %d", ret)); + } + + return PlatformResult(ErrorCode::NO_ERROR); +} + PlatformResult CommonNotification::UpdateNotificationAfterPost(notification_h noti_handle, int id, picojson::object* out_ptr) { time_t posted_time; @@ -966,6 +1064,33 @@ PlatformResult CommonNotification::AddTextsArrayToJson(notification_h noti_handl return PlatformResult(ErrorCode::NO_ERROR); } +PlatformResult CommonNotification::AddEventHandlerToJson(notification_h noti_handle, + notification_event_type_e type, + const std::string& key, + picojson::object* out_ptr) { + ScopeLogger(); + picojson::object& out = *out_ptr; + app_control_h event_handler = nullptr; + SCOPE_EXIT { + if (event_handler) { + app_control_destroy(event_handler); + } + }; + + PlatformResult status = GetEventHandler(noti_handle, type, &event_handler); + CHECK_ERROR(status); + if (event_handler) { + picojson::object app_control; + status = GetApplicationControl(event_handler, &app_control); + CHECK_ERROR(status); + if (app_control.size()) { + out[key] = picojson::value(app_control); + } + } + + return PlatformResult(ErrorCode::NO_ERROR); +} + PlatformResult CommonNotification::AddLedColorToJson(notification_h noti_handle, picojson::object* out_ptr) { ScopeLogger(); @@ -1376,5 +1501,33 @@ PlatformResult CommonNotification::SetTextFromJson(const picojson::value& noti_v return PlatformResult(ErrorCode::NO_ERROR); } +PlatformResult CommonNotification::SetEventHandlerFromJson(const picojson::value& noti_val, + notification_event_type_e type, + const std::string& key, + notification_h noti_handle) { + ScopeLogger(); + const picojson::object& noti_obj = noti_val.get(); + app_control_h event_handler = nullptr; + SCOPE_EXIT { + if (event_handler) { + app_control_destroy(event_handler); + } + }; + + if (noti_val.contains(key) && !IsNull(noti_obj, key.c_str())) { + PlatformResult status = CreateAppControl(&event_handler); + CHECK_ERROR(status); + + const auto& app_control = FromJson(noti_obj, key.c_str()); + status = SetApplicationControl(event_handler, app_control); + CHECK_ERROR(status); + + status = SetEventHandler(noti_handle, type, event_handler); + CHECK_ERROR(status); + } + + return PlatformResult(ErrorCode::NO_ERROR); +} + } // namespace notification } // namespace extension diff --git a/src/notification/common_notification.h b/src/notification/common_notification.h index 7bb17c42..4646c93b 100644 --- a/src/notification/common_notification.h +++ b/src/notification/common_notification.h @@ -39,6 +39,8 @@ const std::string kProgressTypeByte = "BYTE"; typedef std::map InformationEnumMap; typedef std::map ImageEnumMap; +typedef std::map ButtonIndexEnumMap; +typedef std::map EventTypeEnumMap; typedef std::function @@ -57,6 +59,8 @@ class CommonNotification { static const ImageEnumMap thumbnails_map_; static const InformationEnumMap buttons_texts_map_; static const ImageEnumMap buttons_icon_paths_map_; + static const ButtonIndexEnumMap buttons_index_map_; + static const EventTypeEnumMap buttons_events_map_; static common::PlatformResult StatusTypeFromPlatform(notification_type_e noti_type, notification_ly_type_e noti_layout, @@ -99,6 +103,17 @@ class CommonNotification { double progress_value, bool is_update); static common::PlatformResult GetPostedTime(notification_h noti_handle, time_t* posted_time); static common::PlatformResult SetLayout(notification_h noti_handle, const std::string& noti_type); + static common::PlatformResult AddButton(notification_h noti_handle, + notification_button_index_e index); + static common::PlatformResult GetDisplayApplist(notification_h noti_handle, int* applist); + static common::PlatformResult SetDisplayApplist(notification_h noti_handle, int applist); + static common::PlatformResult GetEventHandler(notification_h noti_handle, + notification_event_type_e event_type, + app_control_h* event_handler); + static common::PlatformResult SetEventHandler(notification_h noti_handle, + notification_event_type_e event_type, + app_control_h event_handler); + static common::PlatformResult SetTextInput(notification_h noti_handle, int max_length); static common::PlatformResult CreateAppControl(app_control_h* app_control); static bool IsColorFormatNumeric(const std::string& color); @@ -148,6 +163,10 @@ class CommonNotification { static common::PlatformResult AddTextsArrayToJson(notification_h noti_handle, InformationEnumMap map, const std::string& key, picojson::object* out_ptr); + static common::PlatformResult AddEventHandlerToJson(notification_h noti_handle, + notification_event_type_e type, + const std::string& key, + picojson::object* out_ptr); // FromJson section static common::PlatformResult InitNotiFromJson(const picojson::object& args, @@ -188,6 +207,10 @@ class CommonNotification { static common::PlatformResult SetTextFromJson(const picojson::value& noti_value, notification_text_type_e type, const std::string& key, notification_h noti_handle); + static common::PlatformResult SetEventHandlerFromJson(const picojson::value& noti_val, + notification_event_type_e type, + const std::string& key, + notification_h noti_handle); static common::PlatformResult PostNotification(const picojson::object& args, bool is_update, picojson::object* out_ptr, diff --git a/src/notification/notification_api.js b/src/notification/notification_api.js index 1ca6622f..0f77e5dc 100644 --- a/src/notification/notification_api.js +++ b/src/notification/notification_api.js @@ -283,6 +283,16 @@ NotificationManager.prototype.getAllNotifications = function() { return notifications; }; +NotificationManager.prototype.getBlockState = function() { + var result = native_.callSync('NotificationManagerGetBlockState', {}); + + if (native_.isFailure(result)) { + throw native_.getErrorObject(result); + } + + return native_.getResultObject(result); +}; + /** * Plays the custom effect of the service LED that is located to the front of a device. * @@ -1147,6 +1157,199 @@ function LedsInitDict(data) { } } +function NotificationButton(text, appControl, imagePath) { + validator_.isConstructorCall(this, NotificationButton); + + var _text = type_.isString(text) ? text : ''; + var _appControl = + appControl instanceof tizen.ApplicationControl + ? appControl + : type_.isObject(appControl) + ? new tizen.ApplicationControl( + appControl.operation, + appControl.uri || null, + appControl.mime || null, + appControl.category || null, + appControl.data || [] + ) + : null; + var _imagePath = type_.isString(imagePath) ? imagePath : null; + + Object.defineProperties(this, { + text: { + get: function() { + return _text; + }, + set: function(v) { + _text = type_.isString(v) ? v : _text; + }, + enumerable: true + }, + appControl: { + get: function() { + return _appControl; + }, + set: function(v) { + _appControl = + v instanceof tizen.ApplicationControl + ? v + : type_.isObject(v) + ? new tizen.ApplicationControl( + v.operation, + v.uri || null, + v.mime || null, + v.category || null, + v.data || [] + ) + : _appControl; + }, + enumerable: true + }, + imagePath: { + get: function() { + return _imagePath; + }, + set: function(v) { + _imagePath = type_.isString(v) ? v : _imagePath; + }, + enumerable: true + } + }); +} + +function TextInputInitDict(data) { + if (!this) return; + var _appControl = null; + var _buttonText = null; + var _imagePath = null; + var _maxLength = null; + var _placeholder = null; + + Object.defineProperties(this, { + appControl: { + get: function() { + return _appControl; + }, + set: function(v) { + _appControl = + v instanceof tizen.ApplicationControl + ? v + : type_.isObject(v) + ? new tizen.ApplicationControl( + v.operation, + v.uri || null, + v.mime || null, + v.category || null, + v.data || [] + ) + : _appControl; + }, + enumerable: true + }, + buttonText: { + get: function() { + return _buttonText; + }, + set: function(v) { + _buttonText = type_.isString(v) || type_.isNull(v) ? v : _buttonText; + }, + enumerable: true + }, + imagePath: { + get: function() { + return _imagePath; + }, + set: function(v) { + _imagePath = type_.isString(v) || type_.isNull(v) ? v : _imagePath; + }, + enumerable: true + }, + maxLength: { + get: function() { + return _maxLength; + }, + set: function(v) { + _maxLength = type_.isNumber(v) || type_.isNull(v) ? v : _maxLength; + }, + enumerable: true + }, + placeholder: { + get: function() { + return _placeholder; + }, + set: function(v) { + _placeholder = type_.isString(v) || type_.isNull(v) ? v : _placeholder; + }, + enumerable: true + } + }); + + if (data instanceof _global.Object) { + for (var prop in data) { + if (this.hasOwnProperty(prop)) { + this[prop] = data[prop]; + } + } + } +} + +var _setButtons = function(v) { + return v.map(function(b) { + return new tizen.NotificationButton(b.text, b.appControl, b.imagePath); + }); +}; + +var _checkButtons = function(v) { + if (type_.isNull(v)) { + return true; + } + if (!type_.isArray(v)) { + return false; + } + return v.every(function(b) { + return b instanceof tizen.NotificationButton; + }); +}; + +function InputInitDict(data) { + if (!this) return; + var _buttons = []; + var _textInput = null; + + Object.defineProperties(this, { + buttons: { + get: function() { + return _buttons; + }, + set: function(v) { + _buttons = _checkButtons(v) + ? v + : type_.isArray(v) + ? _setButtons(v) + : _buttons; + }, + enumerable: true + }, + textInput: { + get: function() { + return _textInput; + }, + set: function(v) { + _textInput = type_.isObject(v) || type_.isNull(v) ? v : _textInput; + }, + enumerable: true + } + }); + + if (data instanceof _global.Object) { + for (var prop in data) { + if (this.hasOwnProperty(prop)) { + this[prop] = data[prop]; + } + } + } +} + function UserNotification(userType, title, notificationGroupedInitDict) { validator_.isConstructorCall(this, UserNotification); type_.isObject(notificationGroupedInitDict) @@ -1165,6 +1368,7 @@ function UserNotification(userType, title, notificationGroupedInitDict) { this.groupContents = new GroupContentsInitDict( notificationGroupedInitDict.groupContents ); + this.inputs = new InputInitDict(notificationGroupedInitDict.inputs); var _userType = Object.keys(UserNotificationType).indexOf(userType) >= 0 @@ -1197,6 +1401,7 @@ function UserNotificationInitDict(data) { var _actions = null; var _groupContents = null; var _leds = null; + var _inputs = null; Object.defineProperties(this, { textContents: { @@ -1253,6 +1458,15 @@ function UserNotificationInitDict(data) { _leds = type_.isObject(v) || type_.isNull(v) ? v : _leds; }, enumerable: true + }, + inputs: { + get: function() { + return _inputs; + }, + set: function(v) { + _inputs = type_.isObject(v) || type_.isNull(v) ? v : _inputs; + }, + enumerable: true } }); @@ -1269,3 +1483,4 @@ exports = new NotificationManager(); tizen.StatusNotification = StatusNotification; tizen.UserNotification = UserNotification; tizen.NotificationDetailInfo = NotificationDetailInfo; +tizen.NotificationButton = NotificationButton; diff --git a/src/notification/notification_extension.cc b/src/notification/notification_extension.cc index 2a9495c7..9ea07fc9 100644 --- a/src/notification/notification_extension.cc +++ b/src/notification/notification_extension.cc @@ -29,7 +29,8 @@ NotificationExtension::NotificationExtension() { SetJavaScriptAPI(kSource_notification_api); const char* entry_points[] = {"tizen.StatusNotification", "tizen.UserNotification", - "tizen.NotificationDetailInfo", NULL}; + "tizen.NotificationDetailInfo", "tizen.NotificationButton", + NULL}; SetExtraJSEntryPoints(entry_points); } diff --git a/src/notification/notification_instance.cc b/src/notification/notification_instance.cc index 7d2a0799..ec771107 100644 --- a/src/notification/notification_instance.cc +++ b/src/notification/notification_instance.cc @@ -51,6 +51,7 @@ NotificationInstance::NotificationInstance() { REGISTER_METHOD(NotificationManagerStopLEDCustomEffect); REGISTER_METHOD(NotificationManagerSaveNotificationAsTemplate); REGISTER_METHOD(NotificationManagerCreateNotificationFromTemplate); + REGISTER_METHOD(NotificationManagerGetBlockState); #undef REGISTER_METHOD manager_ = NotificationManager::GetInstance(); @@ -186,6 +187,19 @@ void NotificationInstance::NotificationManagerGetAll(const picojson::value& args } } +void NotificationInstance::NotificationManagerGetBlockState(const picojson::value& args, + picojson::object& out) { + ScopeLogger(); + picojson::value val; + PlatformResult status = manager_->GetBlockState(val); + + if (status.IsSuccess()) { + ReportSuccess(val, out); + } else { + LogAndReportError(status, &out); + } +} + void NotificationInstance::NotificationManagerPlayLEDCustomEffect(const picojson::value& args, picojson::object& out) { ScopeLogger(); diff --git a/src/notification/notification_instance.h b/src/notification/notification_instance.h index 0d730906..509ace8a 100644 --- a/src/notification/notification_instance.h +++ b/src/notification/notification_instance.h @@ -37,6 +37,7 @@ class NotificationInstance : public common::ParsedInstance { void NotificationManagerRemoveAll(const picojson::value& args, picojson::object& out); void NotificationManagerGet(const picojson::value& args, picojson::object& out); void NotificationManagerGetAll(const picojson::value& args, picojson::object& out); + void NotificationManagerGetBlockState(const picojson::value& args, picojson::object& out); void NotificationManagerPlayLEDCustomEffect(const picojson::value& args, picojson::object& out); void NotificationManagerStopLEDCustomEffect(const picojson::value& args, picojson::object& out); diff --git a/src/notification/notification_manager.cc b/src/notification/notification_manager.cc index 8d0a0e26..e249b61c 100644 --- a/src/notification/notification_manager.cc +++ b/src/notification/notification_manager.cc @@ -38,6 +38,11 @@ namespace notification { using namespace common; +const BlockStateEnumMap NotificationManager::block_state_map_ = { + {NOTIFICATION_BLOCK_STATE_ALLOWED, "ALLOWED"}, + {NOTIFICATION_BLOCK_STATE_BLOCKED, "BLOCKED"}, + {NOTIFICATION_BLOCK_STATE_DO_NOT_DISTURB, "DO_NOT_DISTURB"}}; + NotificationManager::NotificationManager() { ScopeLogger(); } @@ -215,6 +220,27 @@ PlatformResult NotificationManager::GetAll(picojson::array& out, bool is_new_imp return PlatformResult(ErrorCode::NO_ERROR); } +PlatformResult NotificationManager::GetBlockState(picojson::value& out) { + ScopeLogger(); + + notification_block_state_e state; + int ret = notification_get_noti_block_state(&state); + + if (ret != NOTIFICATION_ERROR_NONE) { + return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get block state error", + ("Get block state error: %d", ret)); + } + + const auto& state_iter = block_state_map_.find(state); + if (state_iter == block_state_map_.end()) { + return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown state", + ("Unknown state: %d", state)); + } + + out = picojson::value(state_iter->second); + return PlatformResult(ErrorCode::NO_ERROR); +} + PlatformResult NotificationManager::PlayLEDCustomEffect(const picojson::object& args) { ScopeLogger(); diff --git a/src/notification/notification_manager.h b/src/notification/notification_manager.h index 883ee574..6a49cd49 100644 --- a/src/notification/notification_manager.h +++ b/src/notification/notification_manager.h @@ -25,8 +25,12 @@ namespace extension { namespace notification { +typedef std::map BlockStateEnumMap; + class NotificationManager { public: + static const BlockStateEnumMap block_state_map_; + static NotificationManager* GetInstance(); common::PlatformResult Post(const picojson::object& args, picojson::object& out); @@ -38,6 +42,7 @@ class NotificationManager { common::PlatformResult Get(const picojson::object& args, picojson::object& out, bool is_new_impl = false); common::PlatformResult GetAll(picojson::array& out, bool is_new_impl = false); + common::PlatformResult GetBlockState(picojson::value& out); common::PlatformResult PlayLEDCustomEffect(const picojson::object& args); common::PlatformResult StopLEDCustomEffect(); diff --git a/src/notification/user_notification.cc b/src/notification/user_notification.cc index d7960dec..6282a3bc 100644 --- a/src/notification/user_notification.cc +++ b/src/notification/user_notification.cc @@ -59,6 +59,9 @@ PlatformResult UserNotification::ToJson(int id, notification_h noti_handle, ret = AddLedsToJson(noti_handle, out_ptr); CHECK_ERROR(ret); + ret = AddInputsToJson(noti_handle, out_ptr); + CHECK_ERROR(ret); + return PlatformResult(ErrorCode::NO_ERROR); } @@ -95,6 +98,9 @@ PlatformResult UserNotification::GetNotiHandleFromJson(const picojson::value& no status = SetLedsFromJson(noti_val, tmp_noti); CHECK_ERROR(status); + status = SetInputsFromJson(noti_val, tmp_noti); + CHECK_ERROR(status); + *noti_handle = tmp_noti_ptr.release(); return PlatformResult(ErrorCode::NO_ERROR); @@ -277,6 +283,97 @@ PlatformResult UserNotification::AddLedsToJson(notification_h noti_handle, return PlatformResult(ErrorCode::NO_ERROR); } +PlatformResult UserNotification::AddButtonsToJson(notification_h noti_handle, + picojson::object* out_ptr) { + ScopeLogger(); + picojson::object& out = *out_ptr; + picojson::array buttons_array; + + for (size_t i = 0; i < buttons_texts_map_.size(); i++) { + LoggerD("processing button %u", i); + picojson::object item; + + PlatformResult status = AddTextToJson(noti_handle, buttons_texts_map_.at(i), "text", &item); + CHECK_ERROR(status); + // There is no native function to check the number of buttons in a notification. Instead, it + // is assumed that there are no more buttons if the text in a currently processed one does not + // exist or it is null. + if (!picojson::value(item).contains("text") || IsNull(item, "text")) { + LoggerD("no text in the current button, end of buttons"); + break; + } + + status = AddEventHandlerToJson(noti_handle, buttons_events_map_.at(i), "appControl", &item); + CHECK_ERROR(status); + + status = AddPathToJson(noti_handle, buttons_icon_paths_map_.at(i), "imagePath", &item); + CHECK_ERROR(status); + + buttons_array.push_back(picojson::value(item)); + } + + out["buttons"] = picojson::value(buttons_array); + return PlatformResult(ErrorCode::NO_ERROR); +} + +PlatformResult UserNotification::AddTextInputToJson(notification_h noti_handle, + picojson::object* out_ptr) { + ScopeLogger(); + picojson::object& out = *out_ptr; + picojson::object text_input_obj; + + // There is no native function to check whether the text input is present + // in the notification or not. However, if there is one, an event handler + // for NOTIFICATION_EVENT_TYPE_CLICK_ON_TEXT_INPUT_BUTTON must be set. The + // function below returns an error if it is not set (it calls native function + // notification_get_event_handler which returns an error in such a case) + // or no error otherwise. + PlatformResult status = + AddEventHandlerToJson(noti_handle, NOTIFICATION_EVENT_TYPE_CLICK_ON_TEXT_INPUT_BUTTON, + "appControl", &text_input_obj); + + // If AddEventHandlerToJson returns an error, it is assumed that there is no + // text input in the notification. + if (status.IsSuccess() && picojson::value(text_input_obj).contains("appControl")) { + LoggerD("valid appControl, adding text input to json"); + // There is no native function to get max length of a text input + // so an arbitrary value is set. + text_input_obj["maxLength"] = picojson::value(160.0); + + status = AddTextToJson(noti_handle, NOTIFICATION_TEXT_TYPE_TEXT_INPUT_BUTTON, "buttonText", + &text_input_obj); + CHECK_ERROR(status); + + status = AddTextToJson(noti_handle, NOTIFICATION_TEXT_TYPE_TEXT_INPUT_PLACEHOLDER, + "placeholder", &text_input_obj); + CHECK_ERROR(status); + + status = AddPathToJson(noti_handle, NOTIFICATION_IMAGE_TYPE_TEXT_INPUT_BUTTON, "imagePath", + &text_input_obj); + CHECK_ERROR(status); + + out["textInput"] = picojson::value(text_input_obj); + } + + return PlatformResult(ErrorCode::NO_ERROR); +} + +PlatformResult UserNotification::AddInputsToJson(notification_h noti_handle, + picojson::object* out_ptr) { + ScopeLogger(); + picojson::object& out = *out_ptr; + picojson::object inputs_obj; + + PlatformResult status = AddButtonsToJson(noti_handle, &inputs_obj); + CHECK_ERROR(status); + + status = AddTextInputToJson(noti_handle, &inputs_obj); + CHECK_ERROR(status); + + out["inputs"] = picojson::value(inputs_obj); + return PlatformResult(ErrorCode::NO_ERROR); +} + PlatformResult UserNotification::SetTextContentsFromJson(const picojson::value& noti_value, bool is_update, notification_h noti_handle) { @@ -453,5 +550,104 @@ PlatformResult UserNotification::SetLedsFromJson(const picojson::value& noti_val return PlatformResult(ErrorCode::NO_ERROR); } +PlatformResult UserNotification::SetButtonsFromJson(const picojson::value& noti_val, + notification_h noti_handle) { + ScopeLogger(); + const picojson::object& noti_obj = noti_val.get(); + + if (noti_val.contains("buttons") && noti_val.get("buttons").is()) { + const picojson::array& buttons_array = FromJson(noti_obj, "buttons"); + + if (buttons_array.size() > buttons_index_map_.size()) { + return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Too many values in array"); + } + + int i = 0; + for (const auto& item : buttons_array) { + LoggerD("processing button %d", i); + if (!item.is()) { + return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid button object"); + } + + PlatformResult status = AddButton(noti_handle, buttons_index_map_.at(i)); + CHECK_ERROR(status); + + status = SetTextFromJson(item, buttons_texts_map_.at(i), "text", noti_handle); + CHECK_ERROR(status); + + status = SetEventHandlerFromJson(item, buttons_events_map_.at(i), "appControl", noti_handle); + CHECK_ERROR(status); + + status = SetPathFromJson(item, buttons_icon_paths_map_.at(i), "imagePath", noti_handle); + CHECK_ERROR(status); + + i++; + } + + if (i > 0) { + PlatformResult status = SetDisplayApplist(noti_handle, NOTIFICATION_DISPLAY_APP_ACTIVE); + CHECK_ERROR(status); + } + } + + return PlatformResult(ErrorCode::NO_ERROR); +} + +PlatformResult UserNotification::SetTextInputFromJson(const picojson::value& noti_val, + notification_h noti_handle) { + ScopeLogger(); + + if (noti_val.contains("textInput") && noti_val.get("textInput").is()) { + const picojson::value& text_input_val = noti_val.get("textInput"); + const picojson::object& text_input_obj = text_input_val.get(); + + if (text_input_val.contains("maxLength") && text_input_val.get("maxLength").is()) { + LoggerD("valid maxLength, setting text input"); + const unsigned long max_length = + static_cast(FromJson(text_input_obj, "maxLength")); + PlatformResult status = SetTextInput(noti_handle, max_length); + CHECK_ERROR(status); + + status = SetEventHandlerFromJson(text_input_val, + NOTIFICATION_EVENT_TYPE_CLICK_ON_TEXT_INPUT_BUTTON, + "appControl", noti_handle); + + status = SetTextFromJson(text_input_val, NOTIFICATION_TEXT_TYPE_TEXT_INPUT_PLACEHOLDER, + "placeholder", noti_handle); + CHECK_ERROR(status); + + status = SetTextFromJson(text_input_val, NOTIFICATION_TEXT_TYPE_TEXT_INPUT_BUTTON, + "buttonText", noti_handle); + CHECK_ERROR(status); + + status = SetPathFromJson(text_input_val, NOTIFICATION_IMAGE_TYPE_TEXT_INPUT_BUTTON, + "imagePath", noti_handle); + CHECK_ERROR(status); + + status = SetDisplayApplist(noti_handle, NOTIFICATION_DISPLAY_APP_ACTIVE); + CHECK_ERROR(status); + } + } + + return PlatformResult(ErrorCode::NO_ERROR); +} + +PlatformResult UserNotification::SetInputsFromJson(const picojson::value& noti_val, + notification_h noti_handle) { + ScopeLogger(); + + if (noti_val.contains("inputs") && noti_val.get("inputs").is()) { + const picojson::value& inputs_val = noti_val.get("inputs"); + + PlatformResult status = SetButtonsFromJson(inputs_val, noti_handle); + CHECK_ERROR(status); + + status = SetTextInputFromJson(inputs_val, noti_handle); + CHECK_ERROR(status); + } + + return PlatformResult(ErrorCode::NO_ERROR); +} + } // namespace notification } // namespace extension diff --git a/src/notification/user_notification.h b/src/notification/user_notification.h index 86f1c9c5..daec9021 100644 --- a/src/notification/user_notification.h +++ b/src/notification/user_notification.h @@ -47,6 +47,12 @@ class UserNotification : public CommonNotification { picojson::object* out_ptr); static common::PlatformResult AddLedsToJson(notification_h noti_handle, picojson::object* out_ptr); + static common::PlatformResult AddButtonsToJson(notification_h noti_handle, + picojson::object* out_ptr); + static common::PlatformResult AddTextInputToJson(notification_h noti_handle, + picojson::object* out_ptr); + static common::PlatformResult AddInputsToJson(notification_h noti_handle, + picojson::object* out_ptr); static common::PlatformResult SetTextContentsFromJson(const picojson::value& noti_val, bool is_update, notification_h noti_handle); @@ -60,6 +66,12 @@ class UserNotification : public CommonNotification { notification_h noti_handle); static common::PlatformResult SetLedsFromJson(const picojson::value& noti_val, notification_h noti_handle); + static common::PlatformResult SetButtonsFromJson(const picojson::value& noti_val, + notification_h noti_handle); + static common::PlatformResult SetTextInputFromJson(const picojson::value& noti_val, + notification_h noti_handle); + static common::PlatformResult SetInputsFromJson(const picojson::value& noti_val, + notification_h noti_handle); private: UserNotification();