From 1cc07c20906f0be7043f941555da2dff9bc9e9bb Mon Sep 17 00:00:00 2001 From: wangdi Date: Thu, 11 Sep 2025 16:48:59 +0800 Subject: [PATCH] NotificationBasicContent add structuredText Signed-off-by: wangdi --- .../ans/src/notification_basic_content.cpp | 64 +++++++++- ...tification_conversational_content_test.cpp | 5 +- .../notification_live_view_content_test.cpp | 6 +- ...ification_local_live_view_content_test.cpp | 2 +- .../notification_media_content_test.cpp | 2 +- .../notification_multiline_content_test.cpp | 3 +- .../notification_picture_content_test.cpp | 3 +- .../ets/ani/include/sts_convert_other.h | 5 + .../ani/include/sts_notification_content.h | 2 + frameworks/ets/ani/src/sts_convert_other.cpp | 107 +++++++++++++++- .../ets/ani/src/sts_notification_content.cpp | 92 ++++++++++++++ .../ets/ets/@ohos.notificationManager.ets | 18 +++ .../ets/notification/notificationContent.ets | 14 +++ frameworks/js/napi/include/common.h | 7 ++ .../js/napi/src/common_convert_content.cpp | 117 +++++++++++++++++- .../inner_api/notification_basic_content.h | 15 +++ 16 files changed, 451 insertions(+), 11 deletions(-) diff --git a/frameworks/ans/src/notification_basic_content.cpp b/frameworks/ans/src/notification_basic_content.cpp index f622412f8..6939e1dc5 100644 --- a/frameworks/ans/src/notification_basic_content.cpp +++ b/frameworks/ans/src/notification_basic_content.cpp @@ -62,10 +62,22 @@ std::shared_ptr NotificationBasicContent::GetLockScreenPicture( return lockScreenPicture_; } +void NotificationBasicContent::SetStructuredText( + const std::vector> &structuredText) +{ + structuredText_ = structuredText; +} + +std::vector> NotificationBasicContent::GetStructuredText() const +{ + return structuredText_; +} + std::string NotificationBasicContent::Dump() { return "title = " + title_ + ", text = " + text_ + ", additionalText = " + additionalText_ + - ", lockScreenPicture = " + (lockScreenPicture_ ? "not null" : "null"); + ", lockScreenPicture = " + (lockScreenPicture_ ? "not null" : "null") + + ", structuredText = " + (structuredText_.empty() ? "null" : "not null"); } bool NotificationBasicContent::ToJson(nlohmann::json &jsonObject) const @@ -75,6 +87,12 @@ bool NotificationBasicContent::ToJson(nlohmann::json &jsonObject) const jsonObject["additionalText"] = additionalText_; jsonObject["lockscreenPicture"] = AnsImageUtil::PackImage(lockScreenPicture_); + nlohmann::json structuredTextJson; + for (const auto& [key, value] : structuredText_) { + structuredTextJson[key] = value; + } + jsonObject["structuredText"] = structuredTextJson; + return true; } @@ -102,6 +120,15 @@ void NotificationBasicContent::ReadFromJson(const nlohmann::json &jsonObject) auto lockScreenPictureStr = jsonObject.at("lockscreenPicture").get(); lockScreenPicture_ = AnsImageUtil::UnPackImage(lockScreenPictureStr); } + + if (jsonObject.find("structuredText") != jsonEnd) { + auto structuredTextJson = jsonObject.at("structuredText"); + if (!structuredTextJson.empty()) { + for (const auto& iter : structuredTextJson.items()) { + structuredText_.emplace_back(iter.key(), iter.value().get()); + } + } + } } bool NotificationBasicContent::Marshalling(Parcel &parcel) const @@ -134,6 +161,22 @@ bool NotificationBasicContent::Marshalling(Parcel &parcel) const } } + int32_t size = static_cast(structuredText_.size()); + if (!parcel.WriteInt32(size)) { + ANS_LOGE("Failed to write structuredText size."); + return false; + } + for (const auto& [key, value] : structuredText_) { + if (!parcel.WriteString(key)) { + ANS_LOGE("Failed to write structuredText key."); + return false; + } + if (!parcel.WriteString(value)) { + ANS_LOGE("Failed to write structuredText value."); + return false; + } + } + return true; } @@ -163,6 +206,25 @@ bool NotificationBasicContent::ReadFromParcel(Parcel &parcel) } } + int32_t size = -1; + if (!parcel.ReadInt32(size)) { + ANS_LOGE("Failed to read structuredText size."); + return false; + } + for (int32_t i = 0; i < size; ++i) { + std::string key; + std::string value; + if (!parcel.ReadString(key)) { + ANS_LOGE("Failed to read structuredText key."); + return false; + } + if (!parcel.ReadString(value)) { + ANS_LOGE("Failed to read structuredText value."); + return false; + } + structuredText_.emplace_back(key, value); + } + return true; } } // namespace Notification diff --git a/frameworks/ans/test/unittest/notification_conversational_content_test.cpp b/frameworks/ans/test/unittest/notification_conversational_content_test.cpp index 04dab429f..69b8f19b1 100644 --- a/frameworks/ans/test/unittest/notification_conversational_content_test.cpp +++ b/frameworks/ans/test/unittest/notification_conversational_content_test.cpp @@ -205,8 +205,9 @@ HWTEST_F(NotificationConversationalContentTest, AddConversationalMessage_00002, rrc->AddConversationalMessage(messagePtr); EXPECT_EQ(rrc->GetAllConversationalMessages().size(), 0); std::string result = rrc->Dump(); - std::string ret = "NotificationConversationalContent{ title = , text = , additionalText = ," - " lockScreenPicture = null, conversationTitle = , isGroup = false, messageUser = MessageUser{ key = , name = , " + std::string ret = "NotificationConversationalContent{ title = , text = , additionalText = , " + "lockScreenPicture = null, structuredText = null, conversationTitle = , " + "isGroup = false, messageUser = MessageUser{ key = , name = , " "pixelMap = null, uri = , isMachine = false, isUserImportant = false }, messages = }"; EXPECT_EQ(result, ret); } diff --git a/frameworks/ans/test/unittest/notification_live_view_content_test.cpp b/frameworks/ans/test/unittest/notification_live_view_content_test.cpp index 649bc2de9..03596d994 100644 --- a/frameworks/ans/test/unittest/notification_live_view_content_test.cpp +++ b/frameworks/ans/test/unittest/notification_live_view_content_test.cpp @@ -115,7 +115,8 @@ HWTEST_F(NotificationLiveViewContentTest, Dump_00001, Function | SmallTest | Lev { auto rrc = std::make_shared(); std::string ret = "NotificationLiveViewContent{ title = , text = , " - "additionalText = , lockScreenPicture = null, status = 0, version = -1, extraInfo = null, " + "additionalText = , lockScreenPicture = null, structuredText = null, " + "status = 0, version = -1, extraInfo = null, " "isOnlyLocalUpdate_ = false, pictureMap = {}, extensionWantAgent_ = null}"; EXPECT_EQ(rrc->Dump(), ret); @@ -142,7 +143,8 @@ HWTEST_F(NotificationLiveViewContentTest, Dump_00002, Function | SmallTest | Lev rrc->SetAdditionalText("addText"); std::string ret = "NotificationLiveViewContent{ title = title, text = text, " - "additionalText = addText, lockScreenPicture = null, status = 0, version = -1, extraInfo = null, " + "additionalText = addText, lockScreenPicture = null, structuredText = null, " + "status = 0, version = -1, extraInfo = null, " "isOnlyLocalUpdate_ = false, pictureMap = { { key = test, value = not empty } }, " "extensionWantAgent_ = null}"; diff --git a/frameworks/ans/test/unittest/notification_local_live_view_content_test.cpp b/frameworks/ans/test/unittest/notification_local_live_view_content_test.cpp index e9d1e9f83..6bfdf53d4 100644 --- a/frameworks/ans/test/unittest/notification_local_live_view_content_test.cpp +++ b/frameworks/ans/test/unittest/notification_local_live_view_content_test.cpp @@ -261,7 +261,7 @@ HWTEST_F(NotificationLocalLiveViewContentTest, Dump_00001, Function | SmallTest liveViewContent->addFlag(0); std::string dumpStr = "NotificationLocalLiveViewContent{ title = , text = , additionalText = , " - "lockScreenPicture = null, type = 0, " + "lockScreenPicture = null, structuredText = null, type = 0, " "capsule = Capsule{ title = testTitle, backgroundColor = , content = , icon = null, time = 0 }, button = , " "progress = Progress{ maxValue = 1, currentValue = 0, isPercentage = 1 }, " "time = Time{ initialTime = 1, isCountDown = 0, isPaused = 0, isInTitle = 0 }, liveviewType = 0 }"; diff --git a/frameworks/ans/test/unittest/notification_media_content_test.cpp b/frameworks/ans/test/unittest/notification_media_content_test.cpp index 5fb8a5b80..37b688e1f 100644 --- a/frameworks/ans/test/unittest/notification_media_content_test.cpp +++ b/frameworks/ans/test/unittest/notification_media_content_test.cpp @@ -70,7 +70,7 @@ HWTEST_F(NotificationMediaContentTest, Dump_00001, Function | SmallTest | Level1 { auto rrc = std::make_shared(); std::string ret = "NotificationMediaContent{ title = , text = , " - "additionalText = , lockScreenPicture = null, avToken = null, sequenceNumbers = }"; + "additionalText = , lockScreenPicture = null, structuredText = null, avToken = null, sequenceNumbers = }"; EXPECT_EQ(rrc->Dump(), ret); } diff --git a/frameworks/ans/test/unittest/notification_multiline_content_test.cpp b/frameworks/ans/test/unittest/notification_multiline_content_test.cpp index f31b1790b..ef280a558 100644 --- a/frameworks/ans/test/unittest/notification_multiline_content_test.cpp +++ b/frameworks/ans/test/unittest/notification_multiline_content_test.cpp @@ -85,7 +85,8 @@ HWTEST_F(NotificationMultiLineContentTest, Dump_00001, Function | SmallTest | Le { auto rrc = std::make_shared(); std::string ret = "NotificationMultiLineContent{ title = , text = , " - "additionalText = , lockScreenPicture = null, briefText = , expandedTitle = , allLines = [] }"; + "additionalText = , lockScreenPicture = null, structuredText = null, " + "briefText = , expandedTitle = , allLines = [] }"; EXPECT_EQ(rrc->Dump(), ret); } diff --git a/frameworks/ans/test/unittest/notification_picture_content_test.cpp b/frameworks/ans/test/unittest/notification_picture_content_test.cpp index 040b5111a..5f6b61d97 100644 --- a/frameworks/ans/test/unittest/notification_picture_content_test.cpp +++ b/frameworks/ans/test/unittest/notification_picture_content_test.cpp @@ -84,7 +84,8 @@ HWTEST_F(NotificationPictureContentTest, Dump_00001, Function | SmallTest | Leve { auto rrc = std::make_shared(); std::string ret = "NotificationPictureContent{ title = , text = , " - "additionalText = , lockScreenPicture = null, briefText = , expandedTitle = , bigPicture = null }"; + "additionalText = , lockScreenPicture = null, structuredText = null, " + "briefText = , expandedTitle = , bigPicture = null }"; EXPECT_EQ(rrc->Dump(), ret); } diff --git a/frameworks/ets/ani/include/sts_convert_other.h b/frameworks/ets/ani/include/sts_convert_other.h index 13bfe6c56..6f6911b4b 100644 --- a/frameworks/ets/ani/include/sts_convert_other.h +++ b/frameworks/ets/ani/include/sts_convert_other.h @@ -27,6 +27,7 @@ namespace NotificationSts { using namespace OHOS::Media; using namespace OHOS::AbilityRuntime::WantAgent; const uint32_t BUTTON_RESOURCE_SIZE = 3; +const uint32_t STRUCTURED_TEXT_SIZE = 512; std::shared_ptr UnwrapWantAgent(ani_env *env, ani_object agent); ani_object WarpWantAgent(ani_env *env, std::shared_ptr wantAgent); @@ -55,6 +56,10 @@ ani_status GetResourceArray(ani_env *env, ani_object param, const char *name, ani_object GetAniResource(ani_env *env, const std::shared_ptr resource); ani_object GetAniArrayResource(ani_env *env, const std::vector> resources); +ani_object CreateAniUndefined(ani_env *env); +ani_object CreateMapObject(ani_env *env, const std::string name, const char *signature); +ani_status GetMapByAniMap(ani_env *env, ani_object &mapObj, + std::vector> &out); } // namespace NotificationSts } // OHOS #endif \ No newline at end of file diff --git a/frameworks/ets/ani/include/sts_notification_content.h b/frameworks/ets/ani/include/sts_notification_content.h index 34f73e559..e76ca80c1 100644 --- a/frameworks/ets/ani/include/sts_notification_content.h +++ b/frameworks/ets/ani/include/sts_notification_content.h @@ -71,6 +71,8 @@ ani_object WarpNotificationIconButton(ani_env *env, const NotificationIconButton ani_status GetIconButtonArray(ani_env *env, ani_object param, const char *name, std::vector &res, const uint32_t maxLen); ani_object GetAniIconButtonArray(ani_env *env, const std::vector buttons); +ani_status GetStructuredTextFromAni(ani_env *env, ani_object obj, + std::shared_ptr basicContent); void UnWarpNotificationLocalLiveViewButton(ani_env *env, ani_object obj, NotificationLocalLiveViewButton &button); diff --git a/frameworks/ets/ani/src/sts_convert_other.cpp b/frameworks/ets/ani/src/sts_convert_other.cpp index 999796612..6b8a37945 100644 --- a/frameworks/ets/ani/src/sts_convert_other.cpp +++ b/frameworks/ets/ani/src/sts_convert_other.cpp @@ -514,5 +514,110 @@ ani_object GetAniWantAgentArray(ani_env *env, std::vectorGetUndefined(&aniRef); + return reinterpret_cast(aniRef); +} + +ani_object CreateMapObject(ani_env *env, const std::string name, const char *signature) +{ + ani_class cls = nullptr; + if (env->FindClass(name.c_str(), &cls) != ANI_OK) { + ANS_LOGE("Failed to found %{public}s", name.c_str()); + return nullptr; + } + ani_method ctor; + if (env->Class_FindMethod(cls, "", signature, &ctor) != ANI_OK) { + ANS_LOGE("Failed to get ctor %{public}s", name.c_str()); + return nullptr; + } + ani_object obj = {}; + if (env->Object_New(cls, ctor, &obj) != ANI_OK) { + ANS_LOGE("Failed to create object %{public}s", name.c_str()); + return nullptr; + } + return obj; +} + +ani_status GetMapIterator(ani_env *env, ani_object &mapObj, const char *method, ani_ref *it) +{ + ani_status status = env->Object_CallMethodByName_Ref(mapObj, method, nullptr, it); + if (status != ANI_OK) { + ANS_LOGD("Failed to get %{public}s iterator, status: %{public}d", method, status); + } + return status; +} + +ani_status GetMapIteratorNext(ani_env *env, ani_ref &it, ani_ref *next) +{ + ani_status status = env->Object_CallMethodByName_Ref(reinterpret_cast(it), "next", nullptr, next); + if (status != ANI_OK) { + ANS_LOGD("Failed to get next, status: %{public}d", status); + } + return status; +} + +ani_status GetMapIteratorStringValue(ani_env *env, ani_ref &next, std::string &str) +{ + ani_ref val; + ani_status status = env->Object_GetFieldByName_Ref(reinterpret_cast(next), "value", &val); + if (status != ANI_OK) { + ANS_LOGD("Falied to get value, status: %{public}d", status); + } + status = GetStringByAniString(env, reinterpret_cast(val), str); + if (status == ANI_OK && str.size() > STRUCTURED_TEXT_SIZE) { + str.resize(STRUCTURED_TEXT_SIZE); + ANS_LOGW("Structured text truncated to 512 bytes."); + } + return status; +} + +ani_status GetMapByAniMap(ani_env *env, ani_object &mapObj, + std::vector> &out) +{ + ani_status status = ANI_ERROR; + ani_ref keys; + ani_ref values; + bool done = false; + + if (GetMapIterator(env, mapObj, "keys", &keys) != ANI_OK || + GetMapIterator(env, mapObj, "values", &values) != ANI_OK) { + return ANI_ERROR; + } + + while (!done) { + ani_ref nextKey; + ani_ref nextVal; + ani_boolean done; + + if (GetMapIteratorNext(env, keys, &nextKey) != ANI_OK || + GetMapIteratorNext(env, values, &nextVal) != ANI_OK) { + return ANI_ERROR; + } + + if ((status = env->Object_GetFieldByName_Boolean(reinterpret_cast(nextKey), "done", &done)) + != ANI_OK) { + ANS_LOGD("Failed to check iterator done, status: %{public}d", status); + return ANI_ERROR; + } + if (done) { + break; + } + + std::string keyStr; + std::string valStr; + if (GetMapIteratorStringValue(env, nextKey, keyStr) != ANI_OK|| + GetMapIteratorStringValue(env, nextVal, valStr) != ANI_OK) { + return ANI_ERROR; + } + ANS_LOGD("__logwd sts %{public}s %{public}s", keyStr.c_str(), valStr.c_str()); + out.emplace_back(keyStr, valStr); + } + + return ANI_OK; +} } // namespace NotificationSts -} // OHOS \ No newline at end of file +} // OHOS diff --git a/frameworks/ets/ani/src/sts_notification_content.cpp b/frameworks/ets/ani/src/sts_notification_content.cpp index d9062953d..de871da24 100644 --- a/frameworks/ets/ani/src/sts_notification_content.cpp +++ b/frameworks/ets/ani/src/sts_notification_content.cpp @@ -735,10 +735,65 @@ ani_status UnWarpNotificationBasicContent(ani_env *env, ani_object obj, ANS_LOGD("UnWarpNotificationBasicContent: get lockscreenPicture by pixelMap failed"); } } + + if (GetStructuredTextFromAni(env, obj, basicContent) != ANI_OK) { + return ANI_ERROR; + } + ANS_LOGD("UnWarpNotificationBasicContent end"); return status; } +ani_status GetStructuredTextFromAni(ani_env *env, ani_object obj, + std::shared_ptr basicContent) +{ + ANS_LOGD("GetStructuredText enter"); + ani_boolean isUndefined; + ani_status status = ANI_ERROR; + ani_ref structuredTextRef; + std::vector> structuredTexts; + + if (env->Object_GetPropertyByName_Ref(obj, "structuredText", &structuredTextRef) != ANI_OK || + structuredTextRef == nullptr) { + ANS_LOGD("UnWarpNotificationBasicContent: structuredText is nullptr."); + return ANI_OK; + } + + status = env->Reference_IsUndefined(structuredTextRef, &isUndefined); + if (status != ANI_OK) { + ANS_LOGE("Failed to check undefined, status: %{public}d", status); + return ANI_OK; + } + if (isUndefined == ANI_TRUE) { + ANS_LOGE("StructuredTextRef is undefined"); + return ANI_ERROR; + } + + ani_class mapClass; + ani_object mapObj = static_cast(structuredTextRef); + + if (env->FindClass("Lescompat/Map;", &mapClass) != ANI_OK) { + ANS_LOGE("Find Map class failed."); + return ANI_OK; + } + + ani_type typeMap = mapClass; + ani_boolean isMap; + status = env->Object_InstanceOf(mapObj, typeMap, &isMap); + if (isMap != ANI_TRUE) { + ANS_LOGE("Current obj is not map type."); + return ANI_ERROR; + } + + if (GetMapByAniMap(env, mapObj, structuredTexts) != ANI_OK) { + return ANI_ERROR; + } + basicContent->SetStructuredText(structuredTexts); + + ANS_LOGD("GetStructuredText end"); + return ANI_OK; +} + ani_status UnWarpNotificationNormalContent(ani_env *env, ani_object obj, std::shared_ptr &normalContent) { @@ -1144,6 +1199,40 @@ ani_status UnWarpNotificationLocalLiveViewContent(ani_env *env, ani_object obj, return status; } +bool WrapStructuredText(ani_env *env, ani_object &object, const NotificationBasicContent *basicContent) +{ + ANS_LOGD("WrapStructuredText enter"); + const auto& texts = basicContent->GetStructuredText(); + ani_object structuredTextObj = nullptr; + structuredTextObj = CreateMapObject(env, "Lescompat/Map;", ":V"); + if (structuredTextObj == nullptr) { + return false; + } + ani_ref mapRef = nullptr; + ani_status status = ANI_ERROR; + for (const auto& [k, v] : texts) { + ani_string key; + ani_string val; + if (GetAniStringByString(env, k, key) != ANI_OK || + GetAniStringByString(env, v, val) != ANI_OK) { + ANS_LOGE("Faild to get ani string."); + continue; + } + status = env->Object_CallMethodByName_Ref(structuredTextObj, "set", + "Lstd/core/Object;Lstd/core/Object;:Lescompat/Map;", &mapRef, + static_cast(key), static_cast(val)); + if (status != ANI_OK) { + ANS_LOGE("Faild to set structuredText map, status : %{public}d", status); + continue; + } + } + if (structuredTextObj == nullptr || !SetPropertyByRef(env, object, "structuredText", structuredTextObj)) { + return false; + } + ANS_LOGD("WrapStructuredText end"); + return true; +} + bool SetNotificationBasicContent( ani_env* env, const NotificationBasicContent *basicContent, ani_object &object) { @@ -1167,6 +1256,9 @@ bool SetNotificationBasicContent( if (lockScreenPicObj == nullptr || !SetPropertyByRef(env, object, "lockScreenPicture", lockScreenPicObj)) { ANS_LOGD("SetNotificationBasicContent: set lockScreenPicture failed"); } + if (!WrapStructuredText(env, object, basicContent)) { + ANS_LOGD("SetNotificationBasicContent: set structuredText failed"); + } ANS_LOGD("SetNotificationBasicContent end"); return true; } diff --git a/frameworks/ets/ets/@ohos.notificationManager.ets b/frameworks/ets/ets/@ohos.notificationManager.ets index 8e75412be..ce3a515de 100644 --- a/frameworks/ets/ets/@ohos.notificationManager.ets +++ b/frameworks/ets/ets/@ohos.notificationManager.ets @@ -352,6 +352,9 @@ export default namespace notificationManager { if (normal?.lockscreenPicture != undefined && !(normal?.lockscreenPicture instanceof image.PixelMap)) { return false; } + if (normal?.structuredText != undefined && !(normal?.structuredText instanceof Map)) { + return false; + } return true; } function isInvalidLongText(longText?: NotificationLongTextContent): boolean @@ -371,6 +374,9 @@ export default namespace notificationManager { if (longText?.lockscreenPicture != undefined && !(longText?.lockscreenPicture instanceof image.PixelMap)) { return false; } + if (longText?.structuredText != undefined && !(longText?.structuredText instanceof Map)) { + return false; + } if (!longText?.longText || longText?.longText?.trim() === '') { return false; } @@ -399,6 +405,9 @@ export default namespace notificationManager { if (multiLine?.lockscreenPicture != undefined && !(multiLine?.lockscreenPicture instanceof image.PixelMap)) { return false; } + if (multiLine?.structuredText != undefined && !(multiLine?.structuredText instanceof Map)) { + return false; + } if (!multiLine?.briefText || multiLine?.briefText.trim() === '') { return false; } @@ -427,6 +436,9 @@ export default namespace notificationManager { if (picture?.lockscreenPicture != undefined && !(picture?.lockscreenPicture instanceof image.PixelMap)) { return false; } + if (picture?.structuredText != undefined && !(picture?.structuredText instanceof Map)) { + return false; + } if (!picture?.briefText || picture?.briefText?.trim() === '') { return false; } @@ -455,6 +467,9 @@ export default namespace notificationManager { if (systemLiveView?.lockscreenPicture != undefined && !(systemLiveView?.lockscreenPicture instanceof image.PixelMap)) { return false; } + if (systemLiveView?.structuredText != undefined && !(systemLiveView?.structuredText instanceof Map)) { + return false; + } if (systemLiveView?.capsule !== undefined) { if (systemLiveView?.capsule?.icon != undefined && !(systemLiveView?.capsule?.icon instanceof image.PixelMap)) { return false; @@ -498,6 +513,9 @@ export default namespace notificationManager { if (liveView?.lockscreenPicture != undefined && !(liveView?.lockscreenPicture instanceof image.PixelMap)) { return false; } + if (liveView?.structuredText != undefined && !(liveView?.structuredText instanceof Map)) { + return false; + } if (liveView?.extraInfo !== undefined && liveView?.extraInfo === null) { return false; } diff --git a/frameworks/ets/ets/notification/notificationContent.ets b/frameworks/ets/ets/notification/notificationContent.ets index edd60593c..66454581a 100644 --- a/frameworks/ets/ets/notification/notificationContent.ets +++ b/frameworks/ets/ets/notification/notificationContent.ets @@ -39,6 +39,8 @@ export interface NotificationBasicContent { additionalText?: string; lockscreenPicture?: image.PixelMap; + + structuredText?: Map; } class NotificationBasicContentInner implements NotificationBasicContent { @@ -50,6 +52,8 @@ class NotificationBasicContentInner implements NotificationBasicContent { public additionalText?: string | undefined; public lockscreenPicture?: image.PixelMap | undefined; + + public structuredText?: Map; } export interface NotificationLongTextContent extends NotificationBasicContent { @@ -71,6 +75,8 @@ class NotificationLongTextContentInner implements NotificationLongTextContent { public lockscreenPicture?: image.PixelMap | undefined; + public structuredText?: Map; + public longText: string = ''; public briefText: string = ''; @@ -121,6 +127,8 @@ class NotificationLiveViewContentInner implements NotificationLiveViewContent { public lockscreenPicture?: image.PixelMap | undefined; + public structuredText?: Map; + public status: LiveViewStatus = LiveViewStatus.LIVE_VIEW_CREATE; public version?: number | undefined; @@ -151,6 +159,8 @@ class NotificationMultiLineContentInner implements NotificationMultiLineContent public lockscreenPicture?: image.PixelMap | undefined; + public structuredText?: Map; + public briefText: string = ''; public longTitle: string = ''; @@ -181,6 +191,8 @@ class NotificationPictureContentInner implements NotificationPictureContent { public lockscreenPicture?: image.PixelMap | undefined; + public structuredText?: Map; + public briefText: string = ''; public expandedTitle: string = ''; @@ -219,6 +231,8 @@ class NotificationSystemLiveViewContentInner implements NotificationSystemLiveVi public lockscreenPicture?: image.PixelMap | undefined; + public structuredText?: Map; + public briefText: string = ''; public expandedTitle: string = ''; diff --git a/frameworks/js/napi/include/common.h b/frameworks/js/napi/include/common.h index 2f6db2f46..f254045b4 100644 --- a/frameworks/js/napi/include/common.h +++ b/frameworks/js/napi/include/common.h @@ -36,6 +36,7 @@ constexpr uint8_t OPERATION_MAX_TYPE = 3; constexpr int32_t LONG_LONG_STR_MAX_SIZE = 25600; constexpr int32_t COMMON_TEXT_SIZE = 3074; constexpr int32_t SHORT_TEXT_SIZE = 1026; +constexpr int32_t MAP_TEXT_SIZE = 514; constexpr int8_t NO_ERROR = 0; constexpr int8_t ERROR = -1; constexpr uint8_t PARAM0 = 0; @@ -1882,6 +1883,10 @@ public: const napi_env &env, const napi_value &contentResult, std::shared_ptr basicContent); static napi_value SetLockScreenPicture( const napi_env &env, const NotificationBasicContent *basicContent, napi_value &result); + static napi_value GetStructuredText( + const napi_env &env, const napi_value &contentResult, std::shared_ptr basicContent); + static napi_value SetStructuredText( + const napi_env &env, const NotificationBasicContent *basicContent, napi_value &result); static napi_value SetAgentBundle(const napi_env &env, const std::shared_ptr &agentBundle, napi_value &result); static napi_value GetResourceObject(napi_env env, std::shared_ptr &resource, @@ -1894,6 +1899,8 @@ public: uint32_t value); static std::string GetAppInstanceKey(); static void PictureScale(std::shared_ptr pixelMap); + static napi_value GetMapObject(const napi_env &env, const napi_value &object, + std::vector> &out); private: static const int32_t ARGS_ONE = 1; static const int32_t ARGS_TWO = 2; diff --git a/frameworks/js/napi/src/common_convert_content.cpp b/frameworks/js/napi/src/common_convert_content.cpp index 8348d08c4..412ab819d 100644 --- a/frameworks/js/napi/src/common_convert_content.cpp +++ b/frameworks/js/napi/src/common_convert_content.cpp @@ -155,7 +155,14 @@ napi_value Common::SetNotificationBasicContent( napi_set_named_property(env, result, "additionalText", value); // lockScreenPicture?: pixelMap - return SetLockScreenPicture(env, basicContent, result); + SetLockScreenPicture(env, basicContent, result); + + // structuredText?: Map + if (SetStructuredText(env, basicContent, result) == nullptr) { + ANS_LOGE("SetStructuredText failed."); + } + + return NapiGetBoolean(env, true); } napi_value Common::SetNotificationLongTextContent( @@ -611,6 +618,11 @@ napi_value Common::GetNotificationBasicContentDetailed( basicContent->SetAdditionalText(commonStr); } + // structuredText?: Map + if (GetStructuredText(env, contentResult, basicContent) == nullptr) { + return nullptr; + } + // lockScreenPicture?: pixelMap return GetLockScreenPicture(env, contentResult, basicContent); } @@ -1585,5 +1597,108 @@ napi_value Common::SetLockScreenPicture( return NapiGetBoolean(env, true); } + +napi_value Common::GetMapObject(const napi_env &env, const napi_value &object, + std::vector> &out) +{ + napi_value entriesFn = nullptr; + napi_value iter = nullptr; + napi_value nextFn = nullptr; + NAPI_CALL(env, napi_get_named_property(env, object, "entries", &entriesFn)); + NAPI_CALL(env, napi_call_function(env, object, entriesFn, 0, nullptr, &iter)); + NAPI_CALL(env, napi_get_named_property(env, iter, "next", &nextFn)); + + auto toStdString = [&](napi_value v) -> std::string { + char buf[MAP_TEXT_SIZE] = {0}; + size_t len = 0; + NAPI_CALL(env, napi_get_value_string_utf8(env, v, buf, MAP_TEXT_SIZE - 1, &len)); + return std::string(buf, len); + }; + + bool done = false; + while (!done) { + napi_value resultObj; + NAPI_CALL(env, napi_call_function(env, iter, nextFn, 0, nullptr, &resultObj)); + + napi_value doneVal; + NAPI_CALL(env, napi_get_named_property(env, resultObj, "done", &doneVal)); + + NAPI_CALL(env, napi_get_value_bool(env, doneVal, &done)); + if (done) { + break; + } + + napi_value pairArr; + NAPI_CALL(env, napi_get_named_property(env, resultObj, "value", &pairArr)); + napi_value jsKey = nullptr; + napi_value jsVal = nullptr; + NAPI_CALL(env, napi_get_element(env, pairArr, 0, &jsKey)); + NAPI_CALL(env, napi_get_element(env, pairArr, 1, &jsVal)); + + out.emplace_back(std::make_pair( + toStdString(jsKey), toStdString(jsVal))); + } + + return NapiGetNull(env); +} + +napi_value Common::GetStructuredText( + const napi_env &env, const napi_value &contentResult, std::shared_ptr basicContent) +{ + ANS_LOGD("enter"); + std::vector> structuredTexts; + bool hasProperty = false; + napi_value jsStMap = nullptr; + napi_valuetype jsType = napi_undefined; + + NAPI_CALL(env, napi_has_named_property(env, contentResult, "structuredText", &hasProperty)); + if (!hasProperty) { + ANS_LOGD("Null structuredText"); + return NapiGetNull(env); + } + + NAPI_CALL(env, napi_get_named_property(env, contentResult, "structuredText", &jsStMap)); + NAPI_CALL(env, napi_typeof(env, jsStMap, &jsType)); + if (jsType != napi_object) { + ANS_LOGE("Wrong argument type. Obejct expected."); + std::string msg = "Incorrect parameter types. The type of normal must be object."; + Common::NapiThrow(env, ERROR_PARAM_INVALID, msg); + return nullptr; + } + + if (GetMapObject(env, jsStMap, structuredTexts) == nullptr) { + ANS_LOGE("GetMapObject failed."); + return NapiGetNull(env); + } + + basicContent->SetStructuredText(structuredTexts); + return NapiGetNull(env); +} + +napi_value Common::SetStructuredText( + const napi_env &env, const NotificationBasicContent *basicContent, napi_value &result) +{ + ANS_LOGD("enter"); + const auto& texts = basicContent->GetStructuredText(); + if (texts.empty()) { + return NapiGetNull(env); + } + + napi_value jsMap = nullptr; + NAPI_CALL(env, napi_create_map(env, &jsMap)); + + for (const auto& [k, v] : texts) { + napi_value jsKey = nullptr; + napi_value jsValue = nullptr; + + NAPI_CALL(env, napi_create_string_utf8(env, k.c_str(), k.size(), &jsKey)); + NAPI_CALL(env, napi_create_string_utf8(env, v.c_str(), v.size(), &jsValue)); + + NAPI_CALL(env, napi_map_set_property(env, jsMap, jsKey, jsValue)); + } + + NAPI_CALL(env, napi_set_named_property(env, result, "structuredText", jsMap)); + return NapiGetNull(env); +} } } diff --git a/interfaces/inner_api/notification_basic_content.h b/interfaces/inner_api/notification_basic_content.h index 22e336945..00290993e 100644 --- a/interfaces/inner_api/notification_basic_content.h +++ b/interfaces/inner_api/notification_basic_content.h @@ -84,6 +84,20 @@ public: */ virtual std::shared_ptr GetLockScreenPicture() const; + /** + * @brief Sets the structuredText of a notification. + * + * @param structuredText Indicates the structuredText of the notification. + */ + virtual void SetStructuredText(const std::vector> &structuredText); + + /** + * @brief Obtains the structuredText of a notification. + * + * @return Returns the structuredText of the notification. + */ + virtual std::vector> GetStructuredText() const; + /** * @brief Returns a string representation of the object. * @@ -136,6 +150,7 @@ protected: std::string additionalText_ {}; std::shared_ptr lockScreenPicture_ {}; int32_t contentType_; + std::vector> structuredText_ {}; }; } // namespace Notification } // namespace OHOS -- Gitee