From 4e57ab083272fed5d8623277812937c7cffdd6c9 Mon Sep 17 00:00:00 2001 From: wufarong Date: Sun, 17 Nov 2024 16:41:13 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9B=BE=E5=BD=A2=E6=8C=89=E9=92=AE=E6=97=A0?= =?UTF-8?q?=E9=9A=9C=E7=A2=8D=E6=94=AF=E6=8C=81=E9=9C=80=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wufarong Change-Id: I37449c90440e88e0d49e0b7cfb708ea2897f3578 --- frameworks/ans/BUILD.gn | 1 + .../notification_local_live_view_content.cpp | 107 ++++++ ...tification_local_live_view_icon_button.cpp | 347 ++++++++++++++++++ frameworks/js/napi/include/common.h | 45 +++ .../js/napi/src/common_convert_liveview.cpp | 255 ++++++++++++- .../notification_local_live_view_content.h | 31 ++ ...notification_local_live_view_icon_button.h | 170 +++++++++ 7 files changed, 948 insertions(+), 8 deletions(-) create mode 100644 frameworks/ans/src/notification_local_live_view_icon_button.cpp create mode 100644 interfaces/inner_api/notification_local_live_view_icon_button.h diff --git a/frameworks/ans/BUILD.gn b/frameworks/ans/BUILD.gn index 837a2878d..f0804a665 100644 --- a/frameworks/ans/BUILD.gn +++ b/frameworks/ans/BUILD.gn @@ -93,6 +93,7 @@ ohos_shared_library("ans_innerkits") { "${frameworks_module_ans_path}/src/notification_live_view_content.cpp", "${frameworks_module_ans_path}/src/notification_local_live_view_button.cpp", "${frameworks_module_ans_path}/src/notification_local_live_view_content.cpp", + "${frameworks_module_ans_path}/src/notification_local_live_view_icon_button.cpp", "${frameworks_module_ans_path}/src/notification_local_live_view_subscriber.cpp", "${frameworks_module_ans_path}/src/notification_long_text_content.cpp", "${frameworks_module_ans_path}/src/notification_media_content.cpp", diff --git a/frameworks/ans/src/notification_local_live_view_content.cpp b/frameworks/ans/src/notification_local_live_view_content.cpp index 697fa5026..baa35b8fc 100644 --- a/frameworks/ans/src/notification_local_live_view_content.cpp +++ b/frameworks/ans/src/notification_local_live_view_content.cpp @@ -29,12 +29,14 @@ #include "notification_json_convert.h" #include "notification_progress.h" #include "notification_local_live_view_button.h" +#include "notification_local_live_view_icon_button.h" #include "notification_time.h" #include "parcel.h" // for Parcel namespace OHOS { namespace Notification { +const std::size_t NotificationLocalLiveViewContent::MAX_ICON_BUTTONS {3}; void NotificationLocalLiveViewContent::SetType(int32_t type) { type_ = type; @@ -65,6 +67,27 @@ NotificationLocalLiveViewButton NotificationLocalLiveViewContent::GetButton() return button_; } +void NotificationLocalLiveViewContent::AddIconButton( + const std::shared_ptr &iconButton) +{ + if (!iconButton) { + ANS_LOGW("iconButton can not be null"); + return; + } + + if (iconButtons_.size() >= NotificationLocalLiveViewContent::MAX_ICON_BUTTONS) { + ANS_LOGW("three icon buttons have been already added"); + return; + } + + iconButtons_.emplace_back(iconButton); +} + +const std::vector> NotificationLocalLiveViewContent::GetIconButtons() const +{ + return iconButtons_; +} + void NotificationLocalLiveViewContent::SetProgress(NotificationProgress progress) { progress_ = progress; @@ -106,6 +129,7 @@ std::string NotificationLocalLiveViewContent::Dump() ", type = " + std::to_string(type_) + ", capsule = " + capsule_.Dump() + ", button = " + button_.Dump() + + ", iconButtons = " + (!iconButtons_.empty() ? iconButtons_.at(0)->Dump() : "empty") + ", progress = " + progress_.Dump() + ", time = " + time_.Dump() + " }"; @@ -130,6 +154,22 @@ bool NotificationLocalLiveViewContent::ToJson(nlohmann::json &jsonObject) const return false; } + nlohmann::json buttonsArr = nlohmann::json::array(); + for (auto &btn : iconButtons_) { + if (!btn) { + continue; + } + + nlohmann::json btnObj; + if (!NotificationJsonConverter::ConvertToJson(btn.get(), btnObj)) { + ANS_LOGE("Cannot convert iconButton to JSON"); + return false; + } + + buttonsArr.emplace_back(btnObj); + } + jsonObject["iconButtons"] = buttonsArr; + nlohmann::json progressObj; if (!NotificationJsonConverter::ConvertToJson(&progress_, progressObj)) { ANS_LOGE("Cannot convert progress to JSON"); @@ -182,6 +222,12 @@ NotificationLocalLiveViewContent *NotificationLocalLiveViewContent::FromJson(con } } + if (!ConvertJsonToNotificationIconButton(pContent, jsonObject)) { + delete pContent; + pContent = nullptr; + return nullptr; + } + if (jsonObject.find("button") != jsonEnd) { auto buttonObj = jsonObject.at("button"); auto pButton = NotificationJsonConverter::ConvertFromJson(buttonObj); @@ -219,6 +265,31 @@ NotificationLocalLiveViewContent *NotificationLocalLiveViewContent::FromJson(con return pContent; } +bool NotificationLocalLiveViewContent::ConvertJsonToNotificationIconButton( + NotificationLocalLiveViewContent *target, const nlohmann::json &jsonObject) +{ + if (target == nullptr) { + ANS_LOGE("Invalid input parameter"); + return false; + } + + const auto &jsonEnd = jsonObject.cend(); + + if (jsonObject.find("iconButtons") != jsonEnd) { + auto buttonArr = jsonObject.at("iconButtons"); + for (auto &btnObj : buttonArr) { + auto pBtn = NotificationJsonConverter::ConvertFromJson(btnObj); + if (pBtn == nullptr) { + ANS_LOGE("Failed to parse iconButton!"); + return false; + } + + target->iconButtons_.emplace_back(pBtn); + } + } + + return true; +} bool NotificationLocalLiveViewContent::Marshalling(Parcel &parcel) const { if (!NotificationBasicContent::Marshalling(parcel)) { @@ -240,6 +311,18 @@ bool NotificationLocalLiveViewContent::Marshalling(Parcel &parcel) const return false; } + if (!parcel.WriteUint64(iconButtons_.size())) { + ANS_LOGE("Failed to write the size of iconButtons"); + return false; + } + + for (auto it = iconButtons_.begin(); it != iconButtons_.end(); ++it) { + if (!parcel.WriteParcelable(it->get())) { + ANS_LOGE("Failed to write iconButton"); + return false; + } + } + if (!parcel.WriteParcelable(&button_)) { ANS_LOGE("Failed to write button"); return false; @@ -295,6 +378,10 @@ bool NotificationLocalLiveViewContent::ReadFromParcel(Parcel &parcel) delete pCapsule; pCapsule = nullptr; + if (!ReadIconButtonsFromParcel(parcel)) { + return false; + } + auto pButton = parcel.ReadParcelable(); if (pButton == nullptr) { ANS_LOGE("Failed to read button"); @@ -330,6 +417,26 @@ bool NotificationLocalLiveViewContent::ReadFromParcel(Parcel &parcel) return true; } +bool NotificationLocalLiveViewContent::ReadIconButtonsFromParcel(Parcel &parcel) +{ + auto vsize = parcel.ReadUint64(); + if (vsize > NotificationLocalLiveViewContent::MAX_ICON_BUTTONS) { + vsize = NotificationLocalLiveViewContent::MAX_ICON_BUTTONS; + } + for (uint64_t it = 0; it < vsize; ++it) { + auto member = std::shared_ptr + (parcel.ReadParcelable()); + if (member == nullptr) { + iconButtons_.clear(); + ANS_LOGE("Failed to read iconButton"); + return false; + } + + iconButtons_.emplace_back(member); + } + return true; +} + void NotificationLocalLiveViewContent::ClearButton() { button_.ClearButtonIcons(); diff --git a/frameworks/ans/src/notification_local_live_view_icon_button.cpp b/frameworks/ans/src/notification_local_live_view_icon_button.cpp new file mode 100644 index 000000000..9701ff6b5 --- /dev/null +++ b/frameworks/ans/src/notification_local_live_view_icon_button.cpp @@ -0,0 +1,347 @@ +/* + +Copyright (c) 2023 Huawei Device Co., Ltd. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +#include "notification_local_live_view_icon_button.h" + +#include +#include +#include // for basic_string, operator+, basic_string<>... +#include // for shared_ptr, shared_ptr<>::element_type + +#include "ans_image_util.h" +#include "ans_log_wrapper.h" +#include "nlohmann/json.hpp" // for json, basic_json<>::object_t, basic_json +#include "notification_json_convert.h" +#include "parcel.h" // for Parcel +#include "pixel_map.h" // for PixelMap + +namespace OHOS { +namespace Notification { +const uint32_t RESOURCE_BUNDLENAME_INDEX = 0; +const uint32_t RESOURCE_MODULENAME_INDEX = 1; +const uint32_t RESOURCE_ID_INDEX = 2; +const uint32_t BUTTON_RESOURCE_SIZE = 3; +using ResourceVectorPtr = std::vector>; + +void NotificationLocalLiveViewIconButton::SetButtonName(const std::string &buttonName) +{ + buttonName_ = buttonName; + return; +} + +std::string NotificationLocalLiveViewIconButton::GetButtonName() const +{ + return buttonName_; +} + +void NotificationLocalLiveViewIconButton::SetButtonIcon(std::shared_ptr &buttonIcon) +{ + buttonIconPixelMap_ = buttonIcon; + return; +} + +std::shared_ptr NotificationLocalLiveViewIconButton::GetButtonIcon() const +{ + return buttonIconPixelMap_; +} + +void NotificationLocalLiveViewIconButton::SetButtonIconResource( + std::shared_ptr &buttonIconResource) +{ + buttonIconResource_ = buttonIconResource; + return; +} + +std::shared_ptr NotificationLocalLiveViewIconButton::GetButtonIconResource() const +{ + return buttonIconResource_; +} + +void NotificationLocalLiveViewIconButton::SetButtonDescription( + std::shared_ptr &buttonDescription) +{ + buttonDescription_ = buttonDescription; + return; +} + +std::shared_ptr NotificationLocalLiveViewIconButton::GetButtonDescription() const +{ + return buttonDescription_; +} + +void NotificationLocalLiveViewIconButton::SetButtonDescriptionStr(const std::string &buttonDescription) +{ + buttonDescriptionStr_ = buttonDescription; + return; +} + +std::string NotificationLocalLiveViewIconButton::GetButtonDescriptionStr() const +{ + return buttonDescriptionStr_; +} + +bool NotificationLocalLiveViewIconButton::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteString(buttonName_)) { + ANS_LOGE("Failed to write buttonName."); + return false; + } + + if (!WriteIconToParcel(parcel)) { + return false; + } + bool valid {false}; + valid = buttonDescription_ ? true : false; + if (!parcel.WriteBool(valid)) { + ANS_LOGE("Failed to write the flag which indicate whether button description is null"); + return false; + } + if (valid) { + std::vector buttonDescriptionResource = {}; + buttonDescriptionResource.push_back(buttonDescription_->bundleName); + buttonDescriptionResource.push_back(buttonDescription_->moduleName); + buttonDescriptionResource.push_back(buttonDescription_->id); + if (!parcel.WriteStringVector(buttonDescriptionResource)) { + ANS_LOGE("Failed to write button description resource"); + return false; + } + } + + valid = buttonDescriptionStr_.empty() ? false : true; + if (!parcel.WriteBool(valid)) { + ANS_LOGE("Failed to write the flag which indicate whether button description str is null"); + return false; + } + if (valid) { + if (!parcel.WriteString(buttonDescriptionStr_)) { + ANS_LOGE("Failed to write button description str"); + return false; + } + } + return true; +} + +bool NotificationLocalLiveViewIconButton::WriteIconToParcel(Parcel &parcel) const +{ + bool valid {false}; + valid = buttonIconPixelMap_ ? true : false; + if (!parcel.WriteBool(valid)) { + ANS_LOGE("Failed to write the flag which indicate whether button icon is null"); + return false; + } + if (valid) { + if (!parcel.WriteParcelable(buttonIconPixelMap_.get())) { + ANS_LOGE("Failed to write buttonIcon."); + return false; + } + } + + valid = buttonIconResource_ ? true : false; + if (!parcel.WriteBool(valid)) { + ANS_LOGE("Failed to write the flag which indicate whether button icon resource is null"); + return false; + } + if (valid) { + std::vector iconResource = {}; + iconResource.push_back(buttonIconResource_->bundleName); + iconResource.push_back(buttonIconResource_->moduleName); + iconResource.push_back(std::to_string(buttonIconResource_->id)); + if (!parcel.WriteStringVector(iconResource)) { + ANS_LOGE("Failed to write button icon resource"); + return false; + } + } + return true; +} + +bool NotificationLocalLiveViewIconButton::ReadFromParcel(Parcel &parcel) +{ + if (!parcel.ReadString(buttonName_)) { + ANS_LOGE("Failed to read button name."); + return false; + } + + bool valid {false}; + valid = parcel.ReadBool(); + if (valid) { + buttonIconPixelMap_ = std::shared_ptr(parcel.ReadParcelable()); + if (!buttonIconPixelMap_) { + ANS_LOGE("Failed to read button icon."); + return false; + } + } + + valid = parcel.ReadBool(); + if (valid) { + if (!ReadResourceFromParcel(parcel, buttonIconResource_)) { + ANS_LOGE("Failed to read button icon resource."); + return false; + } + } + + valid = parcel.ReadBool(); + if (valid) { + if (!ReadResourceFromParcel(parcel, buttonDescription_)) { + ANS_LOGE("Failed to read button description."); + return false; + } + } + + valid = parcel.ReadBool(); + if (valid) { + if (!parcel.ReadString(buttonDescriptionStr_)) { + ANS_LOGE("Failed to read button description str"); + return false; + } + } + return true; +} + +bool NotificationLocalLiveViewIconButton::ReadResourceFromParcel(Parcel &parcel, + std::shared_ptr &resourceObj) +{ + std::vector resourceInfo = {}; + if (!parcel.ReadStringVector(&resourceInfo)) { + ANS_LOGE("Failed to read resource info"); + return false; + } + if (resourceInfo.size() < BUTTON_RESOURCE_SIZE) { + ANS_LOGE("Invalid input for button icon resource"); + return false; + } + + auto resource = std::make_shared(); + resource->bundleName = resourceInfo[RESOURCE_BUNDLENAME_INDEX]; + resource->moduleName = resourceInfo[RESOURCE_MODULENAME_INDEX]; + resource->id = resourceInfo[RESOURCE_ID_INDEX]; + resourceObj = resource; + + return true; +} + +NotificationLocalLiveViewIconButton *NotificationLocalLiveViewIconButton::Unmarshalling(Parcel &parcel) +{ + NotificationLocalLiveViewIconButton *button = new (std::nothrow) NotificationLocalLiveViewIconButton(); + + if (button && !button->ReadFromParcel(parcel)) { + delete button; + button = nullptr; + } + return button; +} + +bool NotificationLocalLiveViewIconButton::ResourceFromJson(const nlohmann::json &resource, + std::shared_ptr& resourceObj) +{ + const auto &jsonEnd = resource.cend(); + int resourceCount = BUTTON_RESOURCE_SIZE; + if (resource.find("bundleName") != jsonEnd && resource.at("bundleName").is_string()) { + resourceCount--; + resourceObj->bundleName = resource.at("bundleName").get(); + } + if (resource.find("moduleName") != jsonEnd && resource.at("moduleName").is_string()) { + resourceCount--; + resourceObj->moduleName = resource.at("moduleName").get(); + } + if (resource.find("id") != jsonEnd && resource.at("id").is_number_integer()) { + resourceCount--; + resourceObj->id = resource.at("id").get(); + } + if (resourceCount == 0) { + return true; + } + ANS_LOGE("Resource from json failed."); + return false; +} + +std::string NotificationLocalLiveViewIconButton::Dump() +{ + return ""; +} + +bool NotificationLocalLiveViewIconButton::ToJson(nlohmann::json &jsonObject) const +{ + jsonObject["name"] = nlohmann::json(buttonName_); + + if (buttonIconPixelMap_) { + jsonObject["icon"] = AnsImageUtil::PackImage(buttonIconPixelMap_); + } + + if (buttonIconResource_) { + nlohmann::json resourceObj; + resourceObj["bundleName"] = buttonIconResource_->bundleName; + resourceObj["moduleName"] = buttonIconResource_->moduleName; + resourceObj["id"] = buttonIconResource_->id; + jsonObject["icon"] = resourceObj; + } + + if (buttonDescription_) { + nlohmann::json descriptionObj; + descriptionObj["bundleName"] = buttonDescription_->bundleName; + descriptionObj["moduleName"] = buttonDescription_->moduleName; + descriptionObj["id"] = buttonDescription_->id; + jsonObject["description"] = descriptionObj; + } + + if (!buttonDescriptionStr_.empty()) { + jsonObject["description"] = nlohmann::json(buttonDescriptionStr_); + } + return true; +} + +NotificationLocalLiveViewIconButton *NotificationLocalLiveViewIconButton::FromJson(const nlohmann::json &jsonObject) +{ + if (jsonObject.is_null() || !jsonObject.is_object()) { + ANS_LOGE("Invalid JSON object"); + return nullptr; + } + + auto button = new (std::nothrow) NotificationLocalLiveViewIconButton(); + if (button == nullptr) { + ANS_LOGE("Failed to create capsule instance"); + return nullptr; + } + + const auto &jsonEnd = jsonObject.cend(); + if (jsonObject.find("name") != jsonEnd && jsonObject.at("name").is_string()) { + button->buttonName_ = jsonObject.at("name").get(); + } + + if (jsonObject.find("icon") != jsonEnd) { + if (jsonObject.at("icon").is_string()) { + auto iconStr = jsonObject.at("icon").get(); + button->buttonIconPixelMap_ = AnsImageUtil::UnPackImage(iconStr); + } else if (jsonObject.at("icon").is_object()) { + auto resource = jsonObject.at("icon"); + auto resourceObj = std::make_shared(); + if (ResourceFromJson(resource, resourceObj)) { + button->buttonIconResource_ = resourceObj; + } + } + } + + if (jsonObject.find("description") != jsonEnd) { + if (jsonObject.at("description").is_object()) { + auto resource = jsonObject.at("description"); + auto resourceObj = std::make_shared(); + if (ResourceFromJson(resource, resourceObj)) { + button->buttonDescription_ = resourceObj; + } + } else if (jsonObject.at("description").is_string()) { + button->buttonDescriptionStr_ = jsonObject.at("description").get(); + } + } + return button; +} +} // namespace Notification +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/js/napi/include/common.h b/frameworks/js/napi/include/common.h index 44c38dd0f..3ebd3f815 100644 --- a/frameworks/js/napi/include/common.h +++ b/frameworks/js/napi/include/common.h @@ -21,6 +21,7 @@ #include "notification_button_option.h" #include "notification_helper.h" #include "notification_local_live_view_button.h" +#include "notification_local_live_view_icon_button.h" #include "notification_progress.h" #include "notification_time.h" #include "ans_convert_enum.h" @@ -1307,6 +1308,18 @@ public: const napi_env &env, const napi_value &contentResult, std::shared_ptr content); + /** + * @brief Gets a button of NotificationLocalLiveViewContent object from specified js object + * + * @param env Indicates the environment that the API is invoked under + * @param contentResult Indicates a js object to be converted + * @param content Indicates a button object from specified js object + * @return Returns the null object if success, returns the null value otherwise + */ + static napi_value GetNotificationLocalLiveViewIconButtons( + const napi_env &env, const napi_value &contentResult, + std::shared_ptr content); + /** * @brief Gets a time of NotificationLocalLiveViewContent object from specified js object * @@ -1343,6 +1356,38 @@ public: const napi_env &env, const napi_value &contentResult, std::shared_ptr content); + /** + * @brief Gets a NotificationLocalLiveViewIconButton object from specified js object + * + * @param env Indicates the environment that the API is invoked under + * @param contentResult Indicates a js object to be converted + * @param content Indicates a NotificationLocalLiveViewIconButton object from specified js object + * @return Returns the null object if success, returns the null value otherwise + */ + static napi_value GetNotificationLocalLiveViewIconButtonDetailed( + const napi_env &env, const napi_value &iconButton, + std::shared_ptr button); + + static napi_value GetIconButtonIconDetailed( + const napi_env &env, const napi_value &iconButton, + std::shared_ptr button); + + static napi_value GetAccessibilityDescription ( + const napi_env &env, const napi_value &iconButton, + std::shared_ptr button); + + /** + * @brief Sets a js object by specified NotificationLocalLiveViewIconButton object + * + * @param env Indicates the environment that the API is invoked under + * @param capsule Indicates a NotificationLocalLiveViewIconButton object to be converted + * @param result Indicates a js object to be set + * @return Returns the null object if success, returns the null value otherwise + */ + static napi_value SetIconButton( + const napi_env &env, + const std::shared_ptr &iconButton, napi_value &result); + /** * @brief Gets a conversational content of NotificationRequest object from specified js object * diff --git a/frameworks/js/napi/src/common_convert_liveview.cpp b/frameworks/js/napi/src/common_convert_liveview.cpp index 167e82a82..ca338afe5 100644 --- a/frameworks/js/napi/src/common_convert_liveview.cpp +++ b/frameworks/js/napi/src/common_convert_liveview.cpp @@ -67,15 +67,33 @@ napi_value Common::SetNotificationLocalLiveViewContent( napi_set_named_property(env, result, "capsule", capsule); } - // button: NotificationLocalLiveViewButton - if (localLiveViewContent->isFlagExist(NotificationLocalLiveViewContent::LiveViewContentInner::BUTTON)) { - napi_value button = nullptr; - napi_create_object(env, &button); - if (!SetButton(env, localLiveViewContent->GetButton(), button)) { - ANS_LOGE("SetButton call failed"); - return NapiGetBoolean(env, false); + // iconButtons?: Array + napi_value arr = nullptr; + uint32_t count = 0; + napi_create_array(env, &arr); + for (auto button : localLiveViewContent->GetIconButtons()) { + if (button) { + napi_value iconButtonResult = nullptr; + napi_create_object(env, &iconButtonResult); + if (SetIconButton(env, button, iconButtonResult)) { + napi_set_element(env, arr, count, iconButtonResult); + count++; + } + } + } + if (count != 0) { + napi_set_named_property(env, result, "iconButtons", arr); + } else { + // button: NotificationLocalLiveViewButton + if (localLiveViewContent->isFlagExist(NotificationLocalLiveViewContent::LiveViewContentInner::BUTTON)) { + napi_value button = nullptr; + napi_create_object(env, &button); + if (!SetButton(env, localLiveViewContent->GetButton(), button)) { + ANS_LOGE("SetButton call failed"); + return NapiGetBoolean(env, false); + } + napi_set_named_property(env, result, "button", button); } - napi_set_named_property(env, result, "button", button); } // progress: NotificationProgress @@ -239,6 +257,71 @@ napi_value Common::SetResourceObject(napi_env env, std::shared_ptr &iconButton, napi_value &result) +{ + ANS_LOGD("enter"); + + napi_value value = nullptr; + + // name: String + napi_create_string_utf8(env, iconButton->GetButtonName().c_str(), NAPI_AUTO_LENGTH, &value); + napi_set_named_property(env, result, "name", value); + + // Icon: PixelMap + std::shared_ptr icon = iconButton->GetButtonIcon(); + if (icon) { + napi_value iconResult = nullptr; + napi_valuetype valuetype = napi_undefined; + iconResult = Media::PixelMapNapi::CreatePixelMap(env, icon); + NAPI_CALL(env, napi_typeof(env, iconResult, &valuetype)); + if (valuetype == napi_undefined) { + ANS_LOGW("icon result is undefined"); + napi_set_named_property(env, result, "icon", NapiGetNull(env)); + } else { + napi_set_named_property(env, result, "icon", iconResult); + } + } + + // icon: Resource + auto iconResource = iconButton->GetButtonIconResource(); + if (iconResource) { + napi_value object; + napi_status status = napi_create_object(env, &object); + if (status != napi_ok) { + ANS_LOGE("Failed to create Configuration object"); + return NapiGetBoolean(env, false); + } + if (!SetResourceObject(env, iconResource, object)) { + return NapiGetBoolean(env, false); + } + napi_set_named_property(env, result, "icon", object); + } + + // description: Resource + auto description = iconButton->GetButtonDescription(); + if (description) { + napi_value object; + napi_status status = napi_create_object(env, &object); + if (status != napi_ok) { + ANS_LOGE("Failed to create Configuration object"); + return NapiGetBoolean(env, false); + } + if (!SetResourceObject(env, description, object)) { + return NapiGetBoolean(env, false); + } + napi_set_named_property(env, result, "accessibilityDescription", object); + } + + // description:string + if (!iconButton->GetButtonDescriptionStr().empty()) { + napi_create_string_utf8(env, iconButton->GetButtonDescriptionStr().c_str(), NAPI_AUTO_LENGTH, &value); + napi_set_named_property(env, result, "accessibilityDescription", value); + } + + return NapiGetBoolean(env, true); +} + napi_value Common::SetButton(const napi_env &env, const NotificationLocalLiveViewButton &button, napi_value &result) { ANS_LOGD("enter"); @@ -668,6 +751,156 @@ napi_value Common::GetNotificationLocalLiveViewButton( return NapiGetNull(env); } +napi_value Common::GetNotificationLocalLiveViewIconButtons( + const napi_env &env, const napi_value &contentResult, + std::shared_ptr content) +{ + ANS_LOGD("enter"); + + bool isArray = false; + napi_valuetype valuetype = napi_undefined; + napi_value iconButtons = nullptr; + uint32_t length = 0; + + napi_get_named_property(env, contentResult, "iconButtons", &iconButtons); + napi_is_array(env, iconButtons, &isArray); + if (!isArray) { + ANS_LOGE("Property iconButtons is expected to be an array."); + return nullptr; + } + napi_get_array_length(env, iconButtons, &length); + if (length == 0) { + ANS_LOGI("The array is empty."); + return Common::NapiGetNull(env); + } + for (size_t i = 0; i < length; i++) { + napi_value iconButton = nullptr; + napi_get_element(env, iconButtons, i, &iconButton); + NAPI_CALL(env, napi_typeof(env, iconButton, &valuetype)); + if (valuetype != napi_object) { + ANS_LOGE("Wrong argument type. Object expected."); + return nullptr; + } + + auto button = std::make_shared(); + if (GetNotificationLocalLiveViewIconButtonDetailed(env, iconButton, button) == nullptr) { + return nullptr; + } + content->AddIconButton(button); + } + content->addFlag(NotificationLocalLiveViewContent::LiveViewContentInner::BUTTON); + return NapiGetNull(env); +} + +napi_value Common::GetNotificationLocalLiveViewIconButtonDetailed( + const napi_env &env, const napi_value &iconButton, + std::shared_ptr button) +{ + ANS_LOGD("enter"); + napi_valuetype valuetype = napi_undefined; + bool hasProperty = false; + char str[STR_MAX_SIZE] = {0}; + size_t strLen = 0; + + // name: string + NAPI_CALL(env, napi_has_named_property(env, iconButton, "name", &hasProperty)); + if (hasProperty) { + napi_value buttonName = nullptr; + napi_get_named_property(env, iconButton, "name", &buttonName); + NAPI_CALL(env, napi_typeof(env, buttonName, &valuetype)); + if (valuetype != napi_string) { + ANS_LOGE("Wrong argument type. String expected."); + return nullptr; + } + NAPI_CALL(env, napi_get_value_string_utf8(env, buttonName, str, STR_MAX_SIZE - 1, &strLen)); + button->SetButtonName(str); + } + + // icon + if (GetIconButtonIconDetailed(env, iconButton, button) == nullptr) { + return nullptr; + } + + // accessibilityDescription + if (GetAccessibilityDescription(env, iconButton, button) == nullptr) { + return nullptr; + } + return NapiGetNull(env); +} + +napi_value Common::GetIconButtonIconDetailed( + const napi_env &env, const napi_value &iconButton, + std::shared_ptr button) +{ + bool hasProperty = false; + napi_valuetype valuetype = napi_undefined; + std::shared_ptr pixelMap = nullptr; + NAPI_CALL(env, napi_has_named_property(env, iconButton, "icon", &hasProperty)); + if (hasProperty) { + napi_value buttonIcon = nullptr; + napi_get_named_property(env, iconButton, "icon", &buttonIcon); + NAPI_CALL(env, napi_typeof(env, buttonIcon, &valuetype)); + if (valuetype != napi_object) { + ANS_LOGE("Wrong argument type. Object expected."); + return nullptr; + } + // Check icon is image.PixelMap or Resource + // icon?: Resource + auto resource = std::make_shared(); + if (Common::GetResourceObject(env, resource, buttonIcon) == nullptr) { + ANS_LOGW("Invalid icon resource object or not resource."); + } else { + button->SetButtonIconResource(resource); + ANS_LOGI("icon resource object is valid."); + return NapiGetNull(env); + } + // icon?: image.PixelMap + pixelMap = Media::PixelMapNapi::GetPixelMap(env, buttonIcon); + if (pixelMap != nullptr && static_cast(pixelMap->GetByteCount()) <= MAX_ICON_SIZE) { + button->SetButtonIcon(pixelMap); + ANS_LOGI("icon pixelMap = %{public}d", pixelMap->GetWidth()); + } else { + ANS_LOGE("Invalid pixelMap object or pixelMap is over size."); + return nullptr; + } + } + return NapiGetNull(env); +} + +napi_value Common::GetAccessibilityDescription ( + const napi_env &env, const napi_value &iconButton, + std::shared_ptr button) +{ + ANS_LOGD("enter"); + napi_valuetype valuetype = napi_undefined; + bool hasProperty = false; + char str[STR_MAX_SIZE] = {0}; + size_t strLen = 0; + // accessibilityDescription + NAPI_CALL(env, napi_has_named_property(env, iconButton, "accessibilityDescription", &hasProperty)); + if (hasProperty) { + napi_value description = nullptr; + auto descriptionResource = std::make_shared(); + napi_get_named_property(env, iconButton, "accessibilityDescription", &description); + NAPI_CALL(env, napi_typeof(env, description, &valuetype)); + if (valuetype == napi_string) { + NAPI_CALL(env, napi_get_value_string_utf8(env, description, str, STR_MAX_SIZE - 1, &strLen)); + button->SetButtonDescriptionStr(str); + } else if (valuetype == napi_object) { + if (Common::GetResourceObject(env, descriptionResource, description) == nullptr) { + ANS_LOGW("Invalid icon resource object."); + return nullptr; + } else { + button->SetButtonDescription(descriptionResource); + } + } else { + ANS_LOGE("Wrong argument type. Object or string expected."); + return nullptr; + } + } + return NapiGetNull(env); +} + napi_value Common::GetNotificationLocalLiveViewProgress(const napi_env &env, const napi_value &contentResult, std::shared_ptr content) { @@ -859,6 +1092,12 @@ napi_value Common::GetNotificationLocalLiveViewContentDetailed( return nullptr; } + //iconButtons + NAPI_CALL(env, napi_has_named_property(env, contentResult, "iconButtons", &hasProperty)); + if (hasProperty && GetNotificationLocalLiveViewIconButtons(env, contentResult, content) == nullptr) { + return nullptr; + } + //progress? NAPI_CALL(env, napi_has_named_property(env, contentResult, "progress", &hasProperty)); if (hasProperty && GetNotificationLocalLiveViewProgress(env, contentResult, content) == nullptr) { diff --git a/interfaces/inner_api/notification_local_live_view_content.h b/interfaces/inner_api/notification_local_live_view_content.h index 6792ac58e..69bbe2063 100644 --- a/interfaces/inner_api/notification_local_live_view_content.h +++ b/interfaces/inner_api/notification_local_live_view_content.h @@ -19,6 +19,7 @@ #include "notification_capsule.h" #include "notification_progress.h" #include "notification_local_live_view_button.h" +#include "notification_local_live_view_icon_button.h" #include "message_user.h" #include "notification_basic_content.h" #include "notification_conversational_message.h" @@ -81,6 +82,23 @@ public: */ NotificationLocalLiveViewButton GetButton(); + /* + * @brief Adds the icon button to be included in a local live view notification. + * + * @param button Indicates the type to be included. + */ + void AddIconButton(const std::shared_ptr &iconButton); + + /* + * @brief Sets the button to be included in a local live view notification. + * + * @param button Indicates the type to be included. + */ + const std::vector> GetIconButtons() const; + + static bool ConvertJsonToNotificationIconButton( + NotificationLocalLiveViewContent *target, const nlohmann::json &jsonObject); + /* * @brief Sets the progress to be included in a local live view notification. * @@ -172,11 +190,24 @@ protected: * @return Returns true if succeed; returns false otherwise. */ bool ReadFromParcel(Parcel &parcel) override; + + /** + * @brief Read IconButtons from a Parcel. + * + * @param parcel Indicates the parcel object. + * @return Returns true if succeed; returns false otherwise. + */ + bool ReadIconButtonsFromParcel(Parcel &parcel); private: + /** + * the maximum number of icon buttons is 3. + */ + static const std::size_t MAX_ICON_BUTTONS; int32_t type_ {0}; NotificationCapsule capsule_ {}; NotificationLocalLiveViewButton button_ {}; + std::vector> iconButtons_ {}; NotificationProgress progress_ {}; NotificationTime time_ {}; std::vector flags_ {}; diff --git a/interfaces/inner_api/notification_local_live_view_icon_button.h b/interfaces/inner_api/notification_local_live_view_icon_button.h new file mode 100644 index 000000000..028234394 --- /dev/null +++ b/interfaces/inner_api/notification_local_live_view_icon_button.h @@ -0,0 +1,170 @@ +/* + +Copyright (c) 2021 Huawei Device Co., Ltd. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +#ifndef BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_INTERFACES_INNER_API_LOCAL_LIVE_VIEW_ICON_BUTTON_H +#define BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_INTERFACES_INNER_API_LOCAL_LIVE_VIEW_ICON_BUTTON_H + +#include "pixel_map.h" +#include "message_user.h" +#include "notification_json_convert.h" +#include "parcel.h" +#include "resource_manager.h" + +namespace OHOS { +namespace Notification { +using namespace Global::Resource; + +class NotificationLocalLiveViewIconButton : public Parcelable, public NotificationJsonConvertionBase { +public: + NotificationLocalLiveViewIconButton() = default; + ~NotificationLocalLiveViewIconButton() = default; + + /** + * @brief Sets the button name of this NotificationlocalLiveViewIconButton. + * + * @param parcel Indicates the buttonname to add. + */ + void SetButtonName(const std::string &buttonName); + + /** + * @brief Obtains the button name of this NotificationLocalLiveViewIconButton. + * + * @return Returns the button name of this NotificationLocalLiveViewIconButton. + */ + std::string GetButtonName() const; + + /** + * @brief Sets the button icon of this NotificationlocalLiveViewIconButton. + * + * @param parcel Indicates the button icon to add. + */ + void SetButtonIcon(std::shared_ptr &buttonIcon); + + /** + * @brief Obtains the button icon of this NotificationLocalLiveViewIconButton. + * + * @return Returns the button icon of this NotificationLocalLiveViewIconButton. + */ + std::shared_ptr GetButtonIcon() const; + + /** + * @brief Set the button icon ReSource of this NotificationlocalLiveViewIconButton. + * + * @param parcel Indicates the button icon Resouce to add. + */ + void SetButtonIconResource(std::shared_ptr &buttonIconResource); + + /** + * @brief Obtains the button icon resource of this NotificationLocalLiveViewIconButton. + * + * @return Returns the button icon resource of this NotificationLocalLiveViewIconButton. + */ + std::shared_ptr GetButtonIconResource() const; + + /** + * @brief Set the button description resource of this NotificationlocalLiveViewIconButton. + * + * @param parcel Indicates the button description resouce to add. + */ + void SetButtonDescription(std::shared_ptr &buttonDescription); + + /** + * @brief Obtains the button description resouce of this NotificationLocalLiveViewIconButton. + * + * @return Returns the button description resouce of this NotificationLocalLiveViewIconButton. + */ + std::shared_ptr GetButtonDescription() const; + + /** + * @brief Set the button description string of this NotificationlocalLiveViewIconButton. + * + * @param parcel Indicates the button description string to add. + */ + void SetButtonDescriptionStr(const std::string &buttonDescriptionStr); + + /** + * @brief Obtains the button description string of this NotificationLocalLiveViewIconButton. + * + * @return Returns the button description string of this NotificationLocalLiveViewIconButton. + */ + std::string GetButtonDescriptionStr() const; + + /** + * @brief Marshal a object into a Parcel. + * + * @param parcel Indicates the object into the parcel. + * @return Returns true if succeed; returns false otherwise. + */ + virtual bool Marshalling(Parcel &parcel) const override; + + /** + * @brief Marshal a icon into a Parcel. + * + * @param parcel Indicates the object into the parcel. + * @return Returns true if succeed; returns false otherwise. + */ + bool WriteIconToParcel(Parcel &parcel) const; + + /** + * @brief Unmarshal object from a Parcel. + * + * @param parcel Indicates the parcel object. + * @return Returns the NotificationConversationalMessage. + */ + static NotificationLocalLiveViewIconButton *Unmarshalling(Parcel &parcel); + + /** + * @brief Returns a string representation of the object. + * + * @return Returns a string representation of the object. + */ + std::string Dump(); + + /** + * @brief Converts a NotificationLocalLiveViewIconButton object into a Json. + * + * @param jsonObject Indicates the Json object. + * @return Returns true if succeed; returns false otherwise. + */ + bool ToJson(nlohmann::json &jsonObject) const override; + + /** + * @brief Creates a NotificationLocalLiveViewIconButton object from a Json. + * + * @param jsonObject Indicates the Json object. + * @return Returns the NotificationLocalLiveViewIconButton. + */ + static NotificationLocalLiveViewIconButton *FromJson(const nlohmann::json &jsonObject); +private: + /** + * @brief Read a NotificationConversationalMessage object from a Parcel. + * + * @param parcel Indicates the parcel object. + * @return Returns true if succeed; returns false otherwise. + */ + bool ReadFromParcel(Parcel &parcel); + static bool ResourceFromJson(const nlohmann::json &resource, + std::shared_ptr& resourceObj); + static bool ReadResourceFromParcel(Parcel &parcel, + std::shared_ptr& resourceObj); + + std::string buttonName_ {}; + std::shared_ptr buttonIconResource_ {}; + std::shared_ptr buttonIconPixelMap_ {}; + std::shared_ptr buttonDescription_ {}; + std::string buttonDescriptionStr_ {}; +}; +} // namespace Notification +} // namespace OHOS + +#endif //BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_INTERFACES_INNER_API_LOCAL_LIVE_VIEW_ICON_BUTTON_H \ No newline at end of file -- Gitee