1 /*
2 * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "prompt_action.h"
17
18 #include <cstddef>
19 #include <memory>
20 #include <string>
21
22 #include "interfaces/napi/kits/utils/napi_utils.h"
23 #include "base/i18n/localization.h"
24 #include "base/log/log_wrapper.h"
25 #include "base/subwindow/subwindow_manager.h"
26 #include "base/utils/system_properties.h"
27 #include "bridge/common/utils/engine_helper.h"
28 #include "core/common/ace_engine.h"
29 #include "core/components/common/properties/shadow.h"
30 #include "core/components/theme/shadow_theme.h"
31 #include "core/components_ng/pattern/toast/toast_layout_property.h"
32
33 namespace OHOS::Ace::Napi {
34 namespace {
35 const int32_t SHOW_DIALOG_BUTTON_NUM_MAX = -1;
36 const int32_t SHOW_ACTION_MENU_BUTTON_NUM_MAX = 6;
37 const int32_t CUSTOM_DIALOG_PARAM_NUM = 2;
38 const int32_t BG_BLUR_STYLE_MAX_INDEX = 12;
39 const int32_t PROMPTACTION_VALID_PRIMARY_BUTTON_NUM = 1;
40 constexpr char DEFAULT_FONT_COLOR_STRING_VALUE[] = "#ff007dff";
41 const std::vector<DialogAlignment> DIALOG_ALIGNMENT = { DialogAlignment::TOP, DialogAlignment::CENTER,
42 DialogAlignment::BOTTOM, DialogAlignment::DEFAULT, DialogAlignment::TOP_START, DialogAlignment::TOP_END,
43 DialogAlignment::CENTER_START, DialogAlignment::CENTER_END, DialogAlignment::BOTTOM_START,
44 DialogAlignment::BOTTOM_END };
45 const std::vector<KeyboardAvoidMode> KEYBOARD_AVOID_MODE = { KeyboardAvoidMode::DEFAULT, KeyboardAvoidMode::NONE };
46
47 #ifdef OHOS_STANDARD_SYSTEM
ContainerIsService()48 bool ContainerIsService()
49 {
50 auto containerId = Container::CurrentIdSafely();
51 // Get active container when current instanceid is less than 0
52 if (containerId < 0) {
53 auto container = Container::GetActive();
54 if (container) {
55 containerId = container->GetInstanceId();
56 }
57 }
58 // for pa service
59 return containerId >= MIN_PA_SERVICE_ID || containerId < 0;
60 }
61
ContainerIsScenceBoard()62 bool ContainerIsScenceBoard()
63 {
64 auto container = Container::CurrentSafely();
65 if (!container) {
66 container = Container::GetActive();
67 }
68
69 return container && container->IsScenceBoardWindow();
70 }
71 #endif
72 } // namespace
73
GetToastMessage(napi_env env,napi_value messageNApi,std::string & messageString)74 bool GetToastMessage(napi_env env, napi_value messageNApi, std::string& messageString)
75 {
76 size_t ret = 0;
77 ResourceInfo recv;
78 napi_valuetype valueType = napi_undefined;
79 napi_typeof(env, messageNApi, &valueType);
80 if (valueType == napi_string) {
81 size_t messageLen = GetParamLen(env, messageNApi) + 1;
82 std::unique_ptr<char[]> message = std::make_unique<char[]>(messageLen);
83 napi_get_value_string_utf8(env, messageNApi, message.get(), messageLen, &ret);
84 messageString = message.get();
85 } else if (valueType == napi_object) {
86 if (!ParseResourceParam(env, messageNApi, recv)) {
87 NapiThrow(env, "Can not parse resource info from input params.", ERROR_CODE_INTERNAL_ERROR);
88 return false;
89 }
90 if (!ParseString(recv, messageString)) {
91 NapiThrow(env, "Can not get message from resource manager.", ERROR_CODE_INTERNAL_ERROR);
92 return false;
93 }
94 if (messageString.size() == 0) {
95 TAG_LOGE(AceLogTag::ACE_DIALOG, "Toast message is empty");
96 }
97 } else {
98 NapiThrow(env, "The type of message is incorrect.", ERROR_CODE_PARAM_INVALID);
99 return false;
100 }
101 return true;
102 }
103
GetToastDuration(napi_env env,napi_value durationNApi,int32_t & duration)104 bool GetToastDuration(napi_env env, napi_value durationNApi, int32_t& duration)
105 {
106 napi_valuetype valueType = napi_undefined;
107 napi_typeof(env, durationNApi, &valueType);
108 ResourceInfo recv;
109 std::string durationStr;
110 if (valueType == napi_number) {
111 napi_get_value_int32(env, durationNApi, &duration);
112 } else if (valueType == napi_object) {
113 recv = {};
114 if (!ParseResourceParam(env, durationNApi, recv)) {
115 NapiThrow(env, "Can not parse resource info from input params.", ERROR_CODE_INTERNAL_ERROR);
116 return false;
117 }
118 if (!ParseString(recv, durationStr)) {
119 NapiThrow(env, "Can not get message from resource manager.", ERROR_CODE_INTERNAL_ERROR);
120 return false;
121 }
122 duration = StringUtils::StringToInt(durationStr);
123 }
124 return true;
125 }
126
GetToastBottom(napi_env env,napi_value bottomNApi,std::string & bottomString)127 bool GetToastBottom(napi_env env, napi_value bottomNApi, std::string& bottomString)
128 {
129 size_t ret = 0;
130 ResourceInfo recv;
131 napi_valuetype valueType = napi_undefined;
132 napi_typeof(env, bottomNApi, &valueType);
133 if (valueType == napi_string) {
134 size_t bottomLen = GetParamLen(env, bottomNApi) + 1;
135 std::unique_ptr<char[]> bottom = std::make_unique<char[]>(bottomLen);
136 napi_get_value_string_utf8(env, bottomNApi, bottom.get(), bottomLen, &ret);
137 bottomString = bottom.get();
138 } else if (valueType == napi_number) {
139 double bottom = 0.0;
140 napi_get_value_double(env, bottomNApi, &bottom);
141 bottomString = std::to_string(bottom);
142 } else if (valueType == napi_object) {
143 recv = {};
144 if (!ParseResourceParam(env, bottomNApi, recv)) {
145 NapiThrow(env, "Can not parse resource info from input params.", ERROR_CODE_INTERNAL_ERROR);
146 return false;
147 }
148 if (!ParseString(recv, bottomString)) {
149 NapiThrow(env, "Can not get message from resource manager.", ERROR_CODE_INTERNAL_ERROR);
150 return false;
151 }
152 }
153 return true;
154 }
155
GetToastShowMode(napi_env env,napi_value showModeNApi,NG::ToastShowMode & showMode)156 bool GetToastShowMode(napi_env env, napi_value showModeNApi, NG::ToastShowMode& showMode)
157 {
158 napi_valuetype valueType = napi_undefined;
159 napi_typeof(env, showModeNApi, &valueType);
160 if (valueType == napi_number) {
161 int32_t num = -1;
162 napi_get_value_int32(env, showModeNApi, &num);
163 if (num >= 0 && num <= static_cast<int32_t>(NG::ToastShowMode::SYSTEM_TOP_MOST)) {
164 showMode = static_cast<NG::ToastShowMode>(num);
165 }
166 }
167 return true;
168 }
169
GetToastAlignment(napi_env env,napi_value alignmentApi,int32_t & alignment)170 bool GetToastAlignment(napi_env env, napi_value alignmentApi, int32_t& alignment)
171 {
172 napi_valuetype valueType = napi_undefined;
173 napi_typeof(env, alignmentApi, &valueType);
174 if (valueType == napi_number) {
175 napi_get_value_int32(env, alignmentApi, &alignment);
176 }
177 return true;
178 }
179
GetToastOffset(napi_env env,napi_value offsetApi,std::optional<DimensionOffset> & offset)180 bool GetToastOffset(napi_env env, napi_value offsetApi, std::optional<DimensionOffset>& offset)
181 {
182 napi_valuetype valueType = napi_undefined;
183 napi_typeof(env, offsetApi, &valueType);
184 if (valueType == napi_object) {
185 napi_value dxApi = nullptr;
186 napi_value dyApi = nullptr;
187 napi_get_named_property(env, offsetApi, "dx", &dxApi);
188 napi_get_named_property(env, offsetApi, "dy", &dyApi);
189 CalcDimension dx;
190 CalcDimension dy;
191 ParseNapiDimension(env, dx, dxApi, DimensionUnit::VP);
192 ParseNapiDimension(env, dy, dyApi, DimensionUnit::VP);
193 offset = DimensionOffset { dx, dy };
194 }
195 return true;
196 }
197
GetToastBackgroundColor(napi_env env,napi_value backgroundColorNApi,std::optional<Color> & backgroundColor)198 void GetToastBackgroundColor(napi_env env, napi_value backgroundColorNApi, std::optional<Color>& backgroundColor)
199 {
200 napi_valuetype valueType = napi_undefined;
201 napi_typeof(env, backgroundColorNApi, &valueType);
202 Color color;
203 backgroundColor = std::nullopt;
204 if (ParseNapiColor(env, backgroundColorNApi, color)) {
205 backgroundColor = color;
206 }
207 }
208
GetToastTextColor(napi_env env,napi_value textColorNApi,std::optional<Color> & textColor)209 void GetToastTextColor(napi_env env, napi_value textColorNApi, std::optional<Color>& textColor)
210 {
211 napi_valuetype valueType = napi_undefined;
212 napi_typeof(env, textColorNApi, &valueType);
213 Color color;
214 textColor = std::nullopt;
215 if (ParseNapiColor(env, textColorNApi, color)) {
216 textColor = color;
217 }
218 }
219
GetToastBackgroundBlurStyle(napi_env env,napi_value backgroundBlurStyleNApi,std::optional<int32_t> & backgroundBlurStyle)220 void GetToastBackgroundBlurStyle(napi_env env,
221 napi_value backgroundBlurStyleNApi, std::optional<int32_t>& backgroundBlurStyle)
222 {
223 napi_valuetype valueType = napi_undefined;
224 napi_typeof(env, backgroundBlurStyleNApi, &valueType);
225 if (valueType == napi_number) {
226 int32_t num;
227 napi_get_value_int32(env, backgroundBlurStyleNApi, &num);
228 if (num >= 0 && num < BG_BLUR_STYLE_MAX_INDEX) {
229 backgroundBlurStyle = num;
230 }
231 }
232 }
233
GetShadowFromTheme(ShadowStyle shadowStyle,Shadow & shadow)234 bool GetShadowFromTheme(ShadowStyle shadowStyle, Shadow& shadow)
235 {
236 auto colorMode = SystemProperties::GetColorMode();
237 if (shadowStyle == ShadowStyle::None) {
238 return true;
239 }
240 auto container = Container::CurrentSafelyWithCheck();
241 CHECK_NULL_RETURN(container, false);
242 auto pipelineContext = container->GetPipelineContext();
243 CHECK_NULL_RETURN(pipelineContext, false);
244 auto shadowTheme = pipelineContext->GetTheme<ShadowTheme>();
245 if (!shadowTheme) {
246 return false;
247 }
248 shadow = shadowTheme->GetShadow(shadowStyle, colorMode);
249 return true;
250 }
251
ParseResource(const ResourceInfo resource,CalcDimension & result)252 bool ParseResource(const ResourceInfo resource, CalcDimension& result)
253 {
254 auto resourceWrapper = CreateResourceWrapper(resource);
255 CHECK_NULL_RETURN(resourceWrapper, false);
256 if (resource.type == static_cast<uint32_t>(ResourceType::STRING)) {
257 auto value = resourceWrapper->GetString(resource.resId);
258 return StringUtils::StringToCalcDimensionNG(value, result, false);
259 }
260 if (resource.type == static_cast<uint32_t>(ResourceType::INTEGER)) {
261 auto value = std::to_string(resourceWrapper->GetInt(resource.resId));
262 StringUtils::StringToDimensionWithUnitNG(value, result);
263 return true;
264 }
265 if (resource.type == static_cast<uint32_t>(ResourceType::FLOAT)) {
266 result = resourceWrapper->GetDimension(resource.resId);
267 return true;
268 }
269 return false;
270 }
271
GetToastObjectShadow(napi_env env,napi_value shadowNApi,Shadow & shadowProps)272 void GetToastObjectShadow(napi_env env, napi_value shadowNApi, Shadow& shadowProps)
273 {
274 napi_value radiusApi = nullptr;
275 napi_value colorApi = nullptr;
276 napi_value typeApi = nullptr;
277 napi_value fillApi = nullptr;
278 napi_get_named_property(env, shadowNApi, "radius", &radiusApi);
279 napi_get_named_property(env, shadowNApi, "color", &colorApi);
280 napi_get_named_property(env, shadowNApi, "type", &typeApi);
281 napi_get_named_property(env, shadowNApi, "fill", &fillApi);
282 ResourceInfo recv;
283 double radiusValue = 0.0;
284 if (ParseResourceParam(env, radiusApi, recv)) {
285 CalcDimension radius;
286 if (ParseResource(recv, radius)) {
287 radiusValue = LessNotEqual(radius.Value(), 0.0) ? 0.0 : radius.Value();
288 }
289 } else {
290 napi_get_value_double(env, radiusApi, &radiusValue);
291 if (LessNotEqual(radiusValue, 0.0)) {
292 radiusValue = 0.0;
293 }
294 }
295 shadowProps.SetBlurRadius(radiusValue);
296 Color color;
297 ShadowColorStrategy shadowColorStrategy;
298 if (ParseShadowColorStrategy(env, colorApi, shadowColorStrategy)) {
299 shadowProps.SetShadowColorStrategy(shadowColorStrategy);
300 } else if (ParseNapiColor(env, colorApi, color)) {
301 shadowProps.SetColor(color);
302 }
303 napi_valuetype valueType = GetValueType(env, typeApi);
304 int32_t shadowType = static_cast<int32_t>(ShadowType::COLOR);
305 if (valueType == napi_number) {
306 napi_get_value_int32(env, typeApi, &shadowType);
307 }
308 if (shadowType != static_cast<int32_t>(ShadowType::BLUR)) {
309 shadowType = static_cast<int32_t>(ShadowType::COLOR);
310 }
311 shadowType =
312 std::clamp(shadowType, static_cast<int32_t>(ShadowType::COLOR), static_cast<int32_t>(ShadowType::BLUR));
313 shadowProps.SetShadowType(static_cast<ShadowType>(shadowType));
314 valueType = GetValueType(env, fillApi);
315 bool isFilled = false;
316 if (valueType == napi_boolean) {
317 napi_get_value_bool(env, fillApi, &isFilled);
318 }
319 shadowProps.SetIsFilled(isFilled);
320 }
321
GetToastShadow(napi_env env,napi_value shadowNApi,std::optional<Shadow> & shadow,bool & isTypeStyleShadow)322 void GetToastShadow(napi_env env, napi_value shadowNApi, std::optional<Shadow>& shadow, bool& isTypeStyleShadow)
323 {
324 Shadow shadowProps;
325 napi_valuetype valueType = napi_undefined;
326 napi_typeof(env, shadowNApi, &valueType);
327 GetShadowFromTheme(ShadowStyle::OuterDefaultMD, shadowProps);
328 if (valueType == napi_number) {
329 int32_t num = 0;
330 napi_get_value_int32(env, shadowNApi, &num);
331 auto style = static_cast<ShadowStyle>(num);
332 GetShadowFromTheme(style, shadowProps);
333 } else if (valueType == napi_object) {
334 napi_value offsetXApi = nullptr;
335 napi_value offsetYApi = nullptr;
336 napi_get_named_property(env, shadowNApi, "offsetX", &offsetXApi);
337 napi_get_named_property(env, shadowNApi, "offsetY", &offsetYApi);
338 ResourceInfo recv;
339 bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
340 if (ParseResourceParam(env, offsetXApi, recv)) {
341 CalcDimension offsetX;
342 if (ParseResource(recv, offsetX)) {
343 double xValue = isRtl ? offsetX.Value() * (-1) : offsetX.Value();
344 shadowProps.SetOffsetX(xValue);
345 }
346 } else {
347 CalcDimension offsetX;
348 if (ParseNapiDimension(env, offsetX, offsetXApi, DimensionUnit::VP)) {
349 double xValue = isRtl ? offsetX.Value() * (-1) : offsetX.Value();
350 shadowProps.SetOffsetX(xValue);
351 }
352 }
353 if (ParseResourceParam(env, offsetYApi, recv)) {
354 CalcDimension offsetY;
355 if (ParseResource(recv, offsetY)) {
356 shadowProps.SetOffsetY(offsetY.Value());
357 }
358 } else {
359 CalcDimension offsetY;
360 if (ParseNapiDimension(env, offsetY, offsetYApi, DimensionUnit::VP)) {
361 shadowProps.SetOffsetY(offsetY.Value());
362 }
363 }
364 GetToastObjectShadow(env, shadowNApi, shadowProps);
365 isTypeStyleShadow = false;
366 }
367 shadow = shadowProps;
368 }
369
GetToastParams(napi_env env,napi_value argv,NG::ToastInfo & toastInfo)370 bool GetToastParams(napi_env env, napi_value argv, NG::ToastInfo& toastInfo)
371 {
372 napi_value messageNApi = nullptr;
373 napi_value durationNApi = nullptr;
374 napi_value bottomNApi = nullptr;
375 napi_value showModeNApi = nullptr;
376 napi_value alignmentApi = nullptr;
377 napi_value offsetApi = nullptr;
378 napi_value backgroundColorNApi = nullptr;
379 napi_value textColorNApi = nullptr;
380 napi_value backgroundBlurStyleNApi = nullptr;
381 napi_value shadowNApi = nullptr;
382
383 napi_valuetype valueType = napi_undefined;
384 napi_typeof(env, argv, &valueType);
385 if (valueType == napi_object) {
386 // message can not be null
387 if (!HasProperty(env, argv, "message")) {
388 NapiThrow(env, "Required input parameters are missing.", ERROR_CODE_PARAM_INVALID);
389 return false;
390 }
391 napi_get_named_property(env, argv, "message", &messageNApi);
392 napi_get_named_property(env, argv, "duration", &durationNApi);
393 napi_get_named_property(env, argv, "bottom", &bottomNApi);
394 napi_get_named_property(env, argv, "showMode", &showModeNApi);
395 napi_get_named_property(env, argv, "alignment", &alignmentApi);
396 napi_get_named_property(env, argv, "offset", &offsetApi);
397 napi_get_named_property(env, argv, "backgroundColor", &backgroundColorNApi);
398 napi_get_named_property(env, argv, "textColor", &textColorNApi);
399 napi_get_named_property(env, argv, "backgroundBlurStyle", &backgroundBlurStyleNApi);
400 napi_get_named_property(env, argv, "shadow", &shadowNApi);
401 } else {
402 NapiThrow(env, "The type of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
403 return false;
404 }
405 if (!GetToastMessage(env, messageNApi, toastInfo.message) ||
406 !GetToastDuration(env, durationNApi, toastInfo.duration) ||
407 !GetToastBottom(env, bottomNApi, toastInfo.bottom) ||
408 !GetToastShowMode(env, showModeNApi, toastInfo.showMode) ||
409 !GetToastAlignment(env, alignmentApi, toastInfo.alignment) ||
410 !GetToastOffset(env, offsetApi, toastInfo.offset)) {
411 return false;
412 }
413 GetToastBackgroundColor(env, backgroundColorNApi, toastInfo.backgroundColor);
414 GetToastTextColor(env, textColorNApi, toastInfo.textColor);
415 GetToastBackgroundBlurStyle(env, backgroundBlurStyleNApi, toastInfo.backgroundBlurStyle);
416 GetToastShadow(env, shadowNApi, toastInfo.shadow, toastInfo.isTypeStyleShadow);
417 return true;
418 }
419
ShowToast(napi_env env,NG::ToastInfo & toastInfo)420 bool ShowToast(napi_env env, NG::ToastInfo& toastInfo)
421 {
422 #ifdef OHOS_STANDARD_SYSTEM
423 if ((SystemProperties::GetExtSurfaceEnabled() || !ContainerIsService()) && !ContainerIsScenceBoard() &&
424 toastInfo.showMode == NG::ToastShowMode::DEFAULT) {
425 auto delegate = EngineHelper::GetCurrentDelegateSafely();
426 if (!delegate) {
427 NapiThrow(env, "Can not get delegate.", ERROR_CODE_INTERNAL_ERROR);
428 return false;
429 }
430 TAG_LOGD(AceLogTag::ACE_DIALOG, "before delegate show toast");
431 delegate->ShowToast(toastInfo);
432 } else if (SubwindowManager::GetInstance() != nullptr) {
433 TAG_LOGD(AceLogTag::ACE_DIALOG, "before subwindow manager show toast");
434 SubwindowManager::GetInstance()->ShowToast(toastInfo);
435 }
436 #else
437 auto delegate = EngineHelper::GetCurrentDelegateSafely();
438 if (!delegate) {
439 NapiThrow(env, "UI execution context not found.", ERROR_CODE_INTERNAL_ERROR);
440 return false;
441 }
442 if (toastInfo.showMode == NG::ToastShowMode::DEFAULT) {
443 TAG_LOGD(AceLogTag::ACE_DIALOG, "before delegate show toast");
444 delegate->ShowToast(toastInfo);
445 } else if (SubwindowManager::GetInstance() != nullptr) {
446 TAG_LOGD(AceLogTag::ACE_DIALOG, "before subwindow manager show toast");
447 SubwindowManager::GetInstance()->ShowToast(toastInfo);
448 }
449 #endif
450 return true;
451 }
452
JSPromptShowToast(napi_env env,napi_callback_info info)453 napi_value JSPromptShowToast(napi_env env, napi_callback_info info)
454 {
455 TAG_LOGD(AceLogTag::ACE_DIALOG, "show toast enter");
456 size_t requireArgc = 1;
457 size_t argc = 1;
458 napi_value argv = nullptr;
459 napi_value thisVar = nullptr;
460 void* data = nullptr;
461 napi_get_cb_info(env, info, &argc, &argv, &thisVar, &data);
462 if (argc != requireArgc) {
463 NapiThrow(env, "The number of parameters must be equal to 1.", ERROR_CODE_PARAM_INVALID);
464 return nullptr;
465 }
466 auto toastInfo = NG::ToastInfo { .duration = -1, .showMode = NG::ToastShowMode::DEFAULT, .alignment = -1 };
467 if (!GetToastParams(env, argv, toastInfo)) {
468 return nullptr;
469 }
470 ShowToast(env, toastInfo);
471 return nullptr;
472 }
473
474 struct PromptAsyncContext {
475 napi_env env = nullptr;
476 napi_value titleNApi = nullptr;
477 napi_value messageNApi = nullptr;
478 napi_value buttonsNApi = nullptr;
479 napi_value autoCancel = nullptr;
480 napi_value showInSubWindow = nullptr;
481 napi_value isModal = nullptr;
482 napi_value alignmentApi = nullptr;
483 napi_value offsetApi = nullptr;
484 napi_value maskRectApi = nullptr;
485 napi_value builder = nullptr;
486 napi_value onWillDismiss = nullptr;
487 napi_value backgroundColorApi = nullptr;
488 napi_value backgroundBlurStyleApi = nullptr;
489 napi_value borderWidthApi = nullptr;
490 napi_value borderColorApi = nullptr;
491 napi_value borderStyleApi = nullptr;
492 napi_value borderRadiusApi = nullptr;
493 napi_value shadowApi = nullptr;
494 napi_value widthApi = nullptr;
495 napi_value heightApi = nullptr;
496 napi_value frameNodePtr = nullptr;
497 napi_value maskColorApi = nullptr;
498 napi_value onDidAppear = nullptr;
499 napi_value onDidDisappear = nullptr;
500 napi_value onWillAppear = nullptr;
501 napi_value onWillDisappear = nullptr;
502 napi_value transitionApi = nullptr;
503 napi_ref callbackSuccess = nullptr;
504 napi_ref callbackCancel = nullptr;
505 napi_ref callbackComplete = nullptr;
506 std::string titleString;
507 std::string messageString;
508 std::vector<ButtonInfo> buttons;
509 bool autoCancelBool = true;
510 bool showInSubWindowBool = false;
511 bool isModalBool = true;
512 std::set<std::string> callbacks;
513 std::string callbackSuccessString;
514 std::string callbackCancelString;
515 std::string callbackCompleteString;
516 napi_deferred deferred = nullptr;
517 napi_ref callbackRef = nullptr;
518 napi_ref builderRef = nullptr;
519 napi_ref onWillDismissRef = nullptr;
520 int32_t callbackType = -1;
521 int32_t successType = -1;
522 bool valid = true;
523 int32_t instanceId = -1;
524 void* nativePtr = nullptr;
525 napi_ref onDidAppearRef = nullptr;
526 napi_ref onDidDisappearRef = nullptr;
527 napi_ref onWillAppearRef = nullptr;
528 napi_ref onWillDisappearRef = nullptr;
529 napi_value keyboardAvoidModeApi = nullptr;
530 };
531
DeleteContextAndThrowError(napi_env env,std::shared_ptr<PromptAsyncContext> & context,const std::string & errorMessage)532 void DeleteContextAndThrowError(
533 napi_env env, std::shared_ptr<PromptAsyncContext>& context, const std::string& errorMessage)
534 {
535 if (!context) {
536 // context is null, no need to delete
537 return;
538 }
539 NapiThrow(env, errorMessage, ERROR_CODE_PARAM_INVALID);
540 }
541
GetButtonArraryLen(napi_env env,std::shared_ptr<PromptAsyncContext> & context,int32_t maxButtonNum)542 int32_t GetButtonArraryLen(napi_env env, std::shared_ptr<PromptAsyncContext>& context,
543 int32_t maxButtonNum)
544 {
545 uint32_t buttonsLen = 0;
546 napi_get_array_length(env, context->buttonsNApi, &buttonsLen);
547 int32_t buttonsLenInt = static_cast<int32_t>(buttonsLen);
548 if (buttonsLenInt > maxButtonNum && maxButtonNum != -1) {
549 buttonsLenInt = maxButtonNum;
550 }
551 return buttonsLenInt;
552 }
553
GetPrimaryButtonNum(napi_env env,std::shared_ptr<PromptAsyncContext> & context,int32_t buttonsLenInt,int32_t & primaryButtonNum)554 void GetPrimaryButtonNum(napi_env env, std::shared_ptr<PromptAsyncContext>& context,
555 int32_t buttonsLenInt, int32_t& primaryButtonNum)
556 {
557 napi_value buttonArray = nullptr;
558 napi_value primaryButtonNApi = nullptr;
559 napi_valuetype valueType = napi_undefined;
560 for (int32_t index = 0; index < buttonsLenInt; index++) {
561 napi_get_element(env, context->buttonsNApi, index, &buttonArray);
562 bool isPrimaryButtonSet = false;
563 napi_get_named_property(env, buttonArray, "primary", &primaryButtonNApi);
564 napi_typeof(env, primaryButtonNApi, &valueType);
565 if (valueType == napi_boolean) {
566 napi_get_value_bool(env, primaryButtonNApi, &isPrimaryButtonSet);
567 }
568 if (isPrimaryButtonSet) {
569 primaryButtonNum++;
570 }
571 }
572 }
573
ParseButtons(napi_env env,std::shared_ptr<PromptAsyncContext> & context,int32_t maxButtonNum,int32_t & primaryButtonNum)574 bool ParseButtons(napi_env env, std::shared_ptr<PromptAsyncContext>& context,
575 int32_t maxButtonNum, int32_t& primaryButtonNum)
576 {
577 napi_value buttonArray = nullptr;
578 napi_value textNApi = nullptr;
579 napi_value colorNApi = nullptr;
580 napi_value primaryButtonNApi = nullptr;
581 napi_valuetype valueType = napi_undefined;
582 int32_t buttonsLenInt = GetButtonArraryLen(env, context, maxButtonNum);
583 GetPrimaryButtonNum(env, context, buttonsLenInt, primaryButtonNum);
584 for (int32_t index = 0; index < buttonsLenInt; index++) {
585 napi_get_element(env, context->buttonsNApi, index, &buttonArray);
586 if (!HasProperty(env, buttonArray, "text")) {
587 DeleteContextAndThrowError(env, context, "Required input parameters are missing.");
588 return false;
589 }
590 std::string textString;
591 napi_get_named_property(env, buttonArray, "text", &textNApi);
592 if (!GetNapiString(env, textNApi, textString, valueType)) {
593 DeleteContextAndThrowError(env, context, "The type of parameters is incorrect.");
594 return false;
595 }
596 if (!HasProperty(env, buttonArray, "color")) {
597 DeleteContextAndThrowError(env, context, "Required input parameters are missing.");
598 return false;
599 }
600 std::string colorString;
601 napi_get_named_property(env, buttonArray, "color", &colorNApi);
602 if (!GetNapiString(env, colorNApi, colorString, valueType)) {
603 if (valueType == napi_undefined) {
604 colorString = DEFAULT_FONT_COLOR_STRING_VALUE;
605 } else {
606 DeleteContextAndThrowError(env, context, "The type of parameters is incorrect.");
607 return false;
608 }
609 }
610 ButtonInfo buttonInfo = { .text = textString, .textColor = colorString };
611 if (primaryButtonNum <= PROMPTACTION_VALID_PRIMARY_BUTTON_NUM) {
612 napi_get_named_property(env, buttonArray, "primary", &primaryButtonNApi);
613 napi_typeof(env, primaryButtonNApi, &valueType);
614 if (valueType == napi_boolean) {
615 napi_get_value_bool(env, primaryButtonNApi, &buttonInfo.isPrimary);
616 }
617 }
618 context->buttons.emplace_back(buttonInfo);
619 }
620 return true;
621 }
622
ParseButtonsPara(napi_env env,std::shared_ptr<PromptAsyncContext> & context,int32_t maxButtonNum,bool isShowActionMenu)623 bool ParseButtonsPara(napi_env env, std::shared_ptr<PromptAsyncContext>& context,
624 int32_t maxButtonNum, bool isShowActionMenu)
625 {
626 bool isBool = false;
627 napi_valuetype valueType = napi_undefined;
628 int32_t primaryButtonNum = 0;
629 napi_is_array(env, context->buttonsNApi, &isBool);
630 napi_typeof(env, context->buttonsNApi, &valueType);
631 if (valueType == napi_object && isBool) {
632 if (!ParseButtons(env, context, SHOW_DIALOG_BUTTON_NUM_MAX, primaryButtonNum)) {
633 return false;
634 }
635 } else if (isShowActionMenu) {
636 DeleteContextAndThrowError(env, context, "The type of the button parameters is incorrect.");
637 return false;
638 }
639 if (isShowActionMenu) {
640 ButtonInfo buttonInfo = { .text = Localization::GetInstance()->GetEntryLetters("common.cancel"),
641 .textColor = "", .isPrimary = primaryButtonNum == 0 ? true : false};
642 context->buttons.emplace_back(buttonInfo);
643 }
644 return true;
645 }
646
GetNapiDialogProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext,std::optional<DialogAlignment> & alignment,std::optional<DimensionOffset> & offset,std::optional<DimensionRect> & maskRect)647 void GetNapiDialogProps(napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext,
648 std::optional<DialogAlignment>& alignment, std::optional<DimensionOffset>& offset,
649 std::optional<DimensionRect>& maskRect)
650 {
651 TAG_LOGD(AceLogTag::ACE_DIALOG, "get napi dialog props enter");
652 napi_valuetype valueType = napi_undefined;
653 // parse alignment
654 napi_typeof(env, asyncContext->alignmentApi, &valueType);
655 if (valueType == napi_number) {
656 int32_t num;
657 napi_get_value_int32(env, asyncContext->alignmentApi, &num);
658 if (num >= 0 && num < static_cast<int32_t>(DIALOG_ALIGNMENT.size())) {
659 alignment = DIALOG_ALIGNMENT[num];
660 }
661 }
662
663 // parse offset
664 napi_typeof(env, asyncContext->offsetApi, &valueType);
665 if (valueType == napi_object) {
666 napi_value dxApi = nullptr;
667 napi_value dyApi = nullptr;
668 napi_get_named_property(env, asyncContext->offsetApi, "dx", &dxApi);
669 napi_get_named_property(env, asyncContext->offsetApi, "dy", &dyApi);
670 CalcDimension dx;
671 CalcDimension dy;
672 ParseNapiDimension(env, dx, dxApi, DimensionUnit::VP);
673 ParseNapiDimension(env, dy, dyApi, DimensionUnit::VP);
674 offset = DimensionOffset { dx, dy };
675 }
676
677 // parse maskRect
678 napi_typeof(env, asyncContext->maskRectApi, &valueType);
679 if (valueType == napi_object) {
680 napi_value xApi = nullptr;
681 napi_value yApi = nullptr;
682 napi_value widthApi = nullptr;
683 napi_value heightApi = nullptr;
684 napi_get_named_property(env, asyncContext->maskRectApi, "x", &xApi);
685 napi_get_named_property(env, asyncContext->maskRectApi, "y", &yApi);
686 napi_get_named_property(env, asyncContext->maskRectApi, "width", &widthApi);
687 napi_get_named_property(env, asyncContext->maskRectApi, "height", &heightApi);
688 CalcDimension x;
689 CalcDimension y;
690 CalcDimension width;
691 CalcDimension height;
692 ParseNapiDimension(env, x, xApi, DimensionUnit::VP);
693 ParseNapiDimension(env, y, yApi, DimensionUnit::VP);
694 ParseNapiDimension(env, width, widthApi, DimensionUnit::VP);
695 ParseNapiDimension(env, height, heightApi, DimensionUnit::VP);
696 DimensionOffset dimensionOffset = { x, y };
697 maskRect = DimensionRect { width, height, dimensionOffset };
698 }
699 }
700
GetNapiDialogbackgroundBlurStyleProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext,std::optional<int32_t> & backgroundBlurStyle)701 void GetNapiDialogbackgroundBlurStyleProps(napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext,
702 std::optional<int32_t>& backgroundBlurStyle)
703 {
704 TAG_LOGD(AceLogTag::ACE_DIALOG, "get napi dialog backgroundBlurStyle props enter");
705 napi_valuetype valueType = napi_undefined;
706
707 napi_typeof(env, asyncContext->backgroundBlurStyleApi, &valueType);
708 if (valueType == napi_number) {
709 int32_t num;
710 napi_get_value_int32(env, asyncContext->backgroundBlurStyleApi, &num);
711 if (num >= 0 && num < BG_BLUR_STYLE_MAX_INDEX) {
712 backgroundBlurStyle = num;
713 }
714 }
715 }
716
CheckNapiDimension(CalcDimension value)717 void CheckNapiDimension(CalcDimension value)
718 {
719 if (value.IsNegative()) {
720 value.Reset();
721 }
722 }
723
GetBorderColorProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)724 std::optional<NG::BorderColorProperty> GetBorderColorProps(
725 napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
726 {
727 napi_valuetype valueType = napi_undefined;
728 NG::BorderColorProperty colorProperty;
729 napi_typeof(env, asyncContext->borderColorApi, &valueType);
730 if (valueType != napi_number && valueType != napi_string && valueType != napi_object) {
731 return std::nullopt;
732 }
733 Color borderColor;
734 if (ParseNapiColor(env, asyncContext->borderColorApi, borderColor)) {
735 colorProperty.SetColor(borderColor);
736 return colorProperty;
737 } else if (valueType == napi_object) {
738 napi_value leftApi = nullptr;
739 napi_value rightApi = nullptr;
740 napi_value topApi = nullptr;
741 napi_value bottomApi = nullptr;
742 napi_get_named_property(env, asyncContext->borderColorApi, "left", &leftApi);
743 napi_get_named_property(env, asyncContext->borderColorApi, "right", &rightApi);
744 napi_get_named_property(env, asyncContext->borderColorApi, "top", &topApi);
745 napi_get_named_property(env, asyncContext->borderColorApi, "bottom", &bottomApi);
746 Color leftColor;
747 Color rightColor;
748 Color topColor;
749 Color bottomColor;
750 if (ParseNapiColor(env, leftApi, leftColor)) {
751 colorProperty.leftColor = leftColor;
752 }
753 if (ParseNapiColor(env, rightApi, rightColor)) {
754 colorProperty.rightColor = rightColor;
755 }
756 if (ParseNapiColor(env, topApi, topColor)) {
757 colorProperty.topColor = topColor;
758 }
759 if (ParseNapiColor(env, bottomApi, bottomColor)) {
760 colorProperty.bottomColor = bottomColor;
761 }
762 colorProperty.multiValued = true;
763 return colorProperty;
764 }
765 return std::nullopt;
766 }
767
GetBorderWidthProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)768 std::optional<NG::BorderWidthProperty> GetBorderWidthProps(
769 napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
770 {
771 napi_valuetype valueType = napi_undefined;
772 napi_typeof(env, asyncContext->borderWidthApi, &valueType);
773 if (valueType != napi_number && valueType != napi_string && valueType != napi_object) {
774 return std::nullopt;
775 }
776 NG::BorderWidthProperty borderWidthProps;
777 CalcDimension borderWidth;
778 if (ParseNapiDimensionNG(env, borderWidth, asyncContext->borderWidthApi, DimensionUnit::VP, true)) {
779 CheckNapiDimension(borderWidth);
780 borderWidthProps = NG::BorderWidthProperty({ borderWidth, borderWidth, borderWidth, borderWidth });
781 return borderWidthProps;
782 } else if (valueType == napi_object) {
783 napi_value leftApi = nullptr;
784 napi_value rightApi = nullptr;
785 napi_value topApi = nullptr;
786 napi_value bottomApi = nullptr;
787 napi_get_named_property(env, asyncContext->borderWidthApi, "left", &leftApi);
788 napi_get_named_property(env, asyncContext->borderWidthApi, "right", &rightApi);
789 napi_get_named_property(env, asyncContext->borderWidthApi, "top", &topApi);
790 napi_get_named_property(env, asyncContext->borderWidthApi, "bottom", &bottomApi);
791 CalcDimension leftDimen;
792 CalcDimension rightDimen;
793 CalcDimension topDimen;
794 CalcDimension bottomDimen;
795 if (ParseNapiDimensionNG(env, leftDimen, leftApi, DimensionUnit::VP, true)) {
796 CheckNapiDimension(leftDimen);
797 borderWidthProps.leftDimen = leftDimen;
798 }
799 if (ParseNapiDimensionNG(env, rightDimen, rightApi, DimensionUnit::VP, true)) {
800 CheckNapiDimension(rightDimen);
801 borderWidthProps.rightDimen = rightDimen;
802 }
803 if (ParseNapiDimensionNG(env, topDimen, topApi, DimensionUnit::VP, true)) {
804 CheckNapiDimension(topDimen);
805 borderWidthProps.topDimen = topDimen;
806 }
807 if (ParseNapiDimensionNG(env, bottomDimen, bottomApi, DimensionUnit::VP, true)) {
808 CheckNapiDimension(bottomDimen);
809 borderWidthProps.bottomDimen = bottomDimen;
810 }
811 borderWidthProps.multiValued = true;
812 return borderWidthProps;
813 }
814 return std::nullopt;
815 }
816
GetBorderRadiusProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)817 std::optional<NG::BorderRadiusProperty> GetBorderRadiusProps(
818 napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
819 {
820 napi_valuetype valueType = napi_undefined;
821 napi_typeof(env, asyncContext->borderRadiusApi, &valueType);
822 if (valueType != napi_number && valueType != napi_object && valueType != napi_string) {
823 return std::nullopt;
824 }
825 CalcDimension borderRadius;
826 if (ParseNapiDimensionNG(env, borderRadius, asyncContext->borderRadiusApi, DimensionUnit::VP, true)) {
827 CheckNapiDimension(borderRadius);
828 return NG::BorderRadiusProperty(borderRadius);
829 } else if (valueType == napi_object) {
830 NG::BorderRadiusProperty radiusProps;
831 napi_value topLeft = nullptr;
832 napi_value topRight = nullptr;
833 napi_value bottomLeft = nullptr;
834 napi_value bottomRight = nullptr;
835 napi_get_named_property(env, asyncContext->borderRadiusApi, "topLeft", &topLeft);
836 napi_get_named_property(env, asyncContext->borderRadiusApi, "topRight", &topRight);
837 napi_get_named_property(env, asyncContext->borderRadiusApi, "bottomLeft", &bottomLeft);
838 napi_get_named_property(env, asyncContext->borderRadiusApi, "bottomRight", &bottomRight);
839 CalcDimension radiusTopLeft;
840 CalcDimension radiusTopRight;
841 CalcDimension radiusBottomLeft;
842 CalcDimension radiusBottomRight;
843 if (ParseNapiDimensionNG(env, radiusTopLeft, topLeft, DimensionUnit::VP, true)) {
844 CheckNapiDimension(radiusTopLeft);
845 radiusProps.radiusTopLeft = radiusTopLeft;
846 }
847 if (ParseNapiDimensionNG(env, radiusTopRight, topRight, DimensionUnit::VP, true)) {
848 CheckNapiDimension(radiusTopRight);
849 radiusProps.radiusTopRight = radiusTopRight;
850 }
851 if (ParseNapiDimensionNG(env, radiusBottomLeft, bottomLeft, DimensionUnit::VP, true)) {
852 CheckNapiDimension(radiusBottomLeft);
853 radiusProps.radiusBottomLeft = radiusBottomLeft;
854 }
855 if (ParseNapiDimensionNG(env, radiusBottomRight, bottomRight, DimensionUnit::VP, true)) {
856 CheckNapiDimension(radiusBottomRight);
857 radiusProps.radiusBottomRight = radiusBottomRight;
858 }
859 radiusProps.multiValued = true;
860 return radiusProps;
861 }
862 return std::nullopt;
863 }
864
GetColorProps(napi_env env,napi_value value)865 std::optional<Color> GetColorProps(napi_env env, napi_value value)
866 {
867 Color color;
868 if (ParseNapiColor(env, value, color)) {
869 return color;
870 }
871 return std::nullopt;
872 }
873
GetBorderStyleProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)874 std::optional<NG::BorderStyleProperty> GetBorderStyleProps(
875 napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
876 {
877 NG::BorderStyleProperty styleProps;
878 napi_valuetype valueType = napi_undefined;
879 napi_typeof(env, asyncContext->borderStyleApi, &valueType);
880 if (valueType != napi_number && valueType != napi_object) {
881 return std::nullopt;
882 } else if (valueType == napi_object) {
883 napi_value leftApi = nullptr;
884 napi_value rightApi = nullptr;
885 napi_value topApi = nullptr;
886 napi_value bottomApi = nullptr;
887 napi_get_named_property(env, asyncContext->borderStyleApi, "left", &leftApi);
888 napi_get_named_property(env, asyncContext->borderStyleApi, "right", &rightApi);
889 napi_get_named_property(env, asyncContext->borderStyleApi, "top", &topApi);
890 napi_get_named_property(env, asyncContext->borderStyleApi, "bottom", &bottomApi);
891 std::optional<BorderStyle> styleLeft;
892 std::optional<BorderStyle> styleRight;
893 std::optional<BorderStyle> styleTop;
894 std::optional<BorderStyle> styleBottom;
895 if (ParseStyle(env, leftApi, styleLeft)) {
896 styleProps.styleLeft = styleLeft;
897 }
898 if (ParseStyle(env, rightApi, styleRight)) {
899 styleProps.styleRight = styleRight;
900 }
901 if (ParseStyle(env, topApi, styleTop)) {
902 styleProps.styleTop = styleTop;
903 }
904 if (ParseStyle(env, bottomApi, styleBottom)) {
905 styleProps.styleBottom = styleBottom;
906 }
907 styleProps.multiValued = true;
908 return styleProps;
909 }
910 std::optional<BorderStyle> borderStyle;
911 if (ParseStyle(env, asyncContext->borderStyleApi, borderStyle)) {
912 styleProps = NG::BorderStyleProperty({ borderStyle, borderStyle, borderStyle, borderStyle });
913 return styleProps;
914 }
915 return std::nullopt;
916 }
917
GetNapiObjectShadow(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext,Shadow & shadow)918 void GetNapiObjectShadow(napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext, Shadow& shadow)
919 {
920 napi_value radiusApi = nullptr;
921 napi_value colorApi = nullptr;
922 napi_value typeApi = nullptr;
923 napi_value fillApi = nullptr;
924 napi_get_named_property(env, asyncContext->shadowApi, "radius", &radiusApi);
925 napi_get_named_property(env, asyncContext->shadowApi, "color", &colorApi);
926 napi_get_named_property(env, asyncContext->shadowApi, "type", &typeApi);
927 napi_get_named_property(env, asyncContext->shadowApi, "fill", &fillApi);
928 double radius = 0.0;
929 napi_get_value_double(env, radiusApi, &radius);
930 if (LessNotEqual(radius, 0.0)) {
931 radius = 0.0;
932 }
933 shadow.SetBlurRadius(radius);
934 Color color;
935 ShadowColorStrategy shadowColorStrategy;
936 if (ParseShadowColorStrategy(env, colorApi, shadowColorStrategy)) {
937 shadow.SetShadowColorStrategy(shadowColorStrategy);
938 } else if (ParseNapiColor(env, colorApi, color)) {
939 shadow.SetColor(color);
940 }
941 napi_valuetype valueType = GetValueType(env, typeApi);
942 int32_t shadowType = static_cast<int32_t>(ShadowType::COLOR);
943 if (valueType == napi_number) {
944 napi_get_value_int32(env, typeApi, &shadowType);
945 }
946 if (shadowType != static_cast<int32_t>(ShadowType::BLUR)) {
947 shadowType = static_cast<int32_t>(ShadowType::COLOR);
948 }
949 shadowType =
950 std::clamp(shadowType, static_cast<int32_t>(ShadowType::COLOR), static_cast<int32_t>(ShadowType::BLUR));
951 shadow.SetShadowType(static_cast<ShadowType>(shadowType));
952 valueType = GetValueType(env, fillApi);
953 bool isFilled = false;
954 if (valueType == napi_boolean) {
955 napi_get_value_bool(env, fillApi, &isFilled);
956 }
957 shadow.SetIsFilled(isFilled);
958 }
959
GetShadowProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)960 std::optional<Shadow> GetShadowProps(napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
961 {
962 Shadow shadow;
963 napi_valuetype valueType = napi_undefined;
964 napi_typeof(env, asyncContext->shadowApi, &valueType);
965 if (valueType != napi_object && valueType != napi_number) {
966 return std::nullopt;
967 }
968 if (valueType == napi_number) {
969 int32_t num = 0;
970 if (napi_get_value_int32(env, asyncContext->shadowApi, &num) == napi_ok) {
971 auto style = static_cast<ShadowStyle>(num);
972 GetShadowFromTheme(style, shadow);
973 return shadow;
974 }
975 } else if (valueType == napi_object) {
976 napi_value offsetXApi = nullptr;
977 napi_value offsetYApi = nullptr;
978 napi_get_named_property(env, asyncContext->shadowApi, "offsetX", &offsetXApi);
979 napi_get_named_property(env, asyncContext->shadowApi, "offsetY", &offsetYApi);
980 ResourceInfo recv;
981 bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
982 if (ParseResourceParam(env, offsetXApi, recv)) {
983 auto resourceWrapper = CreateResourceWrapper(recv);
984 auto offsetX = resourceWrapper->GetDimension(recv.resId);
985 double xValue = isRtl ? offsetX.Value() * (-1) : offsetX.Value();
986 shadow.SetOffsetX(xValue);
987 } else {
988 CalcDimension offsetX;
989 if (ParseNapiDimension(env, offsetX, offsetXApi, DimensionUnit::VP)) {
990 double xValue = isRtl ? offsetX.Value() * (-1) : offsetX.Value();
991 shadow.SetOffsetX(xValue);
992 }
993 }
994 if (ParseResourceParam(env, offsetYApi, recv)) {
995 auto resourceWrapper = CreateResourceWrapper(recv);
996 auto offsetY = resourceWrapper->GetDimension(recv.resId);
997 shadow.SetOffsetY(offsetY.Value());
998 } else {
999 CalcDimension offsetY;
1000 if (ParseNapiDimension(env, offsetY, offsetYApi, DimensionUnit::VP)) {
1001 shadow.SetOffsetY(offsetY.Value());
1002 }
1003 }
1004 GetNapiObjectShadow(env, asyncContext, shadow);
1005 return shadow;
1006 }
1007 return std::nullopt;
1008 }
1009
GetNapiDialogWidthProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)1010 std::optional<CalcDimension> GetNapiDialogWidthProps(
1011 napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
1012 {
1013 std::optional<CalcDimension> widthProperty;
1014 CalcDimension width;
1015 if (ParseNapiDimensionNG(env, width, asyncContext->widthApi, DimensionUnit::VP, true)) {
1016 widthProperty = width;
1017 }
1018 return widthProperty;
1019 }
1020
GetNapiDialogHeightProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)1021 std::optional<CalcDimension> GetNapiDialogHeightProps(
1022 napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
1023 {
1024 std::optional<CalcDimension> heightProperty;
1025 CalcDimension height;
1026 if (ParseNapiDimensionNG(env, height, asyncContext->heightApi, DimensionUnit::VP, true)) {
1027 heightProperty = height;
1028 }
1029 return heightProperty;
1030 }
1031
GetDialogKeyboardAvoidMode(napi_env env,napi_value keyboardAvoidModeApi)1032 int32_t GetDialogKeyboardAvoidMode(napi_env env, napi_value keyboardAvoidModeApi)
1033 {
1034 int32_t mode = 0;
1035 napi_valuetype valueType = napi_undefined;
1036 napi_typeof(env, keyboardAvoidModeApi, &valueType);
1037 if (valueType == napi_number) {
1038 napi_get_value_int32(env, keyboardAvoidModeApi, &mode);
1039 }
1040 if (mode >= 0 && mode < static_cast<int32_t>(KEYBOARD_AVOID_MODE.size())) {
1041 return mode;
1042 }
1043 return 0;
1044 }
1045
GetNapiNamedProperties(napi_env env,napi_value * argv,size_t index,std::shared_ptr<PromptAsyncContext> & asyncContext)1046 void GetNapiNamedProperties(napi_env env, napi_value* argv, size_t index,
1047 std::shared_ptr<PromptAsyncContext>& asyncContext)
1048 {
1049 napi_valuetype valueType = napi_undefined;
1050
1051 if (index == 0) {
1052 napi_get_named_property(env, argv[index], "builder", &asyncContext->builder);
1053 napi_get_named_property(env, argv[index], "backgroundColor", &asyncContext->backgroundColorApi);
1054 napi_get_named_property(env, argv[index], "backgroundBlurStyle", &asyncContext->backgroundBlurStyleApi);
1055 napi_get_named_property(env, argv[index], "cornerRadius", &asyncContext->borderRadiusApi);
1056 napi_get_named_property(env, argv[index], "borderWidth", &asyncContext->borderWidthApi);
1057 napi_get_named_property(env, argv[index], "borderColor", &asyncContext->borderColorApi);
1058 napi_get_named_property(env, argv[index], "borderStyle", &asyncContext->borderStyleApi);
1059 napi_get_named_property(env, argv[index], "shadow", &asyncContext->shadowApi);
1060 napi_get_named_property(env, argv[index], "width", &asyncContext->widthApi);
1061 napi_get_named_property(env, argv[index], "height", &asyncContext->heightApi);
1062
1063 napi_typeof(env, asyncContext->builder, &valueType);
1064 if (valueType == napi_function) {
1065 napi_create_reference(env, asyncContext->builder, 1, &asyncContext->builderRef);
1066 }
1067 }
1068 napi_get_named_property(env, argv[index], "showInSubWindow", &asyncContext->showInSubWindow);
1069 napi_get_named_property(env, argv[index], "isModal", &asyncContext->isModal);
1070 napi_get_named_property(env, argv[index], "alignment", &asyncContext->alignmentApi);
1071 napi_get_named_property(env, argv[index], "offset", &asyncContext->offsetApi);
1072 napi_get_named_property(env, argv[index], "maskRect", &asyncContext->maskRectApi);
1073 napi_get_named_property(env, argv[index], "autoCancel", &asyncContext->autoCancel);
1074 napi_get_named_property(env, argv[index], "maskColor", &asyncContext->maskColorApi);
1075 napi_get_named_property(env, argv[index], "transition", &asyncContext->transitionApi);
1076 napi_get_named_property(env, argv[index], "onWillDismiss", &asyncContext->onWillDismiss);
1077 napi_get_named_property(env, argv[index], "onDidAppear", &asyncContext->onDidAppear);
1078 napi_get_named_property(env, argv[index], "onDidDisappear", &asyncContext->onDidDisappear);
1079 napi_get_named_property(env, argv[index], "onWillAppear", &asyncContext->onWillAppear);
1080 napi_get_named_property(env, argv[index], "onWillDisappear", &asyncContext->onWillDisappear);
1081 napi_get_named_property(env, argv[index], "keyboardAvoidMode", &asyncContext->keyboardAvoidModeApi);
1082
1083 napi_typeof(env, asyncContext->autoCancel, &valueType);
1084 if (valueType == napi_boolean) {
1085 napi_get_value_bool(env, asyncContext->autoCancel, &asyncContext->autoCancelBool);
1086 }
1087 napi_typeof(env, asyncContext->showInSubWindow, &valueType);
1088 if (valueType == napi_boolean) {
1089 napi_get_value_bool(env, asyncContext->showInSubWindow, &asyncContext->showInSubWindowBool);
1090 }
1091 napi_typeof(env, asyncContext->isModal, &valueType);
1092 if (valueType == napi_boolean) {
1093 napi_get_value_bool(env, asyncContext->isModal, &asyncContext->isModalBool);
1094 }
1095 }
1096
JSPromptParseParam(napi_env env,size_t argc,napi_value * argv,std::shared_ptr<PromptAsyncContext> & asyncContext)1097 bool JSPromptParseParam(napi_env env, size_t argc, napi_value* argv, std::shared_ptr<PromptAsyncContext>& asyncContext)
1098 {
1099 for (size_t i = 0; i < argc; i++) {
1100 napi_valuetype valueType = napi_undefined;
1101 napi_typeof(env, argv[i], &valueType);
1102 if (i == 0 || i == 1) {
1103 if (valueType != napi_object) {
1104 DeleteContextAndThrowError(env, asyncContext, "The type of parameters is incorrect.");
1105 return false;
1106 }
1107 GetNapiNamedProperties(env, argv, i, asyncContext);
1108 auto result = napi_get_named_property(env, argv[0], "nodePtr_", &asyncContext->frameNodePtr);
1109 if (result == napi_ok) {
1110 napi_get_value_external(env, asyncContext->frameNodePtr, &asyncContext->nativePtr);
1111 }
1112
1113 napi_typeof(env, asyncContext->onWillDismiss, &valueType);
1114 if (valueType == napi_function) {
1115 napi_create_reference(env, asyncContext->onWillDismiss, 1, &asyncContext->onWillDismissRef);
1116 }
1117 napi_typeof(env, asyncContext->onDidAppear, &valueType);
1118 if (valueType == napi_function) {
1119 napi_create_reference(env, asyncContext->onDidAppear, 1, &asyncContext->onDidAppearRef);
1120 }
1121 napi_typeof(env, asyncContext->onDidDisappear, &valueType);
1122 if (valueType == napi_function) {
1123 napi_create_reference(env, asyncContext->onDidDisappear, 1, &asyncContext->onDidDisappearRef);
1124 }
1125 napi_typeof(env, asyncContext->onWillAppear, &valueType);
1126 if (valueType == napi_function) {
1127 napi_create_reference(env, asyncContext->onWillAppear, 1, &asyncContext->onWillAppearRef);
1128 }
1129 napi_typeof(env, asyncContext->onWillDisappear, &valueType);
1130 if (valueType == napi_function) {
1131 napi_create_reference(env, asyncContext->onWillDisappear, 1, &asyncContext->onWillDisappearRef);
1132 }
1133 } else {
1134 DeleteContextAndThrowError(env, asyncContext, "The type of parameters is incorrect.");
1135 return false;
1136 }
1137 }
1138 return true;
1139 }
1140
JSPromptThrowInterError(napi_env env,std::shared_ptr<PromptAsyncContext> & asyncContext,std::string & strMsg)1141 void JSPromptThrowInterError(napi_env env, std::shared_ptr<PromptAsyncContext>& asyncContext, std::string& strMsg)
1142 {
1143 napi_value code = nullptr;
1144 std::string strCode = std::to_string(ERROR_CODE_INTERNAL_ERROR);
1145 napi_create_string_utf8(env, strCode.c_str(), strCode.length(), &code);
1146 napi_value msg = nullptr;
1147 napi_create_string_utf8(env, strMsg.c_str(), strMsg.length(), &msg);
1148 napi_value error = nullptr;
1149 napi_create_error(env, code, msg, &error);
1150
1151 if (asyncContext->deferred) {
1152 napi_reject_deferred(env, asyncContext->deferred, error);
1153 }
1154 }
1155
UpdatePromptAlignment(DialogAlignment & alignment)1156 void UpdatePromptAlignment(DialogAlignment& alignment)
1157 {
1158 bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
1159 if (alignment == DialogAlignment::TOP_START) {
1160 if (isRtl) {
1161 alignment = DialogAlignment::TOP_END;
1162 }
1163 } else if (alignment == DialogAlignment::TOP_END) {
1164 if (isRtl) {
1165 alignment = DialogAlignment::TOP_START;
1166 }
1167 } else if (alignment == DialogAlignment::CENTER_START) {
1168 if (isRtl) {
1169 alignment = DialogAlignment::CENTER_END;
1170 }
1171 } else if (alignment == DialogAlignment::CENTER_END) {
1172 if (isRtl) {
1173 alignment = DialogAlignment::CENTER_START;
1174 }
1175 } else if (alignment == DialogAlignment::BOTTOM_START) {
1176 if (isRtl) {
1177 alignment = DialogAlignment::BOTTOM_END;
1178 }
1179 } else if (alignment == DialogAlignment::BOTTOM_END) {
1180 if (isRtl) {
1181 alignment = DialogAlignment::BOTTOM_START;
1182 }
1183 }
1184 }
1185
JSPromptShowDialog(napi_env env,napi_callback_info info)1186 napi_value JSPromptShowDialog(napi_env env, napi_callback_info info)
1187 {
1188 TAG_LOGD(AceLogTag::ACE_DIALOG, "js prompt show dialog enter");
1189 size_t requireArgc = 1;
1190 size_t argc = 2;
1191 napi_value argv[3] = { 0 };
1192 napi_value thisVar = nullptr;
1193 void* data = nullptr;
1194 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1195 if (argc < requireArgc) {
1196 NapiThrow(
1197 env, "The number of parameters must be greater than or equal to 1.", ERROR_CODE_PARAM_INVALID);
1198 return nullptr;
1199 }
1200 if (thisVar == nullptr) {
1201 return nullptr;
1202 }
1203 napi_valuetype valueTypeOfThis = napi_undefined;
1204 napi_typeof(env, thisVar, &valueTypeOfThis);
1205 if (valueTypeOfThis == napi_undefined) {
1206 return nullptr;
1207 }
1208
1209 auto asyncContext = std::make_shared<PromptAsyncContext>();
1210 asyncContext->env = env;
1211 asyncContext->instanceId = Container::CurrentIdSafely();
1212
1213 std::optional<DialogAlignment> alignment;
1214 std::optional<DimensionOffset> offset;
1215 std::optional<DimensionRect> maskRect;
1216 std::optional<Shadow> shadowProps;
1217 std::optional<Color> backgroundColor;
1218 std::optional<int32_t> backgroundBlurStyle;
1219
1220 for (size_t i = 0; i < argc; i++) {
1221 napi_valuetype valueType = napi_undefined;
1222 napi_typeof(env, argv[i], &valueType);
1223 if (i == 0) {
1224 if (valueType != napi_object) {
1225 DeleteContextAndThrowError(env, asyncContext, "The type of parameters is incorrect.");
1226 return nullptr;
1227 }
1228 napi_get_named_property(env, argv[0], "title", &asyncContext->titleNApi);
1229 napi_get_named_property(env, argv[0], "message", &asyncContext->messageNApi);
1230 napi_get_named_property(env, argv[0], "buttons", &asyncContext->buttonsNApi);
1231 napi_get_named_property(env, argv[0], "autoCancel", &asyncContext->autoCancel);
1232 napi_get_named_property(env, argv[0], "showInSubWindow", &asyncContext->showInSubWindow);
1233 napi_get_named_property(env, argv[0], "isModal", &asyncContext->isModal);
1234 napi_get_named_property(env, argv[0], "alignment", &asyncContext->alignmentApi);
1235 napi_get_named_property(env, argv[0], "offset", &asyncContext->offsetApi);
1236 napi_get_named_property(env, argv[0], "maskRect", &asyncContext->maskRectApi);
1237 napi_get_named_property(env, argv[0], "shadow", &asyncContext->shadowApi);
1238 napi_get_named_property(env, argv[0], "backgroundColor", &asyncContext->backgroundColorApi);
1239 napi_get_named_property(env, argv[0], "backgroundBlurStyle", &asyncContext->backgroundBlurStyleApi);
1240 GetNapiString(env, asyncContext->titleNApi, asyncContext->titleString, valueType);
1241 GetNapiString(env, asyncContext->messageNApi, asyncContext->messageString, valueType);
1242 GetNapiDialogProps(env, asyncContext, alignment, offset, maskRect);
1243 GetNapiDialogbackgroundBlurStyleProps(env, asyncContext, backgroundBlurStyle);
1244 backgroundColor = GetColorProps(env, asyncContext->backgroundColorApi);
1245 shadowProps = GetShadowProps(env, asyncContext);
1246 if (!ParseButtonsPara(env, asyncContext, SHOW_DIALOG_BUTTON_NUM_MAX, false)) {
1247 return nullptr;
1248 }
1249 napi_typeof(env, asyncContext->autoCancel, &valueType);
1250 if (valueType == napi_boolean) {
1251 napi_get_value_bool(env, asyncContext->autoCancel, &asyncContext->autoCancelBool);
1252 }
1253 napi_typeof(env, asyncContext->showInSubWindow, &valueType);
1254 if (valueType == napi_boolean) {
1255 napi_get_value_bool(env, asyncContext->showInSubWindow, &asyncContext->showInSubWindowBool);
1256 }
1257 napi_typeof(env, asyncContext->isModal, &valueType);
1258 if (valueType == napi_boolean) {
1259 napi_get_value_bool(env, asyncContext->isModal, &asyncContext->isModalBool);
1260 }
1261 } else if (valueType == napi_function) {
1262 napi_create_reference(env, argv[i], 1, &asyncContext->callbackRef);
1263 } else {
1264 DeleteContextAndThrowError(env, asyncContext, "The type of parameters is incorrect.");
1265 return nullptr;
1266 }
1267 }
1268 auto onLanguageChange = [shadowProps, alignment, offset, maskRect,
1269 updateAlignment = UpdatePromptAlignment](DialogProperties& dialogProps) {
1270 bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
1271 if (shadowProps.has_value()) {
1272 std::optional<Shadow> shadow = shadowProps.value();
1273 double offsetX = isRtl ? shadow->GetOffset().GetX() * (-1) : shadow->GetOffset().GetX();
1274 shadow->SetOffsetX(offsetX);
1275 dialogProps.shadow = shadow.value();
1276 }
1277 if (alignment.has_value()) {
1278 std::optional<DialogAlignment> pmAlign = alignment.value();
1279 updateAlignment(pmAlign.value());
1280 dialogProps.alignment = pmAlign.value();
1281 }
1282 if (offset.has_value()) {
1283 std::optional<DimensionOffset> pmOffset = offset.value();
1284 Dimension offsetX = isRtl ? pmOffset->GetX() * (-1) : pmOffset->GetX();
1285 pmOffset->SetX(offsetX);
1286 dialogProps.offset = pmOffset.value();
1287 }
1288 if (maskRect.has_value()) {
1289 std::optional<DimensionRect> pmMaskRect = maskRect.value();
1290 auto offset = pmMaskRect->GetOffset();
1291 Dimension offsetX = isRtl ? offset.GetX() * (-1) : offset.GetX();
1292 offset.SetX(offsetX);
1293 pmMaskRect->SetOffset(offset);
1294 dialogProps.maskRect = pmMaskRect.value();
1295 }
1296 };
1297 napi_value result = nullptr;
1298 if (asyncContext->callbackRef == nullptr) {
1299 napi_create_promise(env, &asyncContext->deferred, &result);
1300 } else {
1301 napi_get_undefined(env, &result);
1302 }
1303 asyncContext->callbacks.emplace("success");
1304 asyncContext->callbacks.emplace("cancel");
1305
1306 auto callBack = [asyncContext](int32_t callbackType, int32_t successType) mutable {
1307 if (asyncContext == nullptr) {
1308 return;
1309 }
1310
1311 asyncContext->callbackType = callbackType;
1312 asyncContext->successType = successType;
1313 auto container = AceEngine::Get().GetContainer(asyncContext->instanceId);
1314 if (!container) {
1315 return;
1316 }
1317
1318 auto taskExecutor = container->GetTaskExecutor();
1319 if (!taskExecutor) {
1320 return;
1321 }
1322 taskExecutor->PostTask(
1323 [asyncContext]() {
1324 if (asyncContext == nullptr) {
1325 return;
1326 }
1327
1328 if (!asyncContext->valid) {
1329 return;
1330 }
1331
1332 napi_handle_scope scope = nullptr;
1333 napi_open_handle_scope(asyncContext->env, &scope);
1334 if (scope == nullptr) {
1335 return;
1336 }
1337
1338 napi_value ret;
1339 napi_value successIndex = nullptr;
1340 napi_create_int32(asyncContext->env, asyncContext->successType, &successIndex);
1341 napi_value indexObj = nullptr;
1342 napi_create_object(asyncContext->env, &indexObj);
1343 napi_set_named_property(asyncContext->env, indexObj, "index", successIndex);
1344 napi_value result[2] = { 0 };
1345 napi_create_object(asyncContext->env, &result[1]);
1346 napi_set_named_property(asyncContext->env, result[1], "index", successIndex);
1347 bool dialogResult = true;
1348 switch (asyncContext->callbackType) {
1349 case 0:
1350 napi_get_undefined(asyncContext->env, &result[0]);
1351 dialogResult = true;
1352 break;
1353 case 1:
1354 napi_value message = nullptr;
1355 napi_create_string_utf8(asyncContext->env, "cancel", strlen("cancel"), &message);
1356 napi_create_error(asyncContext->env, nullptr, message, &result[0]);
1357 dialogResult = false;
1358 break;
1359 }
1360 if (asyncContext->deferred) {
1361 if (dialogResult) {
1362 napi_resolve_deferred(asyncContext->env, asyncContext->deferred, result[1]);
1363 } else {
1364 napi_reject_deferred(asyncContext->env, asyncContext->deferred, result[0]);
1365 }
1366 } else {
1367 napi_value callback = nullptr;
1368 napi_get_reference_value(asyncContext->env, asyncContext->callbackRef, &callback);
1369 napi_call_function(
1370 asyncContext->env, nullptr, callback, sizeof(result) / sizeof(result[0]), result, &ret);
1371 napi_delete_reference(asyncContext->env, asyncContext->callbackRef);
1372 }
1373 napi_close_handle_scope(asyncContext->env, scope);
1374 },
1375 TaskExecutor::TaskType::JS, "ArkUIDialogParseDialogCallback");
1376 asyncContext = nullptr;
1377 };
1378
1379 PromptDialogAttr promptDialogAttr = {
1380 .title = asyncContext->titleString,
1381 .message = asyncContext->messageString,
1382 .autoCancel = asyncContext->autoCancelBool,
1383 .showInSubWindow = asyncContext->showInSubWindowBool,
1384 .isModal = asyncContext->isModalBool,
1385 .alignment = alignment,
1386 .offset = offset,
1387 .maskRect = maskRect,
1388 .backgroundColor = backgroundColor,
1389 .backgroundBlurStyle = backgroundBlurStyle,
1390 .shadow = shadowProps,
1391 .onLanguageChange = onLanguageChange,
1392 };
1393
1394 #ifdef OHOS_STANDARD_SYSTEM
1395 // NG
1396 if (SystemProperties::GetExtSurfaceEnabled() || !ContainerIsService()) {
1397 auto delegate = EngineHelper::GetCurrentDelegateSafely();
1398 if (delegate) {
1399 delegate->ShowDialog(promptDialogAttr, asyncContext->buttons, std::move(callBack), asyncContext->callbacks);
1400 } else {
1401 // throw internal error
1402 napi_value code = nullptr;
1403 std::string strCode = std::to_string(ERROR_CODE_INTERNAL_ERROR);
1404 napi_create_string_utf8(env, strCode.c_str(), strCode.length(), &code);
1405 napi_value msg = nullptr;
1406 std::string strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "Can not get delegate.";
1407 napi_create_string_utf8(env, strMsg.c_str(), strMsg.length(), &msg);
1408 napi_value error = nullptr;
1409 napi_create_error(env, code, msg, &error);
1410
1411 if (asyncContext->deferred) {
1412 napi_reject_deferred(env, asyncContext->deferred, error);
1413 } else {
1414 napi_value ret1;
1415 napi_value callback = nullptr;
1416 napi_get_reference_value(env, asyncContext->callbackRef, &callback);
1417 napi_call_function(env, nullptr, callback, 1, &error, &ret1);
1418 napi_delete_reference(env, asyncContext->callbackRef);
1419 }
1420 }
1421 } else if (SubwindowManager::GetInstance() != nullptr) {
1422 SubwindowManager::GetInstance()->ShowDialog(
1423 promptDialogAttr, asyncContext->buttons, std::move(callBack), asyncContext->callbacks);
1424 }
1425 #else
1426 auto delegate = EngineHelper::GetCurrentDelegateSafely();
1427 if (delegate) {
1428 delegate->ShowDialog(promptDialogAttr, asyncContext->buttons, std::move(callBack), asyncContext->callbacks);
1429 } else {
1430 // throw internal error
1431 napi_value code = nullptr;
1432 std::string strCode = std::to_string(ERROR_CODE_INTERNAL_ERROR);
1433 napi_create_string_utf8(env, strCode.c_str(), strCode.length(), &code);
1434 napi_value msg = nullptr;
1435 std::string strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "UI execution context not found.";
1436 napi_create_string_utf8(env, strMsg.c_str(), strMsg.length(), &msg);
1437 napi_value error = nullptr;
1438 napi_create_error(env, code, msg, &error);
1439
1440 if (asyncContext->deferred) {
1441 napi_reject_deferred(env, asyncContext->deferred, error);
1442 } else {
1443 napi_value ret1;
1444 napi_value callback = nullptr;
1445 napi_get_reference_value(env, asyncContext->callbackRef, &callback);
1446 napi_call_function(env, nullptr, callback, 1, &error, &ret1);
1447 napi_delete_reference(env, asyncContext->callbackRef);
1448 }
1449 }
1450 #endif
1451 return result;
1452 }
1453
JSPromptShowActionMenu(napi_env env,napi_callback_info info)1454 napi_value JSPromptShowActionMenu(napi_env env, napi_callback_info info)
1455 {
1456 TAG_LOGD(AceLogTag::ACE_DIALOG, "js prompt show action menu enter");
1457 size_t requireArgc = 1;
1458 size_t argc = 2;
1459 napi_value argv[3] = { 0 };
1460 napi_value thisVar = nullptr;
1461 void* data = nullptr;
1462 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1463 if (argc < requireArgc) {
1464 NapiThrow(
1465 env, "The number of parameters must be greater than or equal to 1.", ERROR_CODE_PARAM_INVALID);
1466 return nullptr;
1467 }
1468 if (thisVar == nullptr) {
1469 return nullptr;
1470 }
1471 napi_valuetype valueTypeOfThis = napi_undefined;
1472 napi_typeof(env, thisVar, &valueTypeOfThis);
1473 if (valueTypeOfThis == napi_undefined) {
1474 return nullptr;
1475 }
1476
1477 auto asyncContext = std::make_shared<PromptAsyncContext>();
1478 asyncContext->env = env;
1479 asyncContext->instanceId = Container::CurrentIdSafely();
1480 for (size_t i = 0; i < argc; i++) {
1481 napi_valuetype valueType = napi_undefined;
1482 napi_typeof(env, argv[i], &valueType);
1483 if (i == 0) {
1484 if (valueType != napi_object) {
1485 DeleteContextAndThrowError(env, asyncContext, "The type of parameters is incorrect.");
1486 return nullptr;
1487 }
1488 napi_get_named_property(env, argv[0], "title", &asyncContext->titleNApi);
1489 napi_get_named_property(env, argv[0], "showInSubWindow", &asyncContext->showInSubWindow);
1490 napi_get_named_property(env, argv[0], "isModal", &asyncContext->isModal);
1491 GetNapiString(env, asyncContext->titleNApi, asyncContext->titleString, valueType);
1492 if (!HasProperty(env, argv[0], "buttons")) {
1493 DeleteContextAndThrowError(env, asyncContext, "Required input parameters are missing.");
1494 return nullptr;
1495 }
1496 napi_get_named_property(env, argv[0], "buttons", &asyncContext->buttonsNApi);
1497 if (!ParseButtonsPara(env, asyncContext, SHOW_ACTION_MENU_BUTTON_NUM_MAX, true)) {
1498 return nullptr;
1499 }
1500 napi_typeof(env, asyncContext->showInSubWindow, &valueType);
1501 if (valueType == napi_boolean) {
1502 napi_get_value_bool(env, asyncContext->showInSubWindow, &asyncContext->showInSubWindowBool);
1503 }
1504 napi_typeof(env, asyncContext->isModal, &valueType);
1505 if (valueType == napi_boolean) {
1506 napi_get_value_bool(env, asyncContext->isModal, &asyncContext->isModalBool);
1507 }
1508 } else if (valueType == napi_function) {
1509 napi_create_reference(env, argv[i], 1, &asyncContext->callbackRef);
1510 } else {
1511 DeleteContextAndThrowError(env, asyncContext, "The type of parameters is incorrect.");
1512 return nullptr;
1513 }
1514 }
1515 napi_value result = nullptr;
1516 if (asyncContext->callbackRef == nullptr) {
1517 napi_create_promise(env, &asyncContext->deferred, &result);
1518 } else {
1519 napi_get_undefined(env, &result);
1520 }
1521
1522 auto callBack = [asyncContext](int32_t callbackType, int32_t successType) mutable {
1523 if (asyncContext == nullptr) {
1524 return;
1525 }
1526
1527 asyncContext->callbackType = callbackType;
1528 asyncContext->successType = successType;
1529 auto container = AceEngine::Get().GetContainer(asyncContext->instanceId);
1530 if (!container) {
1531 return;
1532 }
1533
1534 auto taskExecutor = container->GetTaskExecutor();
1535 if (!taskExecutor) {
1536 return;
1537 }
1538 taskExecutor->PostTask(
1539 [asyncContext]() {
1540 if (asyncContext == nullptr) {
1541 return;
1542 }
1543
1544 if (!asyncContext->valid) {
1545 return;
1546 }
1547
1548 napi_handle_scope scope = nullptr;
1549 napi_open_handle_scope(asyncContext->env, &scope);
1550 if (scope == nullptr) {
1551 return;
1552 }
1553
1554 napi_value ret;
1555 napi_value successIndex = nullptr;
1556 napi_create_int32(asyncContext->env, asyncContext->successType, &successIndex);
1557 asyncContext->callbackSuccessString = "showActionMenu:ok";
1558 napi_value indexObj = GetReturnObject(asyncContext->env, asyncContext->callbackSuccessString);
1559 napi_set_named_property(asyncContext->env, indexObj, "index", successIndex);
1560 napi_value result[2] = { 0 };
1561 napi_create_object(asyncContext->env, &result[1]);
1562 napi_set_named_property(asyncContext->env, result[1], "index", successIndex);
1563 bool dialogResult = true;
1564 switch (asyncContext->callbackType) {
1565 case 0:
1566 napi_get_undefined(asyncContext->env, &result[0]);
1567 dialogResult = true;
1568 break;
1569 case 1:
1570 napi_value message = nullptr;
1571 napi_create_string_utf8(asyncContext->env, "cancel", strlen("cancel"), &message);
1572 napi_create_error(asyncContext->env, nullptr, message, &result[0]);
1573 dialogResult = false;
1574 break;
1575 }
1576 if (asyncContext->deferred) {
1577 if (dialogResult) {
1578 napi_resolve_deferred(asyncContext->env, asyncContext->deferred, result[1]);
1579 } else {
1580 napi_reject_deferred(asyncContext->env, asyncContext->deferred, result[0]);
1581 }
1582 } else {
1583 napi_value callback = nullptr;
1584 napi_get_reference_value(asyncContext->env, asyncContext->callbackRef, &callback);
1585 napi_call_function(
1586 asyncContext->env, nullptr, callback, sizeof(result) / sizeof(result[0]), result, &ret);
1587 napi_delete_reference(asyncContext->env, asyncContext->callbackRef);
1588 }
1589 napi_close_handle_scope(asyncContext->env, scope);
1590 },
1591 TaskExecutor::TaskType::JS, "ArkUIDialogParseActionMenuCallback");
1592 asyncContext = nullptr;
1593 };
1594
1595 PromptDialogAttr promptDialogAttr = {
1596 .title = asyncContext->titleString,
1597 .showInSubWindow = asyncContext->showInSubWindowBool,
1598 .isModal = asyncContext->isModalBool,
1599 };
1600 #ifdef OHOS_STANDARD_SYSTEM
1601 if (SystemProperties::GetExtSurfaceEnabled() || !ContainerIsService()) {
1602 auto delegate = EngineHelper::GetCurrentDelegateSafely();
1603 if (delegate) {
1604 delegate->ShowActionMenu(promptDialogAttr, asyncContext->buttons, std::move(callBack));
1605 } else {
1606 napi_value code = nullptr;
1607 std::string strCode = std::to_string(ERROR_CODE_INTERNAL_ERROR);
1608 napi_create_string_utf8(env, strCode.c_str(), strCode.length(), &code);
1609 napi_value msg = nullptr;
1610 std::string strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "Can not get delegate.";
1611 napi_create_string_utf8(env, strMsg.c_str(), strMsg.length(), &msg);
1612 napi_value error = nullptr;
1613 napi_create_error(env, code, msg, &error);
1614
1615 if (asyncContext->deferred) {
1616 napi_reject_deferred(env, asyncContext->deferred, error);
1617 } else {
1618 napi_value ret1;
1619 napi_value callback = nullptr;
1620 napi_get_reference_value(env, asyncContext->callbackRef, &callback);
1621 napi_call_function(env, nullptr, callback, 1, &error, &ret1);
1622 napi_delete_reference(env, asyncContext->callbackRef);
1623 }
1624 }
1625 } else if (SubwindowManager::GetInstance() != nullptr) {
1626 SubwindowManager::GetInstance()->ShowActionMenu(
1627 asyncContext->titleString, asyncContext->buttons, std::move(callBack));
1628 }
1629 #else
1630 auto delegate = EngineHelper::GetCurrentDelegateSafely();
1631 if (delegate) {
1632 delegate->ShowActionMenu(promptDialogAttr, asyncContext->buttons, std::move(callBack));
1633 } else {
1634 napi_value code = nullptr;
1635 std::string strCode = std::to_string(ERROR_CODE_INTERNAL_ERROR);
1636 napi_create_string_utf8(env, strCode.c_str(), strCode.length(), &code);
1637 napi_value msg = nullptr;
1638 std::string strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "UI execution context not found.";
1639 napi_create_string_utf8(env, strMsg.c_str(), strMsg.length(), &msg);
1640 napi_value error = nullptr;
1641 napi_create_error(env, code, msg, &error);
1642
1643 if (asyncContext->deferred) {
1644 napi_reject_deferred(env, asyncContext->deferred, error);
1645 } else {
1646 napi_value ret1;
1647 napi_value callback = nullptr;
1648 napi_get_reference_value(env, asyncContext->callbackRef, &callback);
1649 napi_call_function(env, nullptr, callback, 1, &error, &ret1);
1650 napi_delete_reference(env, asyncContext->callbackRef);
1651 }
1652 }
1653 #endif
1654 return result;
1655 }
1656
JSRemoveCustomDialog(napi_env env,napi_callback_info info)1657 napi_value JSRemoveCustomDialog(napi_env env, napi_callback_info info)
1658 {
1659 auto delegate = EngineHelper::GetCurrentDelegateSafely();
1660 if (delegate) {
1661 delegate->RemoveCustomDialog();
1662 }
1663 return nullptr;
1664 }
1665
ParseDialogCallback(std::shared_ptr<PromptAsyncContext> & asyncContext,std::function<void (const int32_t & info)> & onWillDismiss)1666 void ParseDialogCallback(std::shared_ptr<PromptAsyncContext>& asyncContext,
1667 std::function<void(const int32_t& info)>& onWillDismiss)
1668 {
1669 onWillDismiss = [env = asyncContext->env, onWillDismissRef = asyncContext->onWillDismissRef]
1670 (const int32_t& info) {
1671 if (onWillDismissRef) {
1672 napi_value onWillDismissFunc = nullptr;
1673 napi_value value = nullptr;
1674 napi_value funcValue = nullptr;
1675 napi_value paramObj = nullptr;
1676 napi_create_object(env, ¶mObj);
1677
1678 napi_create_function(env, "dismiss", strlen("dismiss"), JSRemoveCustomDialog, nullptr, &funcValue);
1679 napi_set_named_property(env, paramObj, "dismiss", funcValue);
1680
1681 napi_create_int32(env, info, &value);
1682 napi_set_named_property(env, paramObj, "reason", value);
1683 napi_get_reference_value(env, onWillDismissRef, &onWillDismissFunc);
1684 napi_call_function(env, nullptr, onWillDismissFunc, 1, ¶mObj, nullptr);
1685 }
1686 };
1687 }
1688
GetDialogLifeCycleCallback(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)1689 PromptDialogAttr GetDialogLifeCycleCallback(napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
1690 {
1691 auto onDidAppear = [env = asyncContext->env, onDidAppearRef = asyncContext->onDidAppearRef]() {
1692 if (onDidAppearRef) {
1693 napi_value onDidAppearFunc = nullptr;
1694 napi_get_reference_value(env, onDidAppearRef, &onDidAppearFunc);
1695 napi_call_function(env, nullptr, onDidAppearFunc, 0, nullptr, nullptr);
1696 napi_delete_reference(env, onDidAppearRef);
1697 }
1698 };
1699 auto onDidDisappear = [env = asyncContext->env, onDidDisappearRef = asyncContext->onDidDisappearRef]() {
1700 if (onDidDisappearRef) {
1701 napi_value onDidDisappearFunc = nullptr;
1702 napi_get_reference_value(env, onDidDisappearRef, &onDidDisappearFunc);
1703 napi_call_function(env, nullptr, onDidDisappearFunc, 0, nullptr, nullptr);
1704 napi_delete_reference(env, onDidDisappearRef);
1705 }
1706 };
1707 auto onWillAppear = [env = asyncContext->env, onWillAppearRef = asyncContext->onWillAppearRef]() {
1708 if (onWillAppearRef) {
1709 napi_value onWillAppearFunc = nullptr;
1710 napi_get_reference_value(env, onWillAppearRef, &onWillAppearFunc);
1711 napi_call_function(env, nullptr, onWillAppearFunc, 0, nullptr, nullptr);
1712 napi_delete_reference(env, onWillAppearRef);
1713 }
1714 };
1715 auto onWillDisappear = [env = asyncContext->env, onWillDisappearRef = asyncContext->onWillDisappearRef]() {
1716 if (onWillDisappearRef) {
1717 napi_value onWillDisappearFunc = nullptr;
1718 napi_get_reference_value(env, onWillDisappearRef, &onWillDisappearFunc);
1719 napi_call_function(env, nullptr, onWillDisappearFunc, 0, nullptr, nullptr);
1720 napi_delete_reference(env, onWillDisappearRef);
1721 }
1722 };
1723 PromptDialogAttr promptDialogAttr = {
1724 .onDidAppear = std::move(onDidAppear),
1725 .onDidDisappear = std::move(onDidDisappear),
1726 .onWillAppear = std::move(onWillAppear),
1727 .onWillDisappear = std::move(onWillDisappear) };
1728 return promptDialogAttr;
1729 }
1730
ParseBorderColorAndStyle(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext,std::optional<NG::BorderWidthProperty> & borderWidthProps,std::optional<NG::BorderColorProperty> & borderColorProps,std::optional<NG::BorderStyleProperty> & borderStyleProps)1731 void ParseBorderColorAndStyle(napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext,
1732 std::optional<NG::BorderWidthProperty>& borderWidthProps, std::optional<NG::BorderColorProperty>& borderColorProps,
1733 std::optional<NG::BorderStyleProperty>& borderStyleProps)
1734 {
1735 if (borderWidthProps.has_value()) {
1736 borderColorProps = GetBorderColorProps(env, asyncContext);
1737 if (!borderColorProps.has_value()) {
1738 NG::BorderColorProperty borderColor;
1739 borderColor.SetColor(Color::BLACK);
1740 borderColorProps = borderColor;
1741 }
1742 borderStyleProps = GetBorderStyleProps(env, asyncContext);
1743 if (!borderStyleProps.has_value()) {
1744 borderStyleProps = NG::BorderStyleProperty(
1745 { BorderStyle::SOLID, BorderStyle::SOLID, BorderStyle::SOLID, BorderStyle::SOLID });
1746 }
1747 }
1748 }
1749
GetTransitionProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)1750 RefPtr<NG::ChainedTransitionEffect> GetTransitionProps(
1751 napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
1752 {
1753 RefPtr<NG::ChainedTransitionEffect> transitionEffect = nullptr;
1754 auto delegate = EngineHelper::GetCurrentDelegateSafely();
1755 if (delegate) {
1756 napi_valuetype valueType = napi_undefined;
1757 napi_typeof(env, asyncContext->transitionApi, &valueType);
1758 if (valueType == napi_object) {
1759 transitionEffect = delegate->GetTransitionEffect(asyncContext->transitionApi);
1760 }
1761 }
1762 return transitionEffect;
1763 }
1764
GetCustomBuilder(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)1765 std::function<void()> GetCustomBuilder(napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
1766 {
1767 auto builder = [env = asyncContext->env, builderRef = asyncContext->builderRef]() {
1768 if (builderRef) {
1769 napi_value builderFunc = nullptr;
1770 napi_get_reference_value(env, builderRef, &builderFunc);
1771 napi_call_function(env, nullptr, builderFunc, 0, nullptr, nullptr);
1772 napi_delete_reference(env, builderRef);
1773 }
1774 };
1775 return builder;
1776 }
1777
GetPromptActionDialog(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext,std::function<void (const int32_t & info)> onWillDismiss)1778 PromptDialogAttr GetPromptActionDialog(napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext,
1779 std::function<void(const int32_t& info)> onWillDismiss)
1780 {
1781 std::optional<DialogAlignment> alignment;
1782 std::optional<DimensionOffset> offset;
1783 std::optional<DimensionRect> maskRect;
1784 std::optional<int32_t> backgroundBlurStyle;
1785 GetNapiDialogProps(env, asyncContext, alignment, offset, maskRect);
1786 auto borderWidthProps = GetBorderWidthProps(env, asyncContext);
1787 std::optional<NG::BorderColorProperty> borderColorProps;
1788 std::optional<NG::BorderStyleProperty> borderStyleProps;
1789 GetNapiDialogbackgroundBlurStyleProps(env, asyncContext, backgroundBlurStyle);
1790 ParseBorderColorAndStyle(env, asyncContext, borderWidthProps, borderColorProps, borderStyleProps);
1791 auto borderRadiusProps = GetBorderRadiusProps(env, asyncContext);
1792 auto backgroundColorProps = GetColorProps(env, asyncContext->backgroundColorApi);
1793 auto widthProps = GetNapiDialogWidthProps(env, asyncContext);
1794 auto heightProps = GetNapiDialogHeightProps(env, asyncContext);
1795 auto shadowProps = GetShadowProps(env, asyncContext);
1796 auto builder = GetCustomBuilder(env, asyncContext);
1797 auto* nodePtr = reinterpret_cast<OHOS::Ace::NG::UINode*>(asyncContext->nativePtr);
1798 auto frameNodeWeak = AceType::WeakClaim(nodePtr);
1799 auto maskColorProps = GetColorProps(env, asyncContext->maskColorApi);
1800 auto transitionEffectProps = GetTransitionProps(env, asyncContext);
1801 PromptDialogAttr lifeCycleAttr = GetDialogLifeCycleCallback(env, asyncContext);
1802 int32_t mode = GetDialogKeyboardAvoidMode(env, asyncContext->keyboardAvoidModeApi);
1803 PromptDialogAttr promptDialogAttr = { .autoCancel = asyncContext->autoCancelBool,
1804 .showInSubWindow = asyncContext->showInSubWindowBool,
1805 .isModal = asyncContext->isModalBool,
1806 .customBuilder = std::move(builder),
1807 .customOnWillDismiss = std::move(onWillDismiss),
1808 .alignment = alignment,
1809 .offset = offset,
1810 .maskRect = maskRect,
1811 .backgroundColor = backgroundColorProps,
1812 .backgroundBlurStyle = backgroundBlurStyle,
1813 .borderWidth = borderWidthProps,
1814 .borderColor = borderColorProps,
1815 .borderStyle = borderStyleProps,
1816 .borderRadius = borderRadiusProps,
1817 .shadow = shadowProps,
1818 .width = widthProps,
1819 .height = heightProps,
1820 .contentNode = frameNodeWeak,
1821 .maskColor = maskColorProps,
1822 .transitionEffect = transitionEffectProps,
1823 .onDidAppear = lifeCycleAttr.onDidAppear,
1824 .onDidDisappear = lifeCycleAttr.onDidDisappear,
1825 .onWillAppear = lifeCycleAttr.onWillAppear,
1826 .onWillDisappear = lifeCycleAttr.onWillDisappear,
1827 .keyboardAvoidMode = KEYBOARD_AVOID_MODE[mode]};
1828 return promptDialogAttr;
1829 }
1830
GetErrorMsg(int32_t errorCode)1831 std::string GetErrorMsg(int32_t errorCode)
1832 {
1833 std::string strMsg;
1834 if (errorCode == ERROR_CODE_DIALOG_CONTENT_ERROR) {
1835 strMsg = ErrorToMessage(ERROR_CODE_DIALOG_CONTENT_ERROR) + "The ComponentContent is incorrect.";
1836 } else if (errorCode == ERROR_CODE_DIALOG_CONTENT_ALREADY_EXIST) {
1837 strMsg = ErrorToMessage(ERROR_CODE_DIALOG_CONTENT_ALREADY_EXIST) +
1838 "The ComponentContent has already been opened.";
1839 } else if (errorCode == ERROR_CODE_DIALOG_CONTENT_NOT_FOUND) {
1840 strMsg = ErrorToMessage(ERROR_CODE_DIALOG_CONTENT_NOT_FOUND) + "The ComponentContent cannot be found.";
1841 } else {
1842 strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "Build custom dialog failed.";
1843 }
1844 return strMsg;
1845 }
1846
GetErrorCode(int32_t errorCode)1847 std::string GetErrorCode(int32_t errorCode)
1848 {
1849 std::string strCode;
1850 if (errorCode == ERROR_CODE_DIALOG_CONTENT_ERROR) {
1851 strCode = std::to_string(ERROR_CODE_DIALOG_CONTENT_ERROR);
1852 } else if (errorCode == ERROR_CODE_DIALOG_CONTENT_ALREADY_EXIST) {
1853 strCode = std::to_string(ERROR_CODE_DIALOG_CONTENT_ALREADY_EXIST);
1854 } else if (errorCode == ERROR_CODE_DIALOG_CONTENT_NOT_FOUND) {
1855 strCode = std::to_string(ERROR_CODE_DIALOG_CONTENT_NOT_FOUND);
1856 } else {
1857 strCode = std::to_string(ERROR_CODE_INTERNAL_ERROR);
1858 }
1859 return strCode;
1860 }
1861
ParseCustomDialogContentCallback(std::shared_ptr<PromptAsyncContext> & asyncContext,std::function<void (int32_t)> & callBack)1862 void ParseCustomDialogContentCallback(std::shared_ptr<PromptAsyncContext>& asyncContext,
1863 std::function<void(int32_t)>& callBack)
1864 {
1865 callBack = [asyncContext](int32_t errorCode) mutable {
1866 if (!asyncContext) {
1867 return;
1868 }
1869 auto container = AceEngine::Get().GetContainer(asyncContext->instanceId);
1870 if (!container) {
1871 return;
1872 }
1873 auto taskExecutor = container->GetTaskExecutor();
1874 if (!taskExecutor) {
1875 return;
1876 }
1877 taskExecutor->PostTask(
1878 [asyncContext, errorCode]() {
1879 if (asyncContext == nullptr || !asyncContext->valid) {
1880 return;
1881 }
1882 napi_handle_scope scope = nullptr;
1883 napi_open_handle_scope(asyncContext->env, &scope);
1884 if (scope == nullptr) {
1885 return;
1886 }
1887 if (!asyncContext->deferred) {
1888 return;
1889 }
1890 if (errorCode == ERROR_CODE_NO_ERROR) {
1891 napi_value result = nullptr;
1892 napi_get_undefined(asyncContext->env, &result);
1893 napi_resolve_deferred(asyncContext->env, asyncContext->deferred, result);
1894 } else {
1895 std::string strMsg = GetErrorMsg(errorCode);
1896 std::string strCode = GetErrorCode(errorCode);
1897 napi_value code = nullptr;
1898 napi_create_string_utf8(asyncContext->env, strCode.c_str(), strCode.length(), &code);
1899 napi_value msg = nullptr;
1900 napi_create_string_utf8(asyncContext->env, strMsg.c_str(), strMsg.length(), &msg);
1901 napi_value error = nullptr;
1902 napi_create_error(asyncContext->env, code, msg, &error);
1903 napi_reject_deferred(asyncContext->env, asyncContext->deferred, error);
1904 }
1905 napi_close_handle_scope(asyncContext->env, scope);
1906 },
1907 TaskExecutor::TaskType::JS, "ArkUIDialogParseCustomDialogContentCallback");
1908 asyncContext = nullptr;
1909 };
1910 }
1911
ParseCustomDialogIdCallback(std::shared_ptr<PromptAsyncContext> & asyncContext,std::function<void (int32_t)> & callBack)1912 void ParseCustomDialogIdCallback(std::shared_ptr<PromptAsyncContext>& asyncContext,
1913 std::function<void(int32_t)>& callBack)
1914 {
1915 callBack = [asyncContext](int32_t dialogId) mutable {
1916 if (!asyncContext) {
1917 return;
1918 }
1919 auto container = AceEngine::Get().GetContainer(asyncContext->instanceId);
1920 if (!container) {
1921 return;
1922 }
1923 auto taskExecutor = container->GetTaskExecutor();
1924 if (!taskExecutor) {
1925 return;
1926 }
1927 taskExecutor->PostTask(
1928 [asyncContext, dialogId]() {
1929 if (asyncContext == nullptr || !asyncContext->valid) {
1930 return;
1931 }
1932
1933 napi_handle_scope scope = nullptr;
1934 napi_open_handle_scope(asyncContext->env, &scope);
1935 if (scope == nullptr) {
1936 return;
1937 }
1938
1939 napi_value ret = nullptr;
1940 if (!asyncContext->deferred) {
1941 return;
1942 }
1943 if (dialogId > 0) {
1944 napi_create_int32(asyncContext->env, dialogId, &ret);
1945 napi_resolve_deferred(asyncContext->env, asyncContext->deferred, ret);
1946 } else {
1947 std::string strMsg = GetErrorMsg(dialogId);
1948 std::string strCode = GetErrorCode(dialogId);
1949 napi_value code = nullptr;
1950 napi_create_string_utf8(asyncContext->env, strCode.c_str(), strCode.length(), &code);
1951 napi_value msg = nullptr;
1952 napi_create_string_utf8(asyncContext->env, strMsg.c_str(), strMsg.length(), &msg);
1953 napi_value error = nullptr;
1954 napi_create_error(asyncContext->env, code, msg, &error);
1955 napi_reject_deferred(asyncContext->env, asyncContext->deferred, error);
1956 }
1957 napi_close_handle_scope(asyncContext->env, scope);
1958 },
1959 TaskExecutor::TaskType::JS, "ArkUIDialogParseCustomDialogIdCallback");
1960 asyncContext = nullptr;
1961 };
1962 }
1963
OpenCustomDialog(napi_env env,std::shared_ptr<PromptAsyncContext> & asyncContext,PromptDialogAttr & promptDialogAttr,std::function<void (int32_t)> & openCallback)1964 void OpenCustomDialog(napi_env env, std::shared_ptr<PromptAsyncContext>& asyncContext,
1965 PromptDialogAttr& promptDialogAttr, std::function<void(int32_t)>& openCallback)
1966 {
1967 #ifdef OHOS_STANDARD_SYSTEM
1968 // NG
1969 if (SystemProperties::GetExtSurfaceEnabled() || !ContainerIsService()) {
1970 auto delegate = EngineHelper::GetCurrentDelegateSafely();
1971 if (delegate) {
1972 delegate->OpenCustomDialog(promptDialogAttr, std::move(openCallback));
1973 } else {
1974 // throw internal error
1975 std::string strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "Can not get delegate.";
1976 JSPromptThrowInterError(env, asyncContext, strMsg);
1977 }
1978 } else if (SubwindowManager::GetInstance() != nullptr) {
1979 SubwindowManager::GetInstance()->OpenCustomDialog(promptDialogAttr, std::move(openCallback));
1980 }
1981 #else
1982 auto delegate = EngineHelper::GetCurrentDelegateSafely();
1983 if (delegate) {
1984 delegate->OpenCustomDialog(promptDialogAttr, std::move(openCallback));
1985 } else {
1986 // throw internal error
1987 std::string strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "UI execution context not found.";
1988 JSPromptThrowInterError(env, asyncContext, strMsg);
1989 }
1990 #endif
1991 }
1992
JSPromptOpenCustomDialog(napi_env env,napi_callback_info info)1993 napi_value JSPromptOpenCustomDialog(napi_env env, napi_callback_info info)
1994 {
1995 size_t argc = 2;
1996 napi_value argv[2] = { nullptr };
1997 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
1998 if (argc < 1) {
1999 NapiThrow(
2000 env, "The number of parameters must be greater than or equal to 1.", ERROR_CODE_PARAM_INVALID);
2001 return nullptr;
2002 }
2003
2004 auto asyncContext = std::make_shared<PromptAsyncContext>();
2005 asyncContext->env = env;
2006 asyncContext->instanceId = Container::CurrentIdSafely();
2007 bool parseOK = JSPromptParseParam(env, argc, argv, asyncContext);
2008 if (!parseOK) {
2009 return nullptr;
2010 }
2011 napi_value result = nullptr;
2012 napi_create_promise(env, &asyncContext->deferred, &result);
2013
2014 std::function<void(const int32_t& info)> onWillDismiss = nullptr;
2015 if (asyncContext->onWillDismissRef) {
2016 ParseDialogCallback(asyncContext, onWillDismiss);
2017 }
2018 std::function<void(int32_t)> openCallback = nullptr;
2019 PromptDialogAttr promptDialogAttr = GetPromptActionDialog(env, asyncContext, onWillDismiss);
2020 if (!asyncContext->builderRef) {
2021 ParseCustomDialogContentCallback(asyncContext, openCallback);
2022 promptDialogAttr.customStyle = true;
2023 promptDialogAttr.customBuilder = nullptr;
2024 } else {
2025 ParseCustomDialogIdCallback(asyncContext, openCallback);
2026 }
2027
2028 OpenCustomDialog(env, asyncContext, promptDialogAttr, openCallback);
2029
2030 return result;
2031 }
2032
CloseCustomDialog(napi_env env,std::shared_ptr<PromptAsyncContext> & asyncContext,bool useDialogId,int32_t dialogId,const WeakPtr<NG::UINode> & nodeWk,std::function<void (int32_t)> & contentCallback)2033 void CloseCustomDialog(napi_env env, std::shared_ptr<PromptAsyncContext>& asyncContext, bool useDialogId,
2034 int32_t dialogId, const WeakPtr<NG::UINode>& nodeWk, std::function<void(int32_t)>& contentCallback)
2035 {
2036 #ifdef OHOS_STANDARD_SYSTEM
2037 // NG
2038 if (SystemProperties::GetExtSurfaceEnabled() || !ContainerIsService()) {
2039 auto delegate = EngineHelper::GetCurrentDelegateSafely();
2040 if (delegate) {
2041 if (useDialogId) {
2042 delegate->CloseCustomDialog(dialogId);
2043 } else {
2044 delegate->CloseCustomDialog(nodeWk, std::move(contentCallback));
2045 }
2046 } else {
2047 // throw internal error
2048 napi_create_promise(env, &asyncContext->deferred, nullptr);
2049 std::string strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "Can not get delegate.";
2050 JSPromptThrowInterError(env, asyncContext, strMsg);
2051 }
2052 } else if (SubwindowManager::GetInstance() != nullptr) {
2053 if (useDialogId) {
2054 SubwindowManager::GetInstance()->CloseCustomDialogNG(dialogId);
2055 } else {
2056 SubwindowManager::GetInstance()->CloseCustomDialogNG(nodeWk, std::move(contentCallback));
2057 }
2058 }
2059 #else
2060 auto delegate = EngineHelper::GetCurrentDelegateSafely();
2061 if (delegate) {
2062 if (useDialogId) {
2063 delegate->CloseCustomDialog(dialogId);
2064 } else {
2065 delegate->CloseCustomDialog(nodeWk, std::move(contentCallback));
2066 }
2067 } else {
2068 // throw internal error
2069 napi_create_promise(env, &asyncContext->deferred, nullptr);
2070 std::string strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "UI execution context not found.";
2071 JSPromptThrowInterError(env, asyncContext, strMsg);
2072 }
2073 #endif
2074 }
2075
JSPromptCloseCustomDialog(napi_env env,napi_callback_info info)2076 napi_value JSPromptCloseCustomDialog(napi_env env, napi_callback_info info)
2077 {
2078 size_t argc = 1;
2079 napi_value argv[1] = { 0 };
2080 int32_t dialogId = -1;
2081 WeakPtr<NG::UINode> nodeWk;
2082 bool useDialogId = true;
2083 std::function<void(int32_t)> contentCallback = nullptr;
2084 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
2085 auto asyncContext = std::make_shared<PromptAsyncContext>();
2086 asyncContext->env = env;
2087 asyncContext->instanceId = Container::CurrentIdSafely();
2088 napi_value ret = nullptr;
2089 if (argc > 1) {
2090 NapiThrow(env, "The number of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
2091 return nullptr;
2092 } else if (argc == 0) {
2093 dialogId = -1;
2094 } else {
2095 napi_valuetype valueType = napi_undefined;
2096 napi_typeof(env, argv[0], &valueType);
2097 if (valueType == napi_number) {
2098 napi_get_value_int32(env, argv[0], &dialogId);
2099 } else if (valueType == napi_object) {
2100 napi_value frameNodePtr = nullptr;
2101 auto result = napi_get_named_property(env, argv[0], "nodePtr_", &frameNodePtr);
2102 if (result != napi_ok) {
2103 NapiThrow(env, "The type of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
2104 return nullptr;
2105 }
2106 void* nativePtr = nullptr;
2107 result = napi_get_value_external(env, frameNodePtr, &nativePtr);
2108 if (result != napi_ok) {
2109 NapiThrow(env, "The type of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
2110 return nullptr;
2111 }
2112 auto* uiNodePtr = reinterpret_cast<OHOS::Ace::NG::UINode*>(nativePtr);
2113 nodeWk = AceType::WeakClaim(uiNodePtr);
2114 useDialogId = false;
2115 napi_create_promise(env, &asyncContext->deferred, &ret);
2116 ParseCustomDialogContentCallback(asyncContext, contentCallback);
2117 } else {
2118 NapiThrow(env, "The type of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
2119 return nullptr;
2120 }
2121 }
2122
2123 CloseCustomDialog(env, asyncContext, useDialogId, dialogId, nodeWk, contentCallback);
2124
2125 return ret;
2126 }
2127
UpdateCustomDialog(napi_env env,std::shared_ptr<PromptAsyncContext> & asyncContext,PromptDialogAttr & promptDialogAttr,const WeakPtr<NG::UINode> & nodeWk,std::function<void (int32_t)> & contentCallback)2128 void UpdateCustomDialog(napi_env env, std::shared_ptr<PromptAsyncContext>& asyncContext,
2129 PromptDialogAttr& promptDialogAttr, const WeakPtr<NG::UINode>& nodeWk,
2130 std::function<void(int32_t)>& contentCallback)
2131 {
2132 #ifdef OHOS_STANDARD_SYSTEM
2133 // NG
2134 if (SystemProperties::GetExtSurfaceEnabled() || !ContainerIsService()) {
2135 auto delegate = EngineHelper::GetCurrentDelegateSafely();
2136 if (delegate) {
2137 delegate->UpdateCustomDialog(nodeWk, promptDialogAttr, std::move(contentCallback));
2138 } else {
2139 // throw internal error
2140 napi_create_promise(env, &asyncContext->deferred, nullptr);
2141 std::string strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "Can not get delegate.";
2142 JSPromptThrowInterError(env, asyncContext, strMsg);
2143 }
2144 } else if (SubwindowManager::GetInstance() != nullptr) {
2145 SubwindowManager::GetInstance()->UpdateCustomDialogNG(nodeWk, promptDialogAttr, std::move(contentCallback));
2146 }
2147 #else
2148 auto delegate = EngineHelper::GetCurrentDelegateSafely();
2149 if (delegate) {
2150 delegate->UpdateCustomDialog(nodeWk, promptDialogAttr, std::move(contentCallback));
2151 } else {
2152 // throw internal error
2153 napi_create_promise(env, &asyncContext->deferred, nullptr);
2154 std::string strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "UI execution context not found.";
2155 JSPromptThrowInterError(env, asyncContext, strMsg);
2156 }
2157 #endif
2158 }
2159
JSPromptUpdateCustomDialog(napi_env env,napi_callback_info info)2160 napi_value JSPromptUpdateCustomDialog(napi_env env, napi_callback_info info)
2161 {
2162 size_t argc = CUSTOM_DIALOG_PARAM_NUM;
2163 napi_value argv[CUSTOM_DIALOG_PARAM_NUM] = { nullptr };
2164 WeakPtr<NG::UINode> nodeWk;
2165 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
2166 if (argc != CUSTOM_DIALOG_PARAM_NUM) {
2167 NapiThrow(env, "The number of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
2168 return nullptr;
2169 }
2170 auto asyncContext = std::make_shared<PromptAsyncContext>();
2171 asyncContext->env = env;
2172 asyncContext->instanceId = Container::CurrentIdSafely();
2173 napi_value ret = nullptr;
2174
2175 napi_valuetype valueType = napi_undefined;
2176 napi_typeof(env, argv[0], &valueType);
2177 if (valueType == napi_object) {
2178 napi_value frameNodePtr = nullptr;
2179 auto result = napi_get_named_property(env, argv[0], "nodePtr_", &frameNodePtr);
2180 if (result != napi_ok) {
2181 NapiThrow(env, "The type of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
2182 return nullptr;
2183 }
2184 void* nativePtr = nullptr;
2185 result = napi_get_value_external(env, frameNodePtr, &nativePtr);
2186 if (result != napi_ok) {
2187 NapiThrow(env, "The type of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
2188 return nullptr;
2189 }
2190 auto* uiNodePtr = reinterpret_cast<OHOS::Ace::NG::UINode*>(nativePtr);
2191 nodeWk = AceType::WeakClaim(uiNodePtr);
2192 } else {
2193 NapiThrow(env, "The type of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
2194 return nullptr;
2195 }
2196
2197 napi_typeof(env, argv[1], &valueType);
2198 if (valueType != napi_object) {
2199 NapiThrow(env, "The type of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
2200 return nullptr;
2201 }
2202 GetNapiNamedProperties(env, argv, 1, asyncContext);
2203
2204 napi_create_promise(env, &asyncContext->deferred, &ret);
2205 std::function<void(int32_t)> contentCallback = nullptr;
2206 ParseCustomDialogContentCallback(asyncContext, contentCallback);
2207 PromptDialogAttr promptDialogAttr = GetPromptActionDialog(env, asyncContext, nullptr);
2208
2209 UpdateCustomDialog(env, asyncContext, promptDialogAttr, nodeWk, contentCallback);
2210
2211 return ret;
2212 }
2213
2214 } // namespace OHOS::Ace::Napi
2215