• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &paramObj);
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, &paramObj, 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