diff --git a/interfaces/ets/ani/promptaction/BUILD.gn b/interfaces/ets/ani/promptaction/BUILD.gn index 353ed7daef1faf11b1981dd8f12b1b76415157a4..691bb0e3f7478b6bd9a5d8b477a29853a501e6b3 100644 --- a/interfaces/ets/ani/promptaction/BUILD.gn +++ b/interfaces/ets/ani/promptaction/BUILD.gn @@ -24,6 +24,7 @@ ohos_shared_library("promptAction_ani") { "./src/prompt_action_params.cpp", "./src/toast_params.cpp", "./src/dialog_params.cpp", + "./src/prompt_action_utils", ] external_deps = [ #"runtime_core:libarkruntime", diff --git a/interfaces/ets/ani/promptaction/src/dialog_params.cpp b/interfaces/ets/ani/promptaction/src/dialog_params.cpp index 804d7be3c660e7d020e01e5b9915735fe2a6d3e8..9a2be2773cd61191c7e6d0bbccbd9edcba53e528 100644 --- a/interfaces/ets/ani/promptaction/src/dialog_params.cpp +++ b/interfaces/ets/ani/promptaction/src/dialog_params.cpp @@ -14,6 +14,7 @@ */ #include "dialog_params.h" +#include "prompt_action_utils.h" #include "frameworks/base/error/error_code.h" #include "frameworks/base/i18n/localization.h" @@ -22,44 +23,6 @@ #include "frameworks/core/components_ng/base/view_stack_processor.h" #include "frameworks/core/interfaces/native/implementation/frame_node_peer_impl.h" -namespace OHOS::Ace::NG { -static const std::unordered_map ERROR_CODE_TO_MSG { - { ERROR_CODE_PERMISSION_DENIED, "Permission denied. " }, - { ERROR_CODE_PARAM_INVALID, "Parameter error. " }, - { ERROR_CODE_SYSTEMCAP_ERROR, "Capability not supported. " }, - { ERROR_CODE_INTERNAL_ERROR, "Internal error. " }, - { ERROR_CODE_URI_ERROR, "Uri error. " }, - { ERROR_CODE_PAGE_STACK_FULL, "Page stack error. " }, - { ERROR_CODE_URI_ERROR_LITE, "Uri error. " }, - { ERROR_CODE_DIALOG_CONTENT_ERROR, "Dialog content error. " }, - { ERROR_CODE_DIALOG_CONTENT_ALREADY_EXIST, "Dialog content already exist. " }, - { ERROR_CODE_DIALOG_CONTENT_NOT_FOUND, "Dialog content not found. " }, - { ERROR_CODE_TOAST_NOT_FOUND, "Toast not found. " } -}; - -std::string ErrorToMessage(int32_t code) -{ - auto iter = ERROR_CODE_TO_MSG.find(code); - return (iter != ERROR_CODE_TO_MSG.end()) ? iter->second : ""; -} - -std::string GetErrorMsg(int32_t errorCode) -{ - std::string strMsg; - if (errorCode == ERROR_CODE_DIALOG_CONTENT_ERROR) { - strMsg = ErrorToMessage(ERROR_CODE_DIALOG_CONTENT_ERROR) + "The ComponentContent is incorrect."; - } else if (errorCode == ERROR_CODE_DIALOG_CONTENT_ALREADY_EXIST) { - strMsg = ErrorToMessage(ERROR_CODE_DIALOG_CONTENT_ALREADY_EXIST) + - "The ComponentContent has already been opened."; - } else if (errorCode == ERROR_CODE_DIALOG_CONTENT_NOT_FOUND) { - strMsg = ErrorToMessage(ERROR_CODE_DIALOG_CONTENT_NOT_FOUND) + "The ComponentContent cannot be found."; - } else { - strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "Build custom dialog failed."; - } - return strMsg; -} -} // OHOS::Ace::NG - bool GetButtonInfo(ani_env* env, ani_ref resultRef, OHOS::Ace::ButtonInfo& result) { if (IsUndefinedObject(env, resultRef)) { @@ -1035,7 +998,7 @@ std::function GetOpenCustomDialogPromise(std::shared_ptrenv, errorCode, errorMsg); ani_error error = static_cast(errorRef); ani_status status = asyncContext->env->PromiseResolver_Reject(asyncContext->deferred, error); @@ -1092,7 +1055,7 @@ std::function GetCustomDialogContentPromise(std::shared_ptrenv, errorCode, strMsg); ani_error error = static_cast(errorRef); ani_status status = asyncContext->env->PromiseResolver_Reject(asyncContext->deferred, error); diff --git a/interfaces/ets/ani/promptaction/src/promptAction.cpp b/interfaces/ets/ani/promptaction/src/promptAction.cpp index c222e03ab551dda5409eac762e0cf82f9270c996..d27974558b2cbad8292a550dd6d21dc6e345219c 100644 --- a/interfaces/ets/ani/promptaction/src/promptAction.cpp +++ b/interfaces/ets/ani/promptaction/src/promptAction.cpp @@ -22,6 +22,7 @@ #include "prompt_action_params.h" #include "toast_params.h" #include "dialog_params.h" +#include "prompt_action_utils.h" #include "frameworks/base/error/error_code.h" #include "frameworks/base/utils/utils.h" @@ -84,13 +85,63 @@ static void showToast([[maybe_unused]] ani_env* env, ani_object options) static ani_object openToast([[maybe_unused]] ani_env* env, ani_object options) { TAG_LOGD(OHOS::Ace::AceLogTag::ACE_OVERLAY, "[ANI] openToast enter."); - ani_object result = {}; + auto toastInfo = + OHOS::Ace::NG::ToastInfo { .duration = -1, .showMode = OHOS::Ace::NG::ToastShowMode::DEFAULT, .alignment = -1 }; + if (!GetShowToastOptions(env, options, toastInfo)) { + return nullptr; + } + auto asyncContext = std::make_shared(); + asyncContext->env = env; + asyncContext->instanceId = OHOS::Ace::Container::CurrentIdSafely(); + ani_object result; + ani_status status = env->Promise_New(&asyncContext->deferred, &result); + if (status != ANI_OK) { + TAG_LOGW(OHOS::Ace::AceLogTag::ACE_DIALOG, "Create promise object fail."); + return nullptr; + } + std::function toastCallback = GetToastPromise(asyncContext); + if ((OHOS::Ace::SystemProperties::GetExtSurfaceEnabled() || !OHOS::Ace::NG::ContainerIsService()) && + !OHOS::Ace::NG::ContainerIsScenceBoard() && toastInfo.showMode == OHOS::Ace::NG::ToastShowMode::DEFAULT) { + OHOS::Ace::NG::DialogManagerStatic::ShowToastStatic( + toastInfo, std::move(toastCallback), OHOS::Ace::INSTANCE_ID_UNDEFINED); + } else if (OHOS::Ace::SubwindowManager::GetInstance() != nullptr) { + OHOS::Ace::SubwindowManager::GetInstance()->ShowToastStatic(toastInfo, std::move(toastCallback)); + } return result; } static void closeToast([[maybe_unused]] ani_env* env, ani_int toastId) { TAG_LOGD(OHOS::Ace::AceLogTag::ACE_OVERLAY, "[ANI] closeToast enter."); + std::function toastCloseCallback = nullptr; + toastCloseCallback = [env](int32_t errorCode) mutable { + if (errorCode != OHOS::Ace::ERROR_CODE_NO_ERROR) { + OHOS::Ace::Ani::AniThrow(env, "The toastId is invalid.", errorCode); + }; + }; + if (!toastId) { + toastCloseCallback(OHOS::Ace::ERROR_CODE_PARAM_INVALID); + return; + } + if (toastId < 0 || toastId > INT32_MAX) { + toastCloseCallback(OHOS::Ace::ERROR_CODE_PARAM_INVALID); + return; + } + int32_t showModeVal = static_cast(static_cast(toastId) & 0b111); + toastId = static_cast(static_cast(toastId) >> 3); + if (toastId < 0 || showModeVal < 0 || + showModeVal > static_cast(OHOS::Ace::NG::ToastShowMode::SYSTEM_TOP_MOST)) { + toastCloseCallback(OHOS::Ace::ERROR_CODE_TOAST_NOT_FOUND); + return; + } + auto showMode = static_cast(showModeVal); + if ((OHOS::Ace::SystemProperties::GetExtSurfaceEnabled() || !OHOS::Ace::NG::ContainerIsService()) && + !OHOS::Ace::NG::ContainerIsScenceBoard() && showMode == OHOS::Ace::NG::ToastShowMode::DEFAULT) { + OHOS::Ace::NG::DialogManagerStatic::CloseToastStatic( + toastId, std::move(toastCloseCallback), OHOS::Ace::INSTANCE_ID_UNDEFINED); + } else if (OHOS::Ace::SubwindowManager::GetInstance() != nullptr) { + OHOS::Ace::SubwindowManager::GetInstance()->CloseToastStatic(toastId, showMode, std::move(toastCloseCallback)); + } } static void showDialogWithCallback([[maybe_unused]] ani_env* env, ani_object options, ani_fn_object callback) diff --git a/interfaces/ets/ani/promptaction/src/prompt_action_utils.cpp b/interfaces/ets/ani/promptaction/src/prompt_action_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b696f2a525b42d05882e58c9217173af2886425c --- /dev/null +++ b/interfaces/ets/ani/promptaction/src/prompt_action_utils.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2025 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 "prompt_action_utils.h" + +#include "bridge/common/utils/utils.h" +#include "core/pipeline/pipeline_base.h" +#include "frameworks/base/error/error_code.h" + +namespace OHOS::Ace::Ani { +static const std::unordered_map ERROR_CODE_TO_MSG { + { ERROR_CODE_PERMISSION_DENIED, "Permission denied. " }, + { ERROR_CODE_PARAM_INVALID, "Parameter error. " }, + { ERROR_CODE_SYSTEMCAP_ERROR, "Capability not supported. " }, + { ERROR_CODE_INTERNAL_ERROR, "Internal error. " }, + { ERROR_CODE_URI_ERROR, "Uri error. " }, + { ERROR_CODE_PAGE_STACK_FULL, "Page stack error. " }, + { ERROR_CODE_URI_ERROR_LITE, "Uri error. " }, + { ERROR_CODE_DIALOG_CONTENT_ERROR, "Dialog content error. " }, + { ERROR_CODE_DIALOG_CONTENT_ALREADY_EXIST, "Dialog content already exist. " }, + { ERROR_CODE_DIALOG_CONTENT_NOT_FOUND, "Dialog content not found. " }, + { ERROR_CODE_TOAST_NOT_FOUND, "Toast not found. " } +}; + +std::string ErrorToMessage(int32_t code) +{ + auto iter = ERROR_CODE_TO_MSG.find(code); + return (iter != ERROR_CODE_TO_MSG.end()) ? iter->second : ""; +} + +std::string GetErrorMsg(int32_t errorCode) +{ + std::string strMsg; + if (errorCode == ERROR_CODE_DIALOG_CONTENT_ERROR) { + strMsg = ErrorToMessage(ERROR_CODE_DIALOG_CONTENT_ERROR) + "The ComponentContent is incorrect."; + } else if (errorCode == ERROR_CODE_DIALOG_CONTENT_ALREADY_EXIST) { + strMsg = ErrorToMessage(ERROR_CODE_DIALOG_CONTENT_ALREADY_EXIST) + + "The ComponentContent has already been opened."; + } else if (errorCode == ERROR_CODE_DIALOG_CONTENT_NOT_FOUND) { + strMsg = ErrorToMessage(ERROR_CODE_DIALOG_CONTENT_NOT_FOUND) + "The ComponentContent cannot be found."; + } else { + strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "Build custom dialog failed."; + } + return strMsg; +} + + +ani_error GetErrorObject(ani_env *env, const std::string &errMsg, int32_t code) +{ + CHECK_NULL_RETURN(env, nullptr); + ani_class errClass; + if (ANI_OK != env->FindClass("L@ohos/base/BusinessError;", &errClass)) { + TAG_LOGE(AceLogTag::ACE_DRAG, "find class failed"); + return nullptr; + } + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(errClass, "", ":V", &ctor)) { + TAG_LOGE(AceLogTag::ACE_DRAG, "cannot find constructor for class."); + return nullptr; + } + ani_string errMessage; + if (ANI_OK != env->String_NewUTF8(errMsg.c_str(), errMsg.size(), &errMessage)) { + TAG_LOGE(AceLogTag::ACE_DRAG, "convert string to ani string failed."); + return nullptr; + } + ani_object errObj; + if (ANI_OK != env->Object_New(errClass, ctor, &errObj)) { + TAG_LOGE(AceLogTag::ACE_DRAG, "cannot create ani error object."); + return nullptr; + } + if (ANI_OK != env->Object_SetFieldByName_Double(errObj, "code", static_cast(code))) { + TAG_LOGE(AceLogTag::ACE_DRAG, "set error code failed."); + return nullptr; + } + if (ANI_OK != env->Object_SetPropertyByName_Ref(errObj, "message", errMessage)) { + TAG_LOGE(AceLogTag::ACE_DRAG, "set error message failed."); + return nullptr; + } + return static_cast(errObj); +} + +void AniThrow(ani_env *env, const std::string &errMsg, int32_t code) +{ + CHECK_NULL_VOID(env); + auto errObj = GetErrorObject(env, errMsg, code); + if (errObj == nullptr) { + TAG_LOGE(AceLogTag::ACE_DRAG, "get error object failed!"); + return; + } + if (ANI_OK != env->ThrowError(errObj)) { + TAG_LOGE(AceLogTag::ACE_DRAG, "throw ani error object failed!"); + return; + } +} +} // namespace OHOS::Ace::Ani \ No newline at end of file diff --git a/interfaces/ets/ani/promptaction/src/prompt_action_utils.h b/interfaces/ets/ani/promptaction/src/prompt_action_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..ff82e964e8644d0e533c63169baac85f4e34e112 --- /dev/null +++ b/interfaces/ets/ani/promptaction/src/prompt_action_utils.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 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 INTERFACES_ETS_ANI_PROMPT_ACTION_UTILS_H +#define INTERFACES_ETS_ANI_PROMPT_ACTION_UTILS_H + +#include +#include +#include + +#include "core/common/ace_engine.h" +#include "frameworks/base/error/error_code.h" +#include "frameworks/base/log/log_wrapper.h" + +namespace OHOS::Ace::Ani { +std::string ErrorToMessage(int32_t code); +std::string GetErrorMsg(int32_t errorCode); +ani_error GetErrorObject(ani_env* env, const std::string& errMsg, int32_t code); +void AniThrow(ani_env* env, const std::string& errMsg, int32_t code); +} // namespace OHOS::Ace::Ani +#endif // #define INTERFACES_ETS_ANI_PROMPT_ACTION_UTILS_H \ No newline at end of file diff --git a/interfaces/ets/ani/promptaction/src/toast_params.cpp b/interfaces/ets/ani/promptaction/src/toast_params.cpp index 75d17cbb9601591f03a8df0774431fd714deb1c9..cbaca17c88fcfd57aa420e4ed97266c2a4d29987 100644 --- a/interfaces/ets/ani/promptaction/src/toast_params.cpp +++ b/interfaces/ets/ani/promptaction/src/toast_params.cpp @@ -14,6 +14,7 @@ */ #include "toast_params.h" +#include "prompt_action_utils.h" std::unordered_map alignmentMap = { {"TopStart", 0}, @@ -117,7 +118,9 @@ bool GetShowToastOptions(ani_env* env, ani_object object, OHOS::Ace::NG::ToastIn } GetResourceStrParam(env, object, "message", result.message); - GetInt32Param(env, object, "duration", result.duration); + double duration = 0; + GetDoubleParam(env, object, "duration", duration); + result.duration = static_cast(duration); GetToastBottom(env, object, result.bottom); GetToastShowMode(env, object, result.showMode); GetToastAlignment(env, object, result.alignment); @@ -129,4 +132,63 @@ bool GetShowToastOptions(ani_env* env, ani_object object, OHOS::Ace::NG::ToastIn GetBoolParam(env, object, "enableHoverMode", result.enableHoverMode); GetHoverModeAreaParam(env, object, result.hoverModeArea); return true; +} + +std::function GetToastPromise(std::shared_ptr& asyncContext) +{ + auto callback = [asyncContext](int32_t dialogId) mutable { + if (!asyncContext) { + return; + } + + auto container = OHOS::Ace::AceEngine::Get().GetContainer(asyncContext->instanceId); + if (!container) { + return; + } + + auto taskExecutor = container->GetTaskExecutor(); + if (!taskExecutor) { + return; + } + + auto task = [asyncContext, dialogId]() { + if (asyncContext == nullptr) { + return; + } + + if (!asyncContext->deferred) { + return; + } + + ani_size nrRefs = 16; + asyncContext->env->CreateLocalScope(nrRefs); + if (!nrRefs) { + return; + } + + if (dialogId > 0) { + double returnDialogId = static_cast(dialogId); + ani_object dialogIdObj = CreateANIDoubleObject(asyncContext->env, returnDialogId); + ani_ref dialogRef = static_cast(dialogIdObj); + ani_status status = asyncContext->env->PromiseResolver_Resolve(asyncContext->deferred, dialogRef); + if (status != ANI_OK) { + TAG_LOGW(OHOS::Ace::AceLogTag::ACE_DIALOG, "[ANI] PromiseResolver_Resolve fail."); + } + } else { + int32_t errorCode = OHOS::Ace::ERROR_CODE_INTERNAL_ERROR; + std::string errorMsg = OHOS::Ace::Ani::GetErrorMsg(errorCode); + ani_ref errorRef = CreateBusinessError(asyncContext->env, errorCode, errorMsg); + ani_error error = static_cast(errorRef); + ani_status status = asyncContext->env->PromiseResolver_Reject(asyncContext->deferred, error); + if (status != ANI_OK) { + TAG_LOGW(OHOS::Ace::AceLogTag::ACE_DIALOG, "[ANI] PromiseResolver_Reject fail."); + } + } + asyncContext->env->DestroyLocalScope(); + }; + taskExecutor->PostTask( + std::move(task), OHOS::Ace::TaskExecutor::TaskType::JS, "ArkUIDialogParseCustomDialogIdCallback"); + asyncContext = nullptr; + }; + return callback; } \ No newline at end of file diff --git a/interfaces/ets/ani/promptaction/src/toast_params.h b/interfaces/ets/ani/promptaction/src/toast_params.h index 81594b071563997b761a01abc6617ac2953a4d05..5b04bf1f0b18896535ca1e93d40c3cf9ca033203 100644 --- a/interfaces/ets/ani/promptaction/src/toast_params.h +++ b/interfaces/ets/ani/promptaction/src/toast_params.h @@ -39,5 +39,6 @@ bool GetToastAlignment(ani_env *env, ani_object object, int32_t& result); bool GetToastShadow(ani_env *env, ani_object object, std::optional& result, bool& isTypeStyleShadow); bool GetShowToastOptions(ani_env* env, ani_object object, OHOS::Ace::NG::ToastInfo result); +std::function GetToastPromise(std::shared_ptr& asyncContext); #endif // INTERFACES_ETS_ANI_PROMPTACTION_SRC_TOAST_PARAMS_H \ No newline at end of file