diff --git a/frameworks/ans/BUILD.gn b/frameworks/ans/BUILD.gn index fc05615d17019fe9f9f68f9d9828d9405f6bafde..822e942a14714afc06013ea21210b419470f57ed 100644 --- a/frameworks/ans/BUILD.gn +++ b/frameworks/ans/BUILD.gn @@ -88,6 +88,7 @@ ohos_shared_library("ans_innerkits") { "${frameworks_module_ans_path}/src/notification_do_not_disturb_profile.cpp", "${frameworks_module_ans_path}/src/notification_flags.cpp", "${frameworks_module_ans_path}/src/notification_helper.cpp", + "${frameworks_module_ans_path}/src/notification_icon_button.cpp", "${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", diff --git a/frameworks/ans/src/notification_capsule.cpp b/frameworks/ans/src/notification_capsule.cpp index a1be9fcc45499ad3b05e6677a8a0bf04c7a1a065..caf02024c94f2d2772106d024b9bed2264325b17 100644 --- a/frameworks/ans/src/notification_capsule.cpp +++ b/frameworks/ans/src/notification_capsule.cpp @@ -68,6 +68,26 @@ std::string NotificationCapsule::GetContent() const return content_; } +std::vector NotificationCapsule::GetCapsuleButton() const +{ + return capsuleButton_; +} + +void NotificationCapsule::SetCapsuleButton(const std::vector &buttons) +{ + capsuleButton_ = buttons; +} + +int32_t NotificationCapsule::GetTime() const +{ + return time_; +} + +void NotificationCapsule::SetTime(int32_t time) +{ + time_ = time; +} + std::string NotificationCapsule::Dump() { return "Capsule{ " @@ -75,6 +95,7 @@ std::string NotificationCapsule::Dump() ", backgroundColor = " + backgroundColor_ + ", content = " + content_ + ", icon = " + (icon_ ? "not null" : "null") + + ", time = " + std::to_string(time_) + " }"; } @@ -85,6 +106,18 @@ bool NotificationCapsule::ToJson(nlohmann::json &jsonObject) const jsonObject["content"] = content_; jsonObject["icon"] = AnsImageUtil::PackImage(icon_); + jsonObject["time"] = time_; + nlohmann::json capsuleBtnArr = nlohmann::json::array(); + for (auto btn : capsuleButton_) { + nlohmann::json capsuleBtnObj; + if (!NotificationJsonConverter::ConvertToJson(&btn, capsuleBtnObj)) { + ANS_LOGE("Cannot convert button to JSON"); + return false; + } + capsuleBtnArr.emplace_back(capsuleBtnObj); + } + jsonObject["capsuleButton"] = capsuleBtnArr; + return true; } @@ -119,6 +152,24 @@ NotificationCapsule *NotificationCapsule::FromJson(const nlohmann::json &jsonObj capsule->icon_ = AnsImageUtil::UnPackImage(pmStr); } + if (jsonObject.find("time") != jsonEnd && jsonObject.at("time").is_number_integer()) { + capsule->time_ = jsonObject.at("time").get(); + } + + if (jsonObject.find("capsuleButton") != jsonEnd && jsonObject.at("capsuleButton").is_array()) { + std::vector cardButtons; + for (auto &item : jsonObject.at("capsuleButton").items()) { + nlohmann::json cardBtnObject = item.value(); + auto pButton = NotificationJsonConverter::ConvertFromJson(cardBtnObject); + if (pButton != nullptr) { + cardButtons.push_back(*pButton); + delete pButton; + pButton = nullptr; + } + } + capsule->capsuleButton_ = cardButtons; + } + return capsule; } @@ -152,6 +203,32 @@ bool NotificationCapsule::Marshalling(Parcel &parcel) const } } + if (!parcel.WriteInt32(time_)) { + ANS_LOGE("Write time_ fail."); + return false; + } + + parcel.WriteInt32(static_cast(capsuleButton_.size())); + for (const auto& button : capsuleButton_) { + if (!parcel.WriteParcelable(&button)) { + ANS_LOGE("Failed to write card button"); + return false; + } + } + + if (!parcel.WriteInt32(time_)) { + ANS_LOGE("Write time_ fail."); + return false; + } + + parcel.WriteInt32(static_cast(capsuleButton_.size())); + for (const auto& button : capsuleButton_) { + if (!parcel.WriteParcelable(&button)) { + ANS_LOGE("Failed to write card button"); + return false; + } + } + return true; } @@ -170,6 +247,25 @@ bool NotificationCapsule::ReadFromParcel(Parcel &parcel) } } + if (!parcel.ReadInt32(time_)) { + ANS_LOGE("Read time_ failed."); + return false; + } + + auto vsize = parcel.ReadInt32(); + vsize = (vsize < BUTTON_MAX_SIZE) ? vsize : BUTTON_MAX_SIZE; + capsuleButton_.clear(); + for (int i = 0; i < vsize; ++i) { + auto btn = parcel.ReadParcelable(); + if (btn == nullptr) { + ANS_LOGE("Failed to read card button"); + return false; + } + capsuleButton_.push_back(*btn); + delete btn; + btn = nullptr; + } + return true; } diff --git a/frameworks/ans/src/notification_icon_button.cpp b/frameworks/ans/src/notification_icon_button.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cfff83497dd89516db982ab5a93e8ea9e353a31b --- /dev/null +++ b/frameworks/ans/src/notification_icon_button.cpp @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2024 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_icon_button.h" + +#include // for basic_string, operator+, basic_string<>... +#include // for shared_ptr, shared_ptr<>::element_type +#include + + +#include "ans_image_util.h" +#include "ans_log_wrapper.h" +#include "nlohmann/json.hpp" // for json, basic_json<>::object_t, basic_json +#include "parcel.h" // for Parcel + +namespace OHOS { +namespace Notification { +using ResourceVectorPtr = std::vector>; + +const std::shared_ptr NotificationIconButton::GetIconResource() const +{ + return iconResource_; +} + +void NotificationIconButton::SetIconResource(const std::shared_ptr &iconResource) +{ + iconResource_ = iconResource; +} + + +std::string NotificationIconButton::GetText() const +{ + return text_; +} + +void NotificationIconButton::SetText(const std::string &text) +{ + text_ = text; +} + +std::string NotificationIconButton::GetName() const +{ + return name_; +} + +void NotificationIconButton::SetName(const std::string &name) +{ + name_ = name; +} + +bool NotificationIconButton::GetHidePanel() const +{ + return hidePanel_; +} + +void NotificationIconButton::SetHidePanel(bool hidePanel) +{ + hidePanel_ = hidePanel; +} + +void NotificationIconButton::ClearButtonIconsResource() +{ +} + +std::string NotificationIconButton::Dump() +{ + return "NotificationIconButton {" + "name = " + name_ + + ", text = " + text_ + + ", hidePanel = " + std::to_string(hidePanel_) + + " }"; +} + +bool NotificationIconButton::ToJson(nlohmann::json &jsonObject) const +{ + jsonObject["text"] = text_; + jsonObject["name"] = name_; + jsonObject["hidePanel"] = hidePanel_; + + nlohmann::json resourceObj; + resourceObj["id"] = iconResource_->id; + resourceObj["bundleName"] = iconResource_->bundleName; + resourceObj["moduleName"] = iconResource_->moduleName; + jsonObject["iconResource"] = resourceObj; + return true; +} + +NotificationIconButton *NotificationIconButton::FromJson(const nlohmann::json &jsonObject) +{ + if (jsonObject.is_null() or !jsonObject.is_object()) { + ANS_LOGE("Invalid JSON object"); + return nullptr; + } + + auto *button = new (std::nothrow) NotificationIconButton(); + if (button == nullptr) { + ANS_LOGE("Failed to create icon button"); + return nullptr; + } + + const auto &jsonEnd = jsonObject.cend(); + if (jsonObject.find("text") != jsonEnd && jsonObject.at("text").is_string()) { + button->SetText(jsonObject.at("text").get()); + } + + if (jsonObject.find("name") != jsonEnd && jsonObject.at("name").is_string()) { + button->SetName(jsonObject.at("name").get()); + } + + if (jsonObject.find("hidePanel") != jsonEnd && jsonObject.at("hidePanel").is_boolean()) { + button->SetHidePanel(jsonObject.at("hidePanel").get()); + } + + if (jsonObject.find("iconResource") != jsonEnd) { + auto resources = jsonObject.at("iconResource"); + auto resourceObj = std::make_shared(); + if (ResourceFromJson(resources, resourceObj)) { + button->SetIconResource(resourceObj); + } + } + return button; +} + +bool NotificationIconButton::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; +} + +bool NotificationIconButton::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteString(text_)) { + ANS_LOGE("Failed to write text"); + return false; + } + + if (!parcel.WriteString(name_)) { + ANS_LOGE("Failed to write name"); + return false; + } + + if (!parcel.WriteBool(hidePanel_)) { + ANS_LOGE("Failed to write hidePanel"); + return false; + } + + std::vector iconsResource = {}; + iconsResource.push_back(iconResource_->bundleName); + iconsResource.push_back(iconResource_->moduleName); + iconsResource.push_back(std::to_string(iconResource_->id)); + if (!parcel.WriteStringVector(iconsResource)) { + ANS_LOGE("Failed to write button icon resource"); + return false; + } + return true; +} + +NotificationIconButton *NotificationIconButton::Unmarshalling(Parcel &parcel) +{ + NotificationIconButton *button = new (std::nothrow) NotificationIconButton(); + + if (button && !button->ReadFromParcel(parcel)) { + delete button; + button = nullptr; + } + return button; +} + +bool NotificationIconButton::ReadFromParcel(Parcel &parcel) +{ + if (!parcel.ReadString(text_)) { + ANS_LOGE("Failed to read text"); + return false; + } + + if (!parcel.ReadString(name_)) { + ANS_LOGE("Failed to read name"); + return false; + } + + if (!parcel.ReadBool(hidePanel_)) { + ANS_LOGE("Failed to read hidePanel"); + return false; + } + + std::vector iconsResource; + if (!parcel.ReadStringVector(&iconsResource)) { + ANS_LOGE("Failed to read button names"); + return false; + } + if (iconsResource.size() < BUTTON_RESOURCE_SIZE) { + ANS_LOGE("Invalid input for button icons resource"); + return false; + } + auto resource = std::make_shared(); + resource->bundleName = iconsResource[RESOURCE_BUNDLENAME_INDEX]; + resource->moduleName = iconsResource[RESOURCE_MODULENAME_INDEX]; + std::stringstream sin(iconsResource[RESOURCE_ID_INDEX]); + int32_t checknum; + if (!(sin >> checknum)) { + ANS_LOGE("Invalid input for button icons resource"); + return false; + } + resource->id = std::stoi(iconsResource[RESOURCE_ID_INDEX]); + iconResource_ = resource; + + return true; +} +} +} \ No newline at end of file diff --git a/frameworks/ans/src/notification_local_live_view_content.cpp b/frameworks/ans/src/notification_local_live_view_content.cpp index 697fa5026d5b5b59f4c8c4d8a83cbe06c3f1052b..e2686c159fe2ff8b274b37c96ab898888d2069d1 100644 --- a/frameworks/ans/src/notification_local_live_view_content.cpp +++ b/frameworks/ans/src/notification_local_live_view_content.cpp @@ -65,6 +65,16 @@ NotificationLocalLiveViewButton NotificationLocalLiveViewContent::GetButton() return button_; } +void NotificationLocalLiveViewContent::SetCardButton(std::vector buttons) +{ + card_button_ = buttons; +} + +std::vector NotificationLocalLiveViewContent::GetCardButton() +{ + return card_button_; +} + void NotificationLocalLiveViewContent::SetProgress(NotificationProgress progress) { progress_ = progress; @@ -100,6 +110,16 @@ bool NotificationLocalLiveViewContent::isFlagExist(int32_t flag) } } +void NotificationLocalLiveViewContent::SetLiveviewType(int32_t type) +{ + liveviewType_ = type; +} + +int32_t NotificationLocalLiveViewContent::GetLiveviewType() +{ + return liveviewType_; +} + std::string NotificationLocalLiveViewContent::Dump() { return "NotificationLocalLiveViewContent{ " + NotificationBasicContent::Dump() + @@ -108,6 +128,7 @@ std::string NotificationLocalLiveViewContent::Dump() ", button = " + button_.Dump() + ", progress = " + progress_.Dump() + ", time = " + time_.Dump() + + ", liveviewType = " + std::to_string(liveviewType_) + " }"; } @@ -142,12 +163,24 @@ bool NotificationLocalLiveViewContent::ToJson(nlohmann::json &jsonObject) const return false; } + nlohmann::json cardBtnArr = nlohmann::json::array(); + for (auto btn : card_button_) { + nlohmann::json cardBtnObj; + if (!NotificationJsonConverter::ConvertToJson(&btn, cardBtnObj)) { + ANS_LOGE("Cannot convert button to JSON"); + return false; + } + cardBtnArr.emplace_back(cardBtnObj); + } + jsonObject["type"] = type_; jsonObject["capsule"] = capsuleObj; jsonObject["button"] = buttonObj; + jsonObject["cardButton"] = cardBtnArr; jsonObject["progress"] = progressObj; jsonObject["time"] = timeObj; jsonObject["flags"] = nlohmann::json(flags_); + jsonObject["liveviewType"] = liveviewType_; return true; } @@ -192,6 +225,20 @@ NotificationLocalLiveViewContent *NotificationLocalLiveViewContent::FromJson(con } } + if (jsonObject.find("cardButton") != jsonEnd && jsonObject.at("cardButton").is_array()) { + std::vector cardButtons; + for (auto &item : jsonObject.at("cardButton").items()) { + nlohmann::json cardBtnObject = item.value(); + auto pButton = NotificationJsonConverter::ConvertFromJson(cardBtnObject); + if (pButton != nullptr) { + cardButtons.push_back(*pButton); + delete pButton; + pButton = nullptr; + } + } + pContent->card_button_ = cardButtons; + } + if (jsonObject.find("progress") != jsonEnd) { auto progressObj = jsonObject.at("progress"); auto pProgress = NotificationJsonConverter::ConvertFromJson(progressObj); @@ -216,6 +263,10 @@ NotificationLocalLiveViewContent *NotificationLocalLiveViewContent::FromJson(con pContent->flags_ = jsonObject.at("flags").get>(); } + if (jsonObject.find("liveviewType") != jsonEnd && jsonObject.at("liveviewType").is_number_integer()) { + pContent->liveviewType_ = jsonObject.at("liveviewType").get(); + } + return pContent; } @@ -245,6 +296,14 @@ bool NotificationLocalLiveViewContent::Marshalling(Parcel &parcel) const return false; } + parcel.WriteInt32(static_cast(card_button_.size())); + for (const auto& button : card_button_) { + if (!parcel.WriteParcelable(&button)) { + ANS_LOGE("Failed to write card button"); + return false; + } + } + if (!parcel.WriteParcelable(&progress_)) { ANS_LOGE("Failed to write progress"); return false; @@ -260,6 +319,11 @@ bool NotificationLocalLiveViewContent::Marshalling(Parcel &parcel) const return false; } + if (!parcel.WriteInt32(liveviewType_)) { + ANS_LOGE("Write liveviewType fail."); + return false; + } + return true; } @@ -304,6 +368,20 @@ bool NotificationLocalLiveViewContent::ReadFromParcel(Parcel &parcel) delete pButton; pButton = nullptr; + auto vsize = parcel.ReadInt32(); + vsize = (vsize < BUTTON_MAX_SIZE) ? vsize : BUTTON_MAX_SIZE; + card_button_.clear(); + for (int i = 0; i < vsize; ++i) { + auto btn = parcel.ReadParcelable(); + if (btn == nullptr) { + ANS_LOGE("Failed to read card button"); + return false; + } + card_button_.push_back(*btn); + delete btn; + btn = nullptr; + } + auto pProgress = parcel.ReadParcelable(); if (pProgress == nullptr) { ANS_LOGE("Failed to read progress"); @@ -327,6 +405,11 @@ bool NotificationLocalLiveViewContent::ReadFromParcel(Parcel &parcel) return false; } + if (!parcel.ReadInt32(liveviewType_)) { + ANS_LOGE("Read liveviewType_ failed."); + return false; + } + return true; } diff --git a/frameworks/ans/test/unittest/BUILD.gn b/frameworks/ans/test/unittest/BUILD.gn index 172b7f032b3d26858842a9c29bb0372ff806bd5b..e7edf8060b0801e449261f3f15f6eb1767eebbc9 100644 --- a/frameworks/ans/test/unittest/BUILD.gn +++ b/frameworks/ans/test/unittest/BUILD.gn @@ -45,6 +45,7 @@ ohos_unittest("ans_test") { "${frameworks_module_ans_path}/test/unittest/notification_do_not_disturb_profile_test.cpp", "${frameworks_module_ans_path}/test/unittest/notification_flags_test.cpp", "${frameworks_module_ans_path}/test/unittest/notification_helper_test.cpp", + "${frameworks_module_ans_path}/test/unittest/notification_icon_button_test.cpp", "${frameworks_module_ans_path}/test/unittest/notification_live_view_content_test.cpp", "${frameworks_module_ans_path}/test/unittest/notification_local_live_view_button_test.cpp", "${frameworks_module_ans_path}/test/unittest/notification_local_live_view_content_test.cpp", diff --git a/frameworks/ans/test/unittest/notification_icon_button_test.cpp b/frameworks/ans/test/unittest/notification_icon_button_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..47219fb79d1b5b0c18c3192efe00fce74b4ec044 --- /dev/null +++ b/frameworks/ans/test/unittest/notification_icon_button_test.cpp @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2022 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 +#include +#include +#include "notification_icon_button.h" +#include "ans_image_util.h" + +using namespace testing::ext; +namespace OHOS { +namespace Notification { +class NotificationIconButtonTest : public testing::Test { +public: + static void SetUpTestCase() {} + static void TearDownTestCase() {} + void SetUp() {} + void TearDown() {} +}; + +/** + * @tc.name: ToJson_00001 + * @tc.desc: Test ToJson parameters. + * @tc.type: FUNC + * @tc.require: issueI5WBBH + */ +HWTEST_F(NotificationIconButtonTest, ToJson_00001, Function | SmallTest | Level1) +{ + nlohmann::json jsonObject; + auto rrc = std::make_shared(); + rrc->FromJson(jsonObject); + EXPECT_EQ(rrc->ToJson(jsonObject), true); +} + +/** + * @tc.name: FromJson_00001 + * @tc.desc: Test FromJson parameters. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(NotificationIconButtonTest, FromJson_00001, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + nlohmann::json jsonObject = nlohmann::json{"testjson"}; + EXPECT_EQ(jsonObject.is_object(), false); + EXPECT_EQ(rrc->FromJson(jsonObject), nullptr); +} + +/** + * @tc.name: FromJson_00002 + * @tc.desc: Test FromJson parameters. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(NotificationIconButtonTest, FromJson_00002, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + nlohmann::json jsonObject = nlohmann::json{{"names", {"test"}}, {"icons", {}}}; + EXPECT_EQ(jsonObject.is_object(), true); + EXPECT_NE(rrc->FromJson(jsonObject), nullptr); +} + +/** + * @tc.name: FromJson_00003 + * @tc.desc: Test FromJson parameters. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(NotificationIconButtonTest, FromJson_00003, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + nlohmann::json jsonObject = nlohmann::json{{"names", {"test"}}, {"icons", {1, "testIcons"}}}; + EXPECT_EQ(jsonObject.is_object(), true); + EXPECT_EQ(rrc->FromJson(jsonObject), nullptr); +} + +/** + * @tc.name: Marshalling_00002 + * @tc.desc: Test Marshalling parameters. + * @tc.type: FUNC + * @tc.require: issueI5WBBH + */ +HWTEST_F(NotificationIconButtonTest, Marshalling_00002, Function | SmallTest | Level1) +{ + Parcel parcel; + auto button = std::make_shared(); + button->SetText("test"); + EXPECT_EQ(button->Marshalling(parcel), true); +} + +/** + * @tc.name: Marshalling_00001 + * @tc.desc: Test Marshalling parameters. + * @tc.type: FUNC + * @tc.require: issueI5WBBH + */ +HWTEST_F(NotificationIconButtonTest, Marshalling_00001, Function | SmallTest | Level1) +{ + Parcel parcel; + auto rrc = std::make_shared(); + EXPECT_EQ(rrc->Marshalling(parcel), true); +} + +/** + * @tc.name: Unmarshalling_00001 + * @tc.desc: Test Unmarshalling parameters. + * @tc.type: FUNC + * @tc.require: issueI5WBBH + */ +HWTEST_F(NotificationIconButtonTest, Unmarshalling_00001, Function | SmallTest | Level1) +{ + bool unmarshalling = true; + Parcel parcel; + std::shared_ptr result = + std::make_shared(); + + if (nullptr != result) { + if (nullptr == result->Unmarshalling(parcel)) { + unmarshalling = false; + } + } + EXPECT_EQ(unmarshalling, true); +} + +/** + * @tc.name: Unmarshalling_00002 + * @tc.desc: Test Unmarshalling parameters. + * @tc.type: FUNC + * @tc.require: issueI5WBBH + */ +HWTEST_F(NotificationIconButtonTest, Unmarshalling_00002, Function | SmallTest | Level1) +{ + Parcel parcel; + auto button = std::make_shared(); + button->SetText("testText"); + button->SetName("testName"); + button->Marshalling(parcel); + + auto newButton = button->Unmarshalling(parcel); + EXPECT_NE(newButton, nullptr); +} + + +/** + * @tc.name: Dump_00001 + * @tc.desc: Test Dump. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(NotificationIconButtonTest, Dump_00001, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + + EXPECT_EQ(rrc->Dump(), ""); +} +} +} diff --git a/frameworks/js/napi/include/common.h b/frameworks/js/napi/include/common.h index b061bbd01d9da2958e1bb7cf0a85c2073783ec58..0d55928a84848671847ceb0d3fae0bad4d35648a 100644 --- a/frameworks/js/napi/include/common.h +++ b/frameworks/js/napi/include/common.h @@ -460,6 +460,17 @@ public: */ static napi_value SetButton(const napi_env &env, const NotificationLocalLiveViewButton &button, napi_value &result); + /** + * @brief Sets a js object by specified NotificationIconButton array + * + * @param env Indicates the environment that the API is invoked under + * @param buttons Indicates a NotificationIconButton 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 SetCardButton(const napi_env &env, const std::vector buttons, + napi_value &result); + /** * @brief Sets a js object by specified NotificationProgress object * @@ -1319,6 +1330,41 @@ public: const napi_env &env, const napi_value &contentResult, std::shared_ptr content); + /** + * @brief Gets a card 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 GetNotificationLocalLiveViewCardButton( + const napi_env &env, const napi_value &contentResult, + std::shared_ptr content); + + /** + * @brief Gets a capsule button of NotificationCapsule object from specified js object + * + * @param env Indicates the environment that the API is invoked under + * @param capsuletResult Indicates a js object to be converted + * @param capsule Indicates a capsule object from specified js object + * @return Returns the null object if success, returns the null value otherwise + */ + static napi_value GetNotificationLocalLiveViewCapsuleCardButton( + const napi_env &env, const napi_value &capsuletResult, + OHOS::Notification::NotificationCapsule &capsule); + + /** + * @brief Gets array of NotificationCapsule object from specified js object + * + * @param env Indicates the environment that the API is invoked under + * @param buttonResult Indicates a js array to be converted + * @param cardButtons Indicates a button array from specified js object + * @return Returns the null object if success, returns the null value otherwise + */ + static napi_value GetNotificationIconButton( + const napi_env &env, const napi_value &buttonResult, std::vector &cardButtons); + /** * @brief Gets a time of NotificationLocalLiveViewContent object from specified js object * @@ -1762,7 +1808,7 @@ public: const std::shared_ptr &agentBundle, napi_value &result); static napi_value GetResourceObject(napi_env env, std::shared_ptr &resource, napi_value &value); - static napi_value SetResourceObject(napi_env env, std::shared_ptr &resource, + static napi_value SetResourceObject(napi_env env, const std::shared_ptr &resource, napi_value &value); static napi_value SetObjectStringProperty(const napi_env &env, napi_value& object, const std::string& key, const std::string& value); diff --git a/frameworks/js/napi/src/common_convert_liveview.cpp b/frameworks/js/napi/src/common_convert_liveview.cpp index b888c6069a337bad121f17e94b458b7abb1b3d25..269b0e6996c5c53e94cfe89c2cce6f2b6cf6665f 100644 --- a/frameworks/js/napi/src/common_convert_liveview.cpp +++ b/frameworks/js/napi/src/common_convert_liveview.cpp @@ -24,6 +24,7 @@ #include "notification_capsule.h" #include "notification_constant.h" #include "notification_local_live_view_content.h" +#include "notification_icon_button.h" #include "notification_progress.h" #include "notification_time.h" #include "pixel_map_napi.h" @@ -78,6 +79,24 @@ napi_value Common::SetNotificationLocalLiveViewContent( napi_set_named_property(env, result, "button", button); } + // cardButton?: Array; + if (localLiveViewContent->isFlagExist(NotificationLocalLiveViewContent::LiveViewContentInner::CARD_BUTTON)) { + napi_value cardBtn = nullptr; + napi_create_array_with_length(env, localLiveViewContent->GetCardButton().size(), &cardBtn); + if (!SetCardButton(env, localLiveViewContent->GetCardButton(), cardBtn)) { + ANS_LOGE("SetCardButton call failed"); + return NapiGetBoolean(env, false); + } + napi_set_named_property(env, result, "cardButton", cardBtn); + } + + // liveViewType?: number + napi_create_int32(env, localLiveViewContent->GetLiveviewType(), &value); + if (localLiveViewContent->GetLiveviewType() != -1) { + ANS_LOGE("localLiveViewContent->GetLiveviewType() %{public}d ", localLiveViewContent->GetLiveviewType()); + napi_set_named_property(env, result, "liveViewType", value); + } + // progress: NotificationProgress if (localLiveViewContent->isFlagExist(NotificationLocalLiveViewContent::LiveViewContentInner::PROGRESS)) { napi_value progress = nullptr; @@ -136,6 +155,20 @@ napi_value Common::SetCapsule(const napi_env &env, const NotificationCapsule &ca napi_set_named_property(env, result, "icon", iconResult); } } + + // time?: number + napi_create_int32(env, capsule.GetTime(), &value); + napi_set_named_property(env, result, "time", value); + + // capsuleButton?: Array; + napi_value cardBtn = nullptr; + napi_create_array_with_length(env, capsule.GetCapsuleButton().size(), &cardBtn); + if (!SetCardButton(env, capsule.GetCapsuleButton(), cardBtn)) { + ANS_LOGE("capsuleButton call failed"); + return NapiGetBoolean(env, false); + } + napi_set_named_property(env, result, "capsuleButton", cardBtn); + return NapiGetBoolean(env, true); } @@ -221,7 +254,7 @@ napi_value Common::SetObjectUint32Property(const napi_env &env, napi_value& obje return NapiGetNull(env); } -napi_value Common::SetResourceObject(napi_env env, std::shared_ptr &resource, +napi_value Common::SetResourceObject(napi_env env, const std::shared_ptr &resource, napi_value &object) { if (SetObjectStringProperty(env, object, "bundleName", resource->bundleName) == nullptr) { @@ -297,6 +330,49 @@ napi_value Common::SetButton(const napi_env &env, const NotificationLocalLiveVie return NapiGetBoolean(env, true); } +napi_value Common::SetCardButton(const napi_env &env, const std::vector buttons, + napi_value &result) +{ + ANS_LOGD("enter"); + + int iconCount = 0; + napi_value value = nullptr; + for (auto btn : buttons) { + // name: string + napi_value item = nullptr; + napi_status status = napi_create_object(env, &item); + if (status != napi_ok) { + ANS_LOGE("Failed to create card button item"); + return NapiGetBoolean(env, false); + } + napi_create_string_utf8(env, btn.GetName().c_str(), NAPI_AUTO_LENGTH, &value); + napi_set_named_property(env, item, "name", value); + + // text?: string; + napi_create_string_utf8(env, btn.GetText().c_str(), NAPI_AUTO_LENGTH, &value); + napi_set_named_property(env, item, "text", value); + + // hidePanel?: boolean; + napi_get_boolean(env, btn.GetHidePanel(), &value); + napi_set_named_property(env, item, "hidePanel", value); + + // iconsResource: Resource; + napi_value object; + status = napi_create_object(env, &object); + if (status != napi_ok) { + ANS_LOGE("Failed to create card button item.resource"); + return NapiGetBoolean(env, false); + } + if (!SetResourceObject(env, btn.GetIconResource(), object)) { + return NapiGetBoolean(env, false); + } + napi_set_named_property(env, item, "iconsResource", object); + status = napi_set_element(env, result, iconCount, item); + iconCount++; + } + return NapiGetBoolean(env, true); +} + napi_value Common::SetNotificationLiveViewContent( const napi_env &env, NotificationBasicContent *basicContent, napi_value &result) { @@ -431,6 +507,7 @@ napi_value Common::GetNotificationLocalLiveViewCapsule( char str[STR_MAX_SIZE] = {0}; std::shared_ptr pixelMap = nullptr; napi_value result = nullptr; + int32_t intValue; ANS_LOGD("enter"); @@ -510,12 +587,180 @@ napi_value Common::GetNotificationLocalLiveViewCapsule( ANS_LOGD("capsule icon = %{public}d", pixelMap->GetWidth()); } + //time?: number + NAPI_CALL(env, napi_has_named_property(env, capsuleResult, "time", &hasProperty)); + if (hasProperty) { + napi_get_named_property(env, capsuleResult, "time", &result); + NAPI_CALL(env, napi_typeof(env, result, &valuetype)); + if (valuetype != napi_number) { + ANS_LOGE("Wrong argument type. Number expected."); + return nullptr; + } + napi_get_value_int32(env, result, &intValue); + capsule.SetTime(intValue); + } + + NAPI_CALL(env, napi_has_named_property(env, capsuleResult, "capsuleButton", &hasProperty)); + if (hasProperty) { + napi_get_named_property(env, capsuleResult, "capsuleButton", &result); + NAPI_CALL(env, napi_typeof(env, result, &valuetype)); + if (valuetype != napi_object) { + ANS_LOGE("Wrong argument type. Object expected."); + return nullptr; + } + if (hasProperty && GetNotificationLocalLiveViewCapsuleCardButton(env, result, capsule) == nullptr) { + return nullptr; + } + } + content->SetCapsule(capsule); content->addFlag(NotificationLocalLiveViewContent::LiveViewContentInner::CAPSULE); return NapiGetNull(env); } +napi_value Common::GetNotificationLocalLiveViewCardButton( + const napi_env &env, const napi_value &contentResult, + std::shared_ptr content) +{ + napi_value buttonResult = nullptr; + + ANS_LOGD("enter"); + napi_get_named_property(env, contentResult, "cardButton", &buttonResult); + + // 解析iconbutton数组 + std::vector cardButtons; + if (GetNotificationIconButton(env, buttonResult, cardButtons) == nullptr) { + return nullptr; + } + + content->SetCardButton(cardButtons); + content->addFlag(NotificationLocalLiveViewContent::LiveViewContentInner::CARD_BUTTON); + return NapiGetNull(env); +} + +napi_value Common::GetNotificationLocalLiveViewCapsuleCardButton( + const napi_env &env, const napi_value &capsuletResult, + OHOS::Notification::NotificationCapsule &capsule) +{ + ANS_LOGD("enter"); + std::vector cardButtons; + if (GetNotificationIconButton(env, capsuletResult, cardButtons) == nullptr) { + return nullptr; + } + + capsule.SetCapsuleButton(cardButtons); + return NapiGetNull(env); +} + +napi_value Common::GetNotificationIconButton( + const napi_env &env, const napi_value &buttonResult, std::vector &cardButtons) +{ + // cardButton_item?: NotificationIconButton; + napi_value cardButton = nullptr; + napi_value result = nullptr; + napi_valuetype valuetype = napi_undefined; + + bool isArray = false; + bool boolValue = false; + uint32_t length = 0; + + size_t strLen = 0; + char str[STR_MAX_SIZE] = {0}; + bool hasProperty = false; + + ANS_LOGD("enter"); + napi_is_array(env, buttonResult, &isArray); + if (!isArray) { + ANS_LOGE("Property names is expected to be an array."); + return nullptr; + } + napi_get_array_length(env, buttonResult, &length); + if (length > BUTTON_MAX_SIZE) { + length = BUTTON_MAX_SIZE; + } + + for (size_t i = 0; i < length; i++) { + napi_get_element(env, buttonResult, i, &cardButton); + + NAPI_CALL(env, napi_typeof(env, cardButton, &valuetype)); + if (valuetype != napi_object) { + ANS_LOGE("Wrong argument type. Object expected."); + return nullptr; + } + // 数组item + NotificationIconButton button; + // name: string + NAPI_CALL(env, napi_has_named_property(env, cardButton, "name", &hasProperty)); + if (!hasProperty) { + ANS_LOGE("Property name expected."); + return nullptr; + } else { + napi_get_named_property(env, cardButton, "name", &result); + NAPI_CALL(env, napi_typeof(env, result, &valuetype)); + if (valuetype != napi_string) { + ANS_LOGE("Wrong argument type. String expected."); + return nullptr; + } + NAPI_CALL(env, napi_get_value_string_utf8(env, result, str, STR_MAX_SIZE - 1, &strLen)); + button.SetName(str); + } + + // iconsResource: Resource + NAPI_CALL(env, napi_has_named_property(env, cardButton, "iconsResource", &hasProperty)); + if (!hasProperty) { + ANS_LOGE("Property iconsResource expected."); + return nullptr; + } else { + napi_value iconResource = nullptr; + auto resource = std::make_shared(); + napi_get_named_property(env, cardButton, "iconsResource", &iconResource); + NAPI_CALL(env, napi_typeof(env, iconResource, &valuetype)); + if (valuetype != napi_object) { + ANS_LOGE("Wrong argument type. iconsResource Object expected."); + return nullptr; + } + if (Common::GetResourceObject(env, resource, iconResource) == nullptr) { + ANS_LOGW("Invalid icon resource object."); + return nullptr; + } else { + button.SetIconResource(resource); + } + } + + // text?: string + NAPI_CALL(env, napi_has_named_property(env, cardButton, "text", &hasProperty)); + if (hasProperty) { + napi_get_named_property(env, cardButton, "text", &result); + NAPI_CALL(env, napi_typeof(env, result, &valuetype)); + if (valuetype != napi_string) { + ANS_LOGE("Wrong argument type. String expected."); + return nullptr; + } + NAPI_CALL(env, napi_get_value_string_utf8(env, result, str, STR_MAX_SIZE - 1, &strLen)); + button.SetText(str); + } + + // hidePanel?: boolean; + NAPI_CALL(env, napi_has_named_property(env, cardButton, "hidePanel", &hasProperty)); + if (hasProperty) { + napi_get_named_property(env, cardButton, "hidePanel", &result); + NAPI_CALL(env, napi_typeof(env, result, &valuetype)); + if (valuetype != napi_boolean) { + ANS_LOGE("Wrong argument type. bool expected."); + return nullptr; + } + napi_get_value_bool(env, result, &boolValue); + button.SetHidePanel(boolValue); + } + + cardButtons.push_back(button); + ANS_LOGD("icon button = %{public}s", button.Dump().c_str()); + } + + return NapiGetNull(env); +} + napi_value Common::GetResourceObject(napi_env env, std::shared_ptr &resource, napi_value &value) { @@ -885,6 +1130,26 @@ napi_value Common::GetNotificationLocalLiveViewContentDetailed( return nullptr; } + //cardButton? + NAPI_CALL(env, napi_has_named_property(env, contentResult, "cardButton", &hasProperty)); + if (hasProperty && GetNotificationLocalLiveViewCardButton(env, contentResult, content) == nullptr) { + return nullptr; + } + + // liveViewType?: number + NAPI_CALL(env, napi_has_named_property(env, contentResult, "liveViewType", &hasProperty)); + if (hasProperty) { + napi_get_named_property(env, contentResult, "liveViewType", &result); + NAPI_CALL(env, napi_typeof(env, result, &valuetype)); + if (valuetype != napi_number) { + ANS_LOGE("Wrong argument liveViewType. Number expected."); + return nullptr; + } + napi_get_value_int32(env, result, &type); + content->SetLiveviewType(type); + ANS_LOGD("localLiveView SetLiveviewType = %{public}d", type); + } + //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_capsule.h b/interfaces/inner_api/notification_capsule.h index 65ef26aa5618b0f9955bf9e385758785da23d954..6b3f6de30d0dd09f15fbbf60515fdff3f67f0f87 100644 --- a/interfaces/inner_api/notification_capsule.h +++ b/interfaces/inner_api/notification_capsule.h @@ -19,6 +19,7 @@ #include "pixel_map.h" #include "notification_json_convert.h" #include "parcel.h" +#include "notification_icon_button.h" #include namespace OHOS { @@ -65,6 +66,24 @@ public: void SetContent(const std::string &content); + /** + * @brief Obtains the button of the notification capsule. + * + * @return Returns the button of the notification capsule. + */ + std::vector GetCapsuleButton() const; + + void SetCapsuleButton(const std::vector &buttons); + + /** + * @brief Obtains the expire time of the notification capsule. + * + * @return Returns the expire time of the notification capsule. + */ + int32_t GetTime() const; + + void SetTime(int32_t time); + /** * @brief Returns a string representation of the object. * @@ -120,6 +139,8 @@ private: std::string backgroundColor_ {}; std::string content_ {}; std::shared_ptr icon_ {}; + std::vector capsuleButton_; + int32_t time_ {-1}; }; } // namespace Notification } // namespace OHOS diff --git a/interfaces/inner_api/notification_icon_button.h b/interfaces/inner_api/notification_icon_button.h new file mode 100644 index 0000000000000000000000000000000000000000..e95d07fa43de617b9ae0cca51a4e6fd85b7866b7 --- /dev/null +++ b/interfaces/inner_api/notification_icon_button.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2024 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_ICON_BUTTON_H +#define BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_INTERFACES_INNER_API_ICON_BUTTON_H + +#include "notification_json_convert.h" +#include "resource_manager.h" +#include "parcel.h" +#include +#include + +namespace OHOS { +namespace Notification { +using namespace Global::Resource; +const uint32_t BUTTON_MAX_SIZE = 3; +const uint32_t BUTTON_RESOURCE_SIZE = 3; +const uint32_t RESOURCE_BUNDLENAME_INDEX = 0; +const uint32_t RESOURCE_MODULENAME_INDEX = 1; +const uint32_t RESOURCE_ID_INDEX = 2; + +class NotificationIconButton : public Parcelable, public NotificationJsonConvertionBase { +public: + NotificationIconButton() = default; + ~NotificationIconButton() = default; + /** + * @brief Obtains the icon of the notification capsule. + * + * @return Returns the icon of the notification capsule. + */ + const std::shared_ptr GetIconResource() const; + + void SetIconResource(const std::shared_ptr &iconResource); + + /** + * @brief Obtains the text of the notification button. + * + * @return Returns the text of the notification button. + */ + std::string GetText() const; + + void SetText(const std::string &text); + + /** + * @brief Obtains the unqiue name of the notification button. + * + * @return Returns the unqiue name of the notification button. + */ + std::string GetName() const; + + void SetName(const std::string &name); + + /** + * @brief Obtains the hidePanel of the notification button. + * + * @return Returns the hidePanel of the notification button. + */ + bool GetHidePanel() const; + + void SetHidePanel(bool hidePanel); + + /** + * @brief Returns a string representation of the object. + * + * @return Returns a string representation of the object. + */ + std::string Dump(); + + /** + * @brief Converts a notification capsule 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 notification capsule object from a Json. + * + * @param jsonObject Indicates the Json object. + * @return Returns the notification capsule. + */ + static NotificationIconButton *FromJson(const nlohmann::json &jsonObject); + + /** + * @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 Unmarshal object from a Parcel. + * + * @param parcel Indicates the parcel object. + * @return Returns the notification capsule. + */ + static NotificationIconButton *Unmarshalling(Parcel &parcel); + + void ClearButtonIconsResource(); +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); +private: + std::string text_ {}; + std::string name_ {}; + std::shared_ptr iconResource_ {}; + bool hidePanel_; +}; +} // namespace Notification +} // namespace OHOS +#endif //BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_INTERFACES_INNER_API_ICON_BUTTON_H \ No newline at end of file diff --git a/interfaces/inner_api/notification_local_live_view_content.h b/interfaces/inner_api/notification_local_live_view_content.h index 6792ac58e2cfd22d7632c181dc44dfda045b45c1..ec620c39187a3d68d2ed0338c5576e929ff43752 100644 --- a/interfaces/inner_api/notification_local_live_view_content.h +++ b/interfaces/inner_api/notification_local_live_view_content.h @@ -26,6 +26,7 @@ #include "notification_time.h" #include "parcel.h" #include +#include "ans_const_define.h" namespace OHOS { namespace Notification { @@ -37,6 +38,7 @@ public: PROGRESS, TIME, INITIAL_TIME, + CARD_BUTTON, }; NotificationLocalLiveViewContent() = default; @@ -81,6 +83,19 @@ public: */ NotificationLocalLiveViewButton GetButton(); + /* + * @brief Sets the card button to be included in a local live view notification. + * + * @param button Indicates the type to be included. + */ + void SetCardButton(std::vector buttons); + + /* + * @brief Get the card button of a local live view notification. + * + */ + std::vector GetCardButton(); + /* * @brief Sets the progress to be included in a local live view notification. * @@ -121,6 +136,19 @@ public: */ bool isFlagExist(int32_t flag); + /* + * @brief Sets the type to be included in a local live view notification. + * + * @param type Indicates the type to be included. + */ + void SetLiveviewType(int32_t type); + + /* + * @brief Get the type of a local live view notification. + * + */ + int32_t GetLiveviewType(); + /** * @brief Returns a string representation of the object. * @@ -177,9 +205,11 @@ private: int32_t type_ {0}; NotificationCapsule capsule_ {}; NotificationLocalLiveViewButton button_ {}; + std::vector card_button_ {}; NotificationProgress progress_ {}; NotificationTime time_ {}; std::vector flags_ {}; + int32_t liveviewType_ {-1}; }; } // namespace Notification } // namespace OHOS