• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2025 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 #include "prompt_controller.h"
18 
19 #include "interfaces/napi/kits/utils/napi_utils.h"
20 #include "base/subwindow/subwindow_manager.h"
21 #include "bridge/common/utils/engine_helper.h"
22 #include "core/common/ace_engine.h"
23 #include "core/components/theme/shadow_theme.h"
24 #include "core/components/toast/toast_theme.h"
25 #include "core/components/button/button_theme.h"
26 #include "core/components_ng/pattern/overlay/level_order.h"
27 #include "core/pipeline/pipeline_base.h"
28 
29 namespace OHOS::Ace::Napi {
30 namespace {
31 const int32_t SHOW_DIALOG_BUTTON_NUM_MAX = -1;
32 const int32_t SHOW_ACTION_MENU_BUTTON_NUM_MAX = 6;
33 const int32_t CUSTOM_DIALOG_PARAM_NUM = 2;
34 const int32_t BG_BLUR_STYLE_MAX_INDEX = 13;
35 const int32_t PROMPTACTION_VALID_PRIMARY_BUTTON_NUM = 1;
36 const int32_t OPEN_CUSTOM_DIALOG_WITH_CONTROLLER_PARAM_TOTAL = 3;
37 const int32_t OPEN_CUSTOM_DIALOG_WITH_CONTROLLER_PARAM_MAND_COUNT = 2;
38 const int32_t OPEN_CUSTOM_DIALOG_WITH_CONTROLLER_PARAM_INDEX_CONTROLLER = 1;
39 const int32_t OPEN_CUSTOM_DIALOG_WITH_CONTROLLER_PARAM_INDEX_OPTIONS = 2;
40 const int32_t PRESENT_CUSTOM_DIALOG_PARAM_TOTAL = 3;
41 const int32_t PRESENT_CUSTOM_DIALOG_PARAM_MAND_COUNT = 1;
42 const int32_t PRESENT_CUSTOM_DIALOG_PARAM_INDEX_CONTROLLER = 1;
43 const int32_t PRESENT_CUSTOM_DIALOG_PARAM_INDEX_OPTIONS = 2;
44 constexpr char DEFAULT_FONT_COLOR_STRING_VALUE[] = "#ff007dff";
45 constexpr float DEFAULT_AVOID_DISTANCE = 16.0f;
46 const std::vector<DialogAlignment> DIALOG_ALIGNMENT = { DialogAlignment::TOP, DialogAlignment::CENTER,
47     DialogAlignment::BOTTOM, DialogAlignment::DEFAULT, DialogAlignment::TOP_START, DialogAlignment::TOP_END,
48     DialogAlignment::CENTER_START, DialogAlignment::CENTER_END, DialogAlignment::BOTTOM_START,
49     DialogAlignment::BOTTOM_END };
50 const std::vector<KeyboardAvoidMode> KEYBOARD_AVOID_MODE = { KeyboardAvoidMode::DEFAULT, KeyboardAvoidMode::NONE };
51 const std::vector<HoverModeAreaType> HOVER_MODE_AREA_TYPE = { HoverModeAreaType::TOP_SCREEN,
52     HoverModeAreaType::BOTTOM_SCREEN };
53 const std::vector<LevelMode> DIALOG_LEVEL_MODE = { LevelMode::OVERLAY, LevelMode::EMBEDDED };
54 const std::vector<ImmersiveMode> DIALOG_IMMERSIVE_MODE = { ImmersiveMode::DEFAULT, ImmersiveMode::EXTEND};
55 
56 #ifdef OHOS_STANDARD_SYSTEM
ContainerIsService()57 bool ContainerIsService()
58 {
59     auto containerId = Container::CurrentIdSafely();
60     // Get active container when current instanceid is less than 0
61     if (containerId < 0) {
62         auto container = Container::GetActive();
63         if (container) {
64             containerId = container->GetInstanceId();
65         }
66     }
67     // for pa service
68     return containerId >= MIN_PA_SERVICE_ID || containerId < 0;
69 }
70 
ContainerIsSceneBoard()71 bool ContainerIsSceneBoard()
72 {
73     auto container = Container::CurrentSafely();
74     if (!container) {
75         container = Container::GetActive();
76     }
77 
78     return container && container->IsSceneBoardWindow();
79 }
80 #endif
81 } // namespace
82 
GetToastMessage(napi_env env,napi_value messageNApi,std::string & messageString)83 bool GetToastMessage(napi_env env, napi_value messageNApi, std::string& messageString)
84 {
85     size_t ret = 0;
86     ResourceInfo recv;
87     napi_valuetype valueType = napi_undefined;
88     napi_typeof(env, messageNApi, &valueType);
89     if (valueType == napi_string) {
90         size_t messageLen = GetParamLen(env, messageNApi) + 1;
91         std::unique_ptr<char[]> message = std::make_unique<char[]>(messageLen);
92         napi_get_value_string_utf8(env, messageNApi, message.get(), messageLen, &ret);
93         messageString = message.get();
94     } else if (valueType == napi_object) {
95         if (!ParseResourceParam(env, messageNApi, recv)) {
96             NapiThrow(env, "Can not parse resource info from input params.", ERROR_CODE_INTERNAL_ERROR);
97             return false;
98         }
99         if (!ParseString(recv, messageString)) {
100             NapiThrow(env, "Can not get message from resource manager.", ERROR_CODE_INTERNAL_ERROR);
101             return false;
102         }
103         if (messageString.size() == 0) {
104             TAG_LOGE(AceLogTag::ACE_DIALOG, "Toast message is empty");
105         }
106     } else {
107         NapiThrow(env, "The type of message is incorrect.", ERROR_CODE_PARAM_INVALID);
108         return false;
109     }
110     return true;
111 }
112 
GetToastDuration(napi_env env,napi_value durationNApi,int32_t & duration)113 bool GetToastDuration(napi_env env, napi_value durationNApi, int32_t& duration)
114 {
115     napi_valuetype valueType = napi_undefined;
116     napi_typeof(env, durationNApi, &valueType);
117     ResourceInfo recv;
118     std::string durationStr;
119     if (valueType == napi_number) {
120         napi_get_value_int32(env, durationNApi, &duration);
121     } else if (valueType == napi_object) {
122         recv = {};
123         if (!ParseResourceParam(env, durationNApi, recv)) {
124             NapiThrow(env, "Can not parse resource info from input params.", ERROR_CODE_INTERNAL_ERROR);
125             return false;
126         }
127         if (!ParseString(recv, durationStr)) {
128             NapiThrow(env, "Can not get message from resource manager.", ERROR_CODE_INTERNAL_ERROR);
129             return false;
130         }
131         duration = StringUtils::StringToInt(durationStr);
132     }
133     return true;
134 }
135 
GetToastBottom(napi_env env,napi_value bottomNApi,std::string & bottomString)136 bool GetToastBottom(napi_env env, napi_value bottomNApi, std::string& bottomString)
137 {
138     size_t ret = 0;
139     ResourceInfo recv;
140     napi_valuetype valueType = napi_undefined;
141     napi_typeof(env, bottomNApi, &valueType);
142     if (valueType == napi_string) {
143         size_t bottomLen = GetParamLen(env, bottomNApi) + 1;
144         std::unique_ptr<char[]> bottom = std::make_unique<char[]>(bottomLen);
145         napi_get_value_string_utf8(env, bottomNApi, bottom.get(), bottomLen, &ret);
146         bottomString = bottom.get();
147     } else if (valueType == napi_number) {
148         double bottom = 0.0;
149         napi_get_value_double(env, bottomNApi, &bottom);
150         bottomString = std::to_string(bottom);
151     } else if (valueType == napi_object) {
152         recv = {};
153         if (!ParseResourceParam(env, bottomNApi, recv)) {
154             NapiThrow(env, "Can not parse resource info from input params.", ERROR_CODE_INTERNAL_ERROR);
155             return false;
156         }
157         if (!ParseString(recv, bottomString)) {
158             NapiThrow(env, "Can not get message from resource manager.", ERROR_CODE_INTERNAL_ERROR);
159             return false;
160         }
161     }
162     return true;
163 }
164 
GetToastShowMode(napi_env env,napi_value showModeNApi,NG::ToastShowMode & showMode)165 bool GetToastShowMode(napi_env env, napi_value showModeNApi, NG::ToastShowMode& showMode)
166 {
167     napi_valuetype valueType = napi_undefined;
168     napi_typeof(env, showModeNApi, &valueType);
169     if (valueType == napi_number) {
170         int32_t num = -1;
171         napi_get_value_int32(env, showModeNApi, &num);
172         if (num >= 0 && num <= static_cast<int32_t>(NG::ToastShowMode::SYSTEM_TOP_MOST)) {
173             showMode = static_cast<NG::ToastShowMode>(num);
174         }
175     }
176     return true;
177 }
178 
GetToastAlignment(napi_env env,napi_value alignmentApi,int32_t & alignment)179 bool GetToastAlignment(napi_env env, napi_value alignmentApi, int32_t& alignment)
180 {
181     napi_valuetype valueType = napi_undefined;
182     napi_typeof(env, alignmentApi, &valueType);
183     if (valueType == napi_number) {
184         napi_get_value_int32(env, alignmentApi, &alignment);
185     }
186     return true;
187 }
188 
GetToastOffset(napi_env env,napi_value offsetApi,std::optional<DimensionOffset> & offset)189 bool GetToastOffset(napi_env env, napi_value offsetApi, std::optional<DimensionOffset>& offset)
190 {
191     napi_valuetype valueType = napi_undefined;
192     napi_typeof(env, offsetApi, &valueType);
193     if (valueType == napi_object) {
194         napi_value dxApi = nullptr;
195         napi_value dyApi = nullptr;
196         napi_get_named_property(env, offsetApi, "dx", &dxApi);
197         napi_get_named_property(env, offsetApi, "dy", &dyApi);
198         CalcDimension dx;
199         CalcDimension dy;
200         ParseNapiDimension(env, dx, dxApi, DimensionUnit::VP);
201         ParseNapiDimension(env, dy, dyApi, DimensionUnit::VP);
202         offset = DimensionOffset { dx, dy };
203     }
204     return true;
205 }
206 
GetToastBackgroundColor(napi_env env,napi_value backgroundColorNApi,std::optional<Color> & backgroundColor)207 void GetToastBackgroundColor(napi_env env, napi_value backgroundColorNApi, std::optional<Color>& backgroundColor)
208 {
209     napi_valuetype valueType = napi_undefined;
210     napi_typeof(env, backgroundColorNApi, &valueType);
211     Color color;
212     backgroundColor = std::nullopt;
213     if (ParseNapiColor(env, backgroundColorNApi, color)) {
214         backgroundColor = color;
215     }
216 }
217 
GetToastTextColor(napi_env env,napi_value textColorNApi,std::optional<Color> & textColor)218 void GetToastTextColor(napi_env env, napi_value textColorNApi, std::optional<Color>& textColor)
219 {
220     napi_valuetype valueType = napi_undefined;
221     napi_typeof(env, textColorNApi, &valueType);
222     Color color;
223     textColor = std::nullopt;
224     if (ParseNapiColor(env, textColorNApi, color)) {
225         textColor = color;
226     }
227 }
228 
GetToastBackgroundBlurStyle(napi_env env,napi_value backgroundBlurStyleNApi,std::optional<int32_t> & backgroundBlurStyle)229 void GetToastBackgroundBlurStyle(napi_env env,
230     napi_value backgroundBlurStyleNApi, std::optional<int32_t>& backgroundBlurStyle)
231 {
232     napi_valuetype valueType = napi_undefined;
233     napi_typeof(env, backgroundBlurStyleNApi, &valueType);
234     if (valueType == napi_number) {
235         int32_t num;
236         napi_get_value_int32(env, backgroundBlurStyleNApi, &num);
237         if (num >= 0 && num < BG_BLUR_STYLE_MAX_INDEX) {
238             backgroundBlurStyle = num;
239         }
240     }
241 }
242 
GetShadowFromTheme(ShadowStyle shadowStyle,Shadow & shadow)243 bool GetShadowFromTheme(ShadowStyle shadowStyle, Shadow& shadow)
244 {
245     if (shadowStyle == ShadowStyle::None) {
246         return true;
247     }
248     auto container = Container::CurrentSafelyWithCheck();
249     CHECK_NULL_RETURN(container, false);
250     auto colorMode = container->GetColorMode();
251     auto pipelineContext = container->GetPipelineContext();
252     CHECK_NULL_RETURN(pipelineContext, false);
253     auto shadowTheme = pipelineContext->GetTheme<ShadowTheme>();
254     if (!shadowTheme) {
255         return false;
256     }
257     shadow = shadowTheme->GetShadow(shadowStyle, colorMode);
258     return true;
259 }
260 
ParseResource(const ResourceInfo resource,CalcDimension & result)261 bool ParseResource(const ResourceInfo resource, CalcDimension& result)
262 {
263     auto resourceWrapper = CreateResourceWrapper(resource);
264     CHECK_NULL_RETURN(resourceWrapper, false);
265     if (resource.type == static_cast<uint32_t>(ResourceType::STRING)) {
266         auto value = resourceWrapper->GetString(resource.resId);
267         return StringUtils::StringToCalcDimensionNG(value, result, false);
268     }
269     if (resource.type == static_cast<uint32_t>(ResourceType::INTEGER)) {
270         auto value = std::to_string(resourceWrapper->GetInt(resource.resId));
271         StringUtils::StringToDimensionWithUnitNG(value, result);
272         return true;
273     }
274     if (resource.type == static_cast<uint32_t>(ResourceType::FLOAT)) {
275         result = resourceWrapper->GetDimension(resource.resId);
276         return true;
277     }
278     return false;
279 }
280 
GetToastObjectShadow(napi_env env,napi_value shadowNApi,Shadow & shadowProps)281 void GetToastObjectShadow(napi_env env, napi_value shadowNApi, Shadow& shadowProps)
282 {
283     napi_value radiusApi = nullptr;
284     napi_value colorApi = nullptr;
285     napi_value typeApi = nullptr;
286     napi_value fillApi = nullptr;
287     napi_get_named_property(env, shadowNApi, "radius", &radiusApi);
288     napi_get_named_property(env, shadowNApi, "color", &colorApi);
289     napi_get_named_property(env, shadowNApi, "type", &typeApi);
290     napi_get_named_property(env, shadowNApi, "fill", &fillApi);
291     ResourceInfo recv;
292     double radiusValue = 0.0;
293     if (ParseResourceParam(env, radiusApi, recv)) {
294         CalcDimension radius;
295         if (ParseResource(recv, radius)) {
296             radiusValue = LessNotEqual(radius.Value(), 0.0) ? 0.0 : radius.Value();
297         }
298     } else {
299         napi_get_value_double(env, radiusApi, &radiusValue);
300         if (LessNotEqual(radiusValue, 0.0)) {
301             radiusValue = 0.0;
302         }
303     }
304     shadowProps.SetBlurRadius(radiusValue);
305     Color color;
306     ShadowColorStrategy shadowColorStrategy;
307     if (ParseShadowColorStrategy(env, colorApi, shadowColorStrategy)) {
308         shadowProps.SetShadowColorStrategy(shadowColorStrategy);
309     } else if (ParseNapiColor(env, colorApi, color)) {
310         shadowProps.SetColor(color);
311     }
312     napi_valuetype valueType = GetValueType(env, typeApi);
313     int32_t shadowType = static_cast<int32_t>(ShadowType::COLOR);
314     if (valueType == napi_number) {
315         napi_get_value_int32(env, typeApi, &shadowType);
316     }
317     if (shadowType != static_cast<int32_t>(ShadowType::BLUR)) {
318         shadowType = static_cast<int32_t>(ShadowType::COLOR);
319     }
320     shadowType =
321         std::clamp(shadowType, static_cast<int32_t>(ShadowType::COLOR), static_cast<int32_t>(ShadowType::BLUR));
322     shadowProps.SetShadowType(static_cast<ShadowType>(shadowType));
323     valueType = GetValueType(env, fillApi);
324     bool isFilled = false;
325     if (valueType == napi_boolean) {
326         napi_get_value_bool(env, fillApi, &isFilled);
327     }
328     shadowProps.SetIsFilled(isFilled);
329 }
330 
GetToastDefaultShadowStyle()331 ShadowStyle GetToastDefaultShadowStyle()
332 {
333     auto shadowStyle = ShadowStyle::OuterDefaultMD;
334     auto container = Container::Current();
335     CHECK_NULL_RETURN(container, shadowStyle);
336     auto pipelineContext = container->GetPipelineContext();
337     CHECK_NULL_RETURN(pipelineContext, shadowStyle);
338     auto toastTheme = pipelineContext->GetTheme<ToastTheme>();
339     CHECK_NULL_RETURN(toastTheme, shadowStyle);
340     return toastTheme->GetToastShadowStyle();
341 }
342 
GetToastShadow(napi_env env,napi_value shadowNApi,std::optional<Shadow> & shadow,bool & isTypeStyleShadow)343 void GetToastShadow(napi_env env, napi_value shadowNApi, std::optional<Shadow>& shadow, bool& isTypeStyleShadow)
344 {
345     Shadow shadowProps;
346     napi_valuetype valueType = napi_undefined;
347     napi_typeof(env, shadowNApi, &valueType);
348     if (valueType == napi_number) {
349         int32_t num = 0;
350         napi_get_value_int32(env, shadowNApi, &num);
351         auto style = static_cast<ShadowStyle>(num);
352         CHECK_EQUAL_VOID(GetShadowFromTheme(style, shadowProps), false);
353     } else if (valueType == napi_object) {
354         napi_value offsetXApi = nullptr;
355         napi_value offsetYApi = nullptr;
356         napi_get_named_property(env, shadowNApi, "offsetX", &offsetXApi);
357         napi_get_named_property(env, shadowNApi, "offsetY", &offsetYApi);
358         ResourceInfo recv;
359         bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
360         if (ParseResourceParam(env, offsetXApi, recv)) {
361             CalcDimension offsetX;
362             if (ParseResource(recv, offsetX)) {
363                 double xValue = isRtl ? offsetX.Value() * (-1) : offsetX.Value();
364                 shadowProps.SetOffsetX(xValue);
365             }
366         } else {
367             CalcDimension offsetX;
368             if (ParseNapiDimension(env, offsetX, offsetXApi, DimensionUnit::VP)) {
369                 double xValue = isRtl ? offsetX.Value() * (-1) : offsetX.Value();
370                 shadowProps.SetOffsetX(xValue);
371             }
372         }
373         if (ParseResourceParam(env, offsetYApi, recv)) {
374             CalcDimension offsetY;
375             if (ParseResource(recv, offsetY)) {
376                 shadowProps.SetOffsetY(offsetY.Value());
377             }
378         } else {
379             CalcDimension offsetY;
380             if (ParseNapiDimension(env, offsetY, offsetYApi, DimensionUnit::VP)) {
381                 shadowProps.SetOffsetY(offsetY.Value());
382             }
383         }
384         GetToastObjectShadow(env, shadowNApi, shadowProps);
385         isTypeStyleShadow = false;
386     } else {
387         auto shadowStyle = GetToastDefaultShadowStyle();
388         CHECK_EQUAL_VOID(GetShadowFromTheme(shadowStyle, shadowProps), false);
389     }
390     shadow = shadowProps;
391 }
392 
GetToastEnableHoverMode(napi_env env,napi_value enableHoverModeNApi,bool & enableHoverMode)393 void GetToastEnableHoverMode(napi_env env, napi_value enableHoverModeNApi, bool& enableHoverMode)
394 {
395     napi_valuetype valueType = napi_undefined;
396     napi_typeof(env, enableHoverModeNApi, &valueType);
397     if (valueType == napi_boolean) {
398         napi_get_value_bool(env, enableHoverModeNApi, &enableHoverMode);
399     }
400 }
401 
GetToastHoverModeArea(napi_env env,napi_value hoverModeAreaNApi,HoverModeAreaType & hoverModeArea)402 void GetToastHoverModeArea(napi_env env, napi_value hoverModeAreaNApi, HoverModeAreaType& hoverModeArea)
403 {
404     napi_valuetype valueType = napi_undefined;
405     napi_typeof(env, hoverModeAreaNApi, &valueType);
406     if (valueType == napi_number) {
407         int32_t num = -1;
408         napi_get_value_int32(env, hoverModeAreaNApi, &num);
409         if (num >= 0 && num <= static_cast<int32_t>(HoverModeAreaType::BOTTOM_SCREEN)) {
410             hoverModeArea = static_cast<HoverModeAreaType>(num);
411         }
412     }
413 }
414 
GetToastHoverModeParams(napi_env env,napi_value argv,NG::ToastInfo & toastInfo)415 void GetToastHoverModeParams(napi_env env, napi_value argv, NG::ToastInfo& toastInfo)
416 {
417     napi_value enableHoverModeNApi = nullptr;
418     napi_value hoverModeAreaNApi = nullptr;
419 
420     napi_get_named_property(env, argv, "enableHoverMode", &enableHoverModeNApi);
421     napi_get_named_property(env, argv, "hoverModeArea", &hoverModeAreaNApi);
422 
423     GetToastEnableHoverMode(env, enableHoverModeNApi, toastInfo.enableHoverMode);
424     GetToastHoverModeArea(env, hoverModeAreaNApi, toastInfo.hoverModeArea);
425 }
426 
GetToastParams(napi_env env,napi_value argv,NG::ToastInfo & toastInfo)427 bool GetToastParams(napi_env env, napi_value argv, NG::ToastInfo& toastInfo)
428 {
429     napi_value messageNApi = nullptr;
430     napi_value durationNApi = nullptr;
431     napi_value bottomNApi = nullptr;
432     napi_value showModeNApi = nullptr;
433     napi_value alignmentApi = nullptr;
434     napi_value offsetApi = nullptr;
435     napi_value backgroundColorNApi = nullptr;
436     napi_value textColorNApi = nullptr;
437     napi_value backgroundBlurStyleNApi = nullptr;
438     napi_value shadowNApi = nullptr;
439 
440     napi_valuetype valueType = napi_undefined;
441     napi_typeof(env, argv, &valueType);
442     if (valueType == napi_object) {
443         // message can not be null
444         if (!HasProperty(env, argv, "message")) {
445             NapiThrow(env, "Required input parameters are missing.", ERROR_CODE_PARAM_INVALID);
446             return false;
447         }
448         napi_get_named_property(env, argv, "message", &messageNApi);
449         napi_get_named_property(env, argv, "duration", &durationNApi);
450         napi_get_named_property(env, argv, "bottom", &bottomNApi);
451         napi_get_named_property(env, argv, "showMode", &showModeNApi);
452         napi_get_named_property(env, argv, "alignment", &alignmentApi);
453         napi_get_named_property(env, argv, "offset", &offsetApi);
454         napi_get_named_property(env, argv, "backgroundColor", &backgroundColorNApi);
455         napi_get_named_property(env, argv, "textColor", &textColorNApi);
456         napi_get_named_property(env, argv, "backgroundBlurStyle", &backgroundBlurStyleNApi);
457         napi_get_named_property(env, argv, "shadow", &shadowNApi);
458     } else {
459         NapiThrow(env, "The type of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
460         return false;
461     }
462     if (!GetToastMessage(env, messageNApi, toastInfo.message) ||
463         !GetToastDuration(env, durationNApi, toastInfo.duration) ||
464         !GetToastBottom(env, bottomNApi, toastInfo.bottom) ||
465         !GetToastShowMode(env, showModeNApi, toastInfo.showMode) ||
466         !GetToastAlignment(env, alignmentApi, toastInfo.alignment) ||
467         !GetToastOffset(env, offsetApi, toastInfo.offset)) {
468         return false;
469     }
470     GetToastHoverModeParams(env, argv, toastInfo);
471     GetToastBackgroundColor(env, backgroundColorNApi, toastInfo.backgroundColor);
472     GetToastTextColor(env, textColorNApi, toastInfo.textColor);
473     GetToastBackgroundBlurStyle(env, backgroundBlurStyleNApi, toastInfo.backgroundBlurStyle);
474     GetToastShadow(env, shadowNApi, toastInfo.shadow, toastInfo.isTypeStyleShadow);
475     return true;
476 }
477 
ShowToast(napi_env env,NG::ToastInfo & toastInfo,std::function<void (int32_t)> & toastCallback)478 bool ShowToast(napi_env env, NG::ToastInfo& toastInfo, std::function<void(int32_t)>& toastCallback)
479 {
480 #ifdef OHOS_STANDARD_SYSTEM
481     if ((SystemProperties::GetExtSurfaceEnabled() || !ContainerIsService()) && !ContainerIsSceneBoard() &&
482         toastInfo.showMode == NG::ToastShowMode::DEFAULT) {
483         auto delegate = EngineHelper::GetCurrentDelegateSafely();
484         if (!delegate) {
485             NapiThrow(env, "Can not get delegate.", ERROR_CODE_INTERNAL_ERROR);
486             return false;
487         }
488         TAG_LOGD(AceLogTag::ACE_DIALOG, "before delegate show toast");
489         delegate->ShowToast(toastInfo, std::move(toastCallback));
490     } else if (SubwindowManager::GetInstance() != nullptr) {
491         TAG_LOGD(AceLogTag::ACE_DIALOG, "before subwindow manager show toast");
492         SubwindowManager::GetInstance()->ShowToast(toastInfo, std::move(toastCallback));
493     }
494 #else
495     auto delegate = EngineHelper::GetCurrentDelegateSafely();
496     if (!delegate) {
497         NapiThrow(env, "UI execution context not found.", ERROR_CODE_INTERNAL_ERROR);
498         return false;
499     }
500     if (toastInfo.showMode == NG::ToastShowMode::DEFAULT) {
501         TAG_LOGD(AceLogTag::ACE_DIALOG, "before delegate show toast");
502         delegate->ShowToast(toastInfo, std::move(toastCallback));
503     } else if (SubwindowManager::GetInstance() != nullptr) {
504         TAG_LOGD(AceLogTag::ACE_DIALOG, "before subwindow manager show toast");
505         SubwindowManager::GetInstance()->ShowToast(toastInfo, std::move(toastCallback));
506     }
507 #endif
508     return true;
509 }
510 
JSPromptShowToast(napi_env env,napi_callback_info info)511 napi_value JSPromptShowToast(napi_env env, napi_callback_info info)
512 {
513     TAG_LOGD(AceLogTag::ACE_DIALOG, "show toast enter");
514     size_t requireArgc = 1;
515     size_t argc = 1;
516     napi_value argv = nullptr;
517     napi_value thisVar = nullptr;
518     void* data = nullptr;
519     napi_get_cb_info(env, info, &argc, &argv, &thisVar, &data);
520     if (argc != requireArgc) {
521         NapiThrow(env, "The number of parameters must be equal to 1.", ERROR_CODE_PARAM_INVALID);
522         return nullptr;
523     }
524     int32_t alignment = -1;
525     int32_t updateAlignment = 0;
526     const int32_t steps = 2; // 2: alignment from theme
527     auto pipelineContext = PipelineBase::GetCurrentContext();
528     if (pipelineContext) {
529         auto toastTheme = pipelineContext->GetTheme<ToastTheme>();
530         updateAlignment = steps - 1;
531         if (toastTheme) {
532             alignment = toastTheme->GetAlign();
533             updateAlignment = steps;
534         }
535     }
536     auto toastInfo = NG::ToastInfo { .duration = -1, .showMode = NG::ToastShowMode::DEFAULT, .alignment = alignment };
537     if (!GetToastParams(env, argv, toastInfo)) {
538         return nullptr;
539     }
540     TAG_LOGD(AceLogTag::ACE_DIALOG, "The show toast process: parameters are prased successfully, "
541         "updateAlignment is %{public}d", updateAlignment);
542     std::function<void(int32_t)> toastCallback = nullptr;
543     ShowToast(env, toastInfo, toastCallback);
544     return nullptr;
545 }
546 
JSPromptOpenToast(napi_env env,napi_callback_info info)547 napi_value JSPromptOpenToast(napi_env env, napi_callback_info info)
548 {
549     TAG_LOGD(AceLogTag::ACE_DIALOG, "open toast enter");
550     size_t requireArgc = 1;
551     size_t argc = 1;
552     napi_value argv = nullptr;
553     napi_value thisVar = nullptr;
554     void* data = nullptr;
555     napi_get_cb_info(env, info, &argc, &argv, &thisVar, &data);
556     if (argc != requireArgc) {
557         NapiThrow(env, "The number of parameters must be equal to 1.", ERROR_CODE_PARAM_INVALID);
558         return nullptr;
559     }
560     auto toastInfo = NG::ToastInfo { .duration = -1, .showMode = NG::ToastShowMode::DEFAULT, .alignment = -1 };
561     if (!GetToastParams(env, argv, toastInfo)) {
562         return nullptr;
563     }
564     napi_deferred deferred;
565     napi_value result;
566     napi_create_promise(env, &deferred, &result);
567     std::function<void(int32_t)> toastCallback = nullptr;
568     toastCallback = [env, deferred](int32_t toastId) mutable {
569         napi_value napiToastId = nullptr;
570         napi_create_int32(env, toastId, &napiToastId);
571         napi_resolve_deferred(env, deferred, napiToastId);
572     };
573     if (ShowToast(env, toastInfo, toastCallback)) {
574         return result;
575     }
576     return nullptr;
577 }
578 
CloseToast(napi_env env,int32_t toastId,NG::ToastShowMode showMode)579 void CloseToast(napi_env env, int32_t toastId, NG::ToastShowMode showMode)
580 {
581     std::function<void(int32_t)> toastCloseCallback = nullptr;
582     toastCloseCallback = [env](int32_t errorCode) mutable {
583         if (errorCode != ERROR_CODE_NO_ERROR) {
584             NapiThrow(env, "", errorCode);
585         }
586     };
587 #ifdef OHOS_STANDARD_SYSTEM
588     if ((SystemProperties::GetExtSurfaceEnabled() || !ContainerIsService()) && !ContainerIsSceneBoard() &&
589         showMode == NG::ToastShowMode::DEFAULT) {
590         auto delegate = EngineHelper::GetCurrentDelegateSafely();
591         if (delegate) {
592             delegate->CloseToast(toastId, std::move(toastCloseCallback));
593         } else {
594             NapiThrow(env, "Can not get delegate.", ERROR_CODE_INTERNAL_ERROR);
595         }
596     } else if (SubwindowManager::GetInstance() != nullptr) {
597         SubwindowManager::GetInstance()->CloseToast(toastId, showMode, std::move(toastCloseCallback));
598     }
599 #else
600     auto delegate = EngineHelper::GetCurrentDelegateSafely();
601     if (!delegate) {
602         NapiThrow(env, "UI execution context not found.", ERROR_CODE_INTERNAL_ERROR);
603     }
604     if (showMode == NG::ToastShowMode::DEFAULT) {
605         delegate->CloseToast(toastId, std::move(toastCloseCallback));
606     } else if (SubwindowManager::GetInstance() != nullptr) {
607         SubwindowManager::GetInstance()->CloseToast(toastId, showMode, std::move(toastCloseCallback));
608     }
609 #endif
610 }
611 
JSPromptCloseToast(napi_env env,napi_callback_info info)612 napi_value JSPromptCloseToast(napi_env env, napi_callback_info info)
613 {
614     TAG_LOGD(AceLogTag::ACE_DIALOG, "closeToast enter");
615     size_t argc = 1;
616     napi_value args[1];
617     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
618     if (argc != 1) {
619         NapiThrow(env, "The number of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
620         return nullptr;
621     }
622     int32_t id = -1;
623     napi_get_value_int32(env, args[0], &id);
624     if (id < 0 || id > INT32_MAX) {
625         NapiThrow(env, "The toastId is invalid.", ERROR_CODE_PARAM_INVALID);
626         return nullptr;
627     }
628     int32_t showModeVal = static_cast<int32_t>(static_cast<uint32_t>(id) & 0b111);
629     int32_t toastId =
630         static_cast<int32_t>(static_cast<uint32_t>(id) >>
631                              3); // 3 : Move 3 bits to the right to get toastId, and the last 3 bits are the showMode
632     if (toastId < 0 || showModeVal < 0 || showModeVal > static_cast<int32_t>(NG::ToastShowMode::SYSTEM_TOP_MOST)) {
633         NapiThrow(env, "", ERROR_CODE_TOAST_NOT_FOUND);
634         return nullptr;
635     }
636     auto showMode = static_cast<NG::ToastShowMode>(showModeVal);
637     CloseToast(env, toastId, showMode);
638     return nullptr;
639 }
640 
641 struct PromptAsyncContext {
642     napi_env env = nullptr;
643     napi_value titleNApi = nullptr;
644     napi_value messageNApi = nullptr;
645     napi_value buttonsNApi = nullptr;
646     napi_value autoCancel = nullptr;
647     napi_value showInSubWindow = nullptr;
648     napi_value isModal = nullptr;
649     napi_value alignmentApi = nullptr;
650     napi_value offsetApi = nullptr;
651     napi_value maskRectApi = nullptr;
652     napi_value builder = nullptr;
653     napi_value onWillDismiss = nullptr;
654     napi_value backgroundColorApi = nullptr;
655     napi_value backgroundBlurStyleApi = nullptr;
656     napi_value blurStyleOptionApi = nullptr;
657     napi_value effectOptionApi = nullptr;
658     napi_value enableHoverMode = nullptr;
659     napi_value hoverModeAreaApi = nullptr;
660     napi_value borderWidthApi = nullptr;
661     napi_value borderColorApi = nullptr;
662     napi_value borderStyleApi = nullptr;
663     napi_value borderRadiusApi = nullptr;
664     napi_value shadowApi = nullptr;
665     napi_value widthApi = nullptr;
666     napi_value heightApi = nullptr;
667     napi_value frameNodePtr = nullptr;
668     napi_value maskColorApi = nullptr;
669     napi_value onDidAppear = nullptr;
670     napi_value onDidDisappear = nullptr;
671     napi_value onWillAppear = nullptr;
672     napi_value onWillDisappear = nullptr;
673     napi_value transitionApi = nullptr;
674     napi_value dialogTransitionApi = nullptr;
675     napi_value maskTransitionApi = nullptr;
676     napi_ref callbackSuccess = nullptr;
677     napi_ref callbackCancel = nullptr;
678     napi_ref callbackComplete = nullptr;
679     std::string titleString;
680     std::string messageString;
681     std::vector<ButtonInfo> buttons;
682     bool autoCancelBool = true;
683     bool showInSubWindowBool = false;
684     bool isModalBool = true;
685     std::set<std::string> callbacks;
686     std::string callbackSuccessString;
687     std::string callbackCancelString;
688     std::string callbackCompleteString;
689     napi_deferred deferred = nullptr;
690     napi_ref callbackRef = nullptr;
691     napi_ref builderRef = nullptr;
692     napi_ref onWillDismissRef = nullptr;
693     int32_t callbackType = -1;
694     int32_t successType = -1;
695     bool valid = true;
696     int32_t instanceId = -1;
697     void* nativePtr = nullptr;
698     napi_ref onDidAppearRef = nullptr;
699     napi_ref onDidDisappearRef = nullptr;
700     napi_ref onWillAppearRef = nullptr;
701     napi_ref onWillDisappearRef = nullptr;
702     napi_value keyboardAvoidModeApi = nullptr;
703     napi_value keyboardAvoidDistanceApi = nullptr;
704     napi_value levelOrderApi = nullptr;
705     napi_value dialogLevelModeApi = nullptr;
706     napi_value dialogLevelUniqueId = nullptr;
707     napi_value dialogImmersiveModeApi = nullptr;
708     napi_value focusableApi = nullptr;
709 };
710 
DeleteContextAndThrowError(napi_env env,std::shared_ptr<PromptAsyncContext> & context,const std::string & errorMessage)711 void DeleteContextAndThrowError(
712     napi_env env, std::shared_ptr<PromptAsyncContext>& context, const std::string& errorMessage)
713 {
714     if (!context) {
715         // context is null, no need to delete
716         return;
717     }
718     NapiThrow(env, errorMessage, ERROR_CODE_PARAM_INVALID);
719 }
720 
GetButtonArraryLen(napi_env env,std::shared_ptr<PromptAsyncContext> & context,int32_t maxButtonNum)721 int32_t GetButtonArraryLen(napi_env env, std::shared_ptr<PromptAsyncContext>& context,
722     int32_t maxButtonNum)
723 {
724     uint32_t buttonsLen = 0;
725     napi_get_array_length(env, context->buttonsNApi, &buttonsLen);
726     int32_t buttonsLenInt = static_cast<int32_t>(buttonsLen);
727     if (buttonsLenInt > maxButtonNum && maxButtonNum != -1) {
728         buttonsLenInt = maxButtonNum;
729     }
730     return buttonsLenInt;
731 }
732 
GetPrimaryButtonNum(napi_env env,std::shared_ptr<PromptAsyncContext> & context,int32_t buttonsLenInt,int32_t & primaryButtonNum)733 void GetPrimaryButtonNum(napi_env env, std::shared_ptr<PromptAsyncContext>& context,
734     int32_t buttonsLenInt, int32_t& primaryButtonNum)
735 {
736     napi_value buttonArray = nullptr;
737     napi_value primaryButtonNApi = nullptr;
738     napi_valuetype valueType = napi_undefined;
739     for (int32_t index = 0; index < buttonsLenInt; index++) {
740         napi_get_element(env, context->buttonsNApi, index, &buttonArray);
741         bool isPrimaryButtonSet = false;
742         napi_get_named_property(env, buttonArray, "primary", &primaryButtonNApi);
743         napi_typeof(env, primaryButtonNApi, &valueType);
744         if (valueType == napi_boolean) {
745             napi_get_value_bool(env, primaryButtonNApi, &isPrimaryButtonSet);
746         }
747         if (isPrimaryButtonSet) {
748             primaryButtonNum++;
749         }
750     }
751 }
752 
ParseButtons(napi_env env,std::shared_ptr<PromptAsyncContext> & context,int32_t maxButtonNum,int32_t & primaryButtonNum)753 bool ParseButtons(napi_env env, std::shared_ptr<PromptAsyncContext>& context,
754     int32_t maxButtonNum, int32_t& primaryButtonNum)
755 {
756     napi_value buttonArray = nullptr;
757     napi_value textNApi = nullptr;
758     napi_value colorNApi = nullptr;
759     napi_value primaryButtonNApi = nullptr;
760     napi_valuetype valueType = napi_undefined;
761     int32_t buttonsLenInt = GetButtonArraryLen(env, context, maxButtonNum);
762     GetPrimaryButtonNum(env, context, buttonsLenInt, primaryButtonNum);
763     for (int32_t index = 0; index < buttonsLenInt; index++) {
764         napi_get_element(env, context->buttonsNApi, index, &buttonArray);
765         if (!HasProperty(env, buttonArray, "text")) {
766             DeleteContextAndThrowError(env, context, "Required input parameters are missing.");
767             return false;
768         }
769         std::string textString;
770         napi_get_named_property(env, buttonArray, "text", &textNApi);
771         if (!GetNapiString(env, textNApi, textString, valueType)) {
772             DeleteContextAndThrowError(env, context, "The type of parameters is incorrect.");
773             return false;
774         }
775         if (!HasProperty(env, buttonArray, "color")) {
776             DeleteContextAndThrowError(env, context, "Required input parameters are missing.");
777             return false;
778         }
779         std::string colorString;
780         napi_get_named_property(env, buttonArray, "color", &colorNApi);
781         if (!GetNapiString(env, colorNApi, colorString, valueType)) {
782             if (valueType == napi_undefined) {
783                 colorString = DEFAULT_FONT_COLOR_STRING_VALUE;
784             } else {
785                 DeleteContextAndThrowError(env, context, "The type of parameters is incorrect.");
786                 return false;
787             }
788         }
789         ButtonInfo buttonInfo = { .text = textString, .textColor = colorString };
790         if (primaryButtonNum <= PROMPTACTION_VALID_PRIMARY_BUTTON_NUM) {
791             napi_get_named_property(env, buttonArray, "primary", &primaryButtonNApi);
792             napi_typeof(env, primaryButtonNApi, &valueType);
793             if (valueType == napi_boolean) {
794                 napi_get_value_bool(env, primaryButtonNApi, &buttonInfo.isPrimary);
795             }
796         }
797         context->buttons.emplace_back(buttonInfo);
798     }
799     return true;
800 }
801 
ParseButtonsPara(napi_env env,std::shared_ptr<PromptAsyncContext> & context,int32_t maxButtonNum,bool isShowActionMenu)802 bool ParseButtonsPara(napi_env env, std::shared_ptr<PromptAsyncContext>& context,
803     int32_t maxButtonNum, bool isShowActionMenu)
804 {
805     bool isBool = false;
806     napi_valuetype valueType = napi_undefined;
807     int32_t primaryButtonNum = 0;
808     napi_is_array(env, context->buttonsNApi, &isBool);
809     napi_typeof(env, context->buttonsNApi, &valueType);
810     if (valueType == napi_object && isBool) {
811         if (!ParseButtons(env, context, SHOW_DIALOG_BUTTON_NUM_MAX, primaryButtonNum)) {
812             return false;
813         }
814     } else if (isShowActionMenu) {
815         DeleteContextAndThrowError(env, context, "The type of the button parameters is incorrect.");
816         return false;
817     }
818     if (isShowActionMenu) {
819         std::string buttonCancelText = "Cancel";
820         auto pipeline = PipelineBase::GetCurrentContextSafelyWithCheck();
821         if (pipeline) {
822             auto theme = pipeline->GetTheme<ButtonTheme>();
823             if (theme) {
824                 buttonCancelText = theme->GetCancelText();
825             }
826         }
827         ButtonInfo buttonInfo = { .text = buttonCancelText,
828             .textColor = "", .isPrimary = primaryButtonNum == 0 ? true : false};
829         context->buttons.emplace_back(buttonInfo);
830     }
831     return true;
832 }
833 
GetNapiDialogProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext,std::optional<DialogAlignment> & alignment,std::optional<DimensionOffset> & offset,std::optional<DimensionRect> & maskRect)834 void GetNapiDialogProps(napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext,
835     std::optional<DialogAlignment>& alignment, std::optional<DimensionOffset>& offset,
836     std::optional<DimensionRect>& maskRect)
837 {
838     TAG_LOGD(AceLogTag::ACE_DIALOG, "get napi dialog props enter");
839     napi_valuetype valueType = napi_undefined;
840     // parse alignment
841     napi_typeof(env, asyncContext->alignmentApi, &valueType);
842     if (valueType == napi_number) {
843         int32_t num;
844         napi_get_value_int32(env, asyncContext->alignmentApi, &num);
845         if (num >= 0 && num < static_cast<int32_t>(DIALOG_ALIGNMENT.size())) {
846             alignment = DIALOG_ALIGNMENT[num];
847         }
848     }
849 
850     // parse offset
851     napi_typeof(env, asyncContext->offsetApi, &valueType);
852     if (valueType == napi_object) {
853         napi_value dxApi = nullptr;
854         napi_value dyApi = nullptr;
855         napi_get_named_property(env, asyncContext->offsetApi, "dx", &dxApi);
856         napi_get_named_property(env, asyncContext->offsetApi, "dy", &dyApi);
857         CalcDimension dx;
858         CalcDimension dy;
859         ParseNapiDimension(env, dx, dxApi, DimensionUnit::VP);
860         ParseNapiDimension(env, dy, dyApi, DimensionUnit::VP);
861         offset = DimensionOffset { dx, dy };
862     }
863 
864     // parse maskRect
865     DimensionRect rect;
866     rect.SetOffset(DimensionOffset(CalcDimension(0, DimensionUnit::VP), CalcDimension(0, DimensionUnit::VP)));
867     rect.SetSize(DimensionSize(CalcDimension(1, DimensionUnit::PERCENT), CalcDimension(1, DimensionUnit::PERCENT)));
868     maskRect = rect;
869     napi_typeof(env, asyncContext->maskRectApi, &valueType);
870     if (valueType == napi_object) {
871         napi_value xApi = nullptr;
872         napi_value yApi = nullptr;
873         napi_value widthApi = nullptr;
874         napi_value heightApi = nullptr;
875         napi_get_named_property(env, asyncContext->maskRectApi, "x", &xApi);
876         napi_get_named_property(env, asyncContext->maskRectApi, "y", &yApi);
877         napi_get_named_property(env, asyncContext->maskRectApi, "width", &widthApi);
878         napi_get_named_property(env, asyncContext->maskRectApi, "height", &heightApi);
879         CalcDimension x;
880         CalcDimension y;
881         CalcDimension width;
882         CalcDimension height;
883         ParseNapiDimension(env, x, xApi, DimensionUnit::VP);
884         ParseNapiDimension(env, y, yApi, DimensionUnit::VP);
885         ParseNapiDimension(env, width, widthApi, DimensionUnit::VP);
886         ParseNapiDimension(env, height, heightApi, DimensionUnit::VP);
887         DimensionOffset dimensionOffset = { x, y };
888         maskRect = DimensionRect { width, height, dimensionOffset };
889     }
890 }
891 
GetNapiBlurStyleAndHoverModeProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext,std::optional<int32_t> & backgroundBlurStyle,std::optional<HoverModeAreaType> & hoverModeArea,std::optional<bool> & enableHoverMode)892 void GetNapiBlurStyleAndHoverModeProps(napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext,
893     std::optional<int32_t>& backgroundBlurStyle, std::optional<HoverModeAreaType>& hoverModeArea,
894     std::optional<bool>& enableHoverMode)
895 {
896     TAG_LOGD(AceLogTag::ACE_DIALOG, "get napi dialog backgroundBlurStyle and hoverModeArea props enter");
897     napi_valuetype blurStyleValueType = napi_undefined;
898 
899     napi_typeof(env, asyncContext->backgroundBlurStyleApi, &blurStyleValueType);
900     if (blurStyleValueType == napi_number) {
901         int32_t num = 0;
902         napi_get_value_int32(env, asyncContext->backgroundBlurStyleApi, &num);
903         if (num >= 0 && num < BG_BLUR_STYLE_MAX_INDEX) {
904             backgroundBlurStyle = num;
905         }
906     }
907 
908     napi_valuetype enableHoverModeValueType = napi_undefined;
909     napi_typeof(env, asyncContext->enableHoverMode, &enableHoverModeValueType);
910     if (enableHoverModeValueType == napi_boolean) {
911         bool enableHoverModeBool = false;
912         napi_get_value_bool(env, asyncContext->enableHoverMode, &enableHoverModeBool);
913         enableHoverMode = enableHoverModeBool;
914     }
915 
916     napi_valuetype hoverModeValueType = napi_undefined;
917     napi_typeof(env, asyncContext->hoverModeAreaApi, &hoverModeValueType);
918     if (hoverModeValueType == napi_number) {
919         int32_t num = 0;
920         napi_get_value_int32(env, asyncContext->hoverModeAreaApi, &num);
921         if (num >= 0 && num < static_cast<int32_t>(HOVER_MODE_AREA_TYPE.size())) {
922             hoverModeArea = HOVER_MODE_AREA_TYPE[num];
923         }
924     }
925 }
926 
GetBackgroundBlurStyleOption(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext,std::optional<BlurStyleOption> & blurStyleOption)927 void GetBackgroundBlurStyleOption(napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext,
928     std::optional<BlurStyleOption>& blurStyleOption)
929 {
930     napi_valuetype valueType = napi_undefined;
931     napi_typeof(env, asyncContext->blurStyleOptionApi, &valueType);
932     if (valueType == napi_object) {
933         BlurStyleOption styleOption;
934         auto delegate = EngineHelper::GetCurrentDelegateSafely();
935         if (delegate) {
936             delegate->GetBackgroundBlurStyleOption(asyncContext->blurStyleOptionApi, styleOption);
937         }
938         if (!blurStyleOption.has_value()) {
939             blurStyleOption.emplace();
940         }
941         blurStyleOption.value() = styleOption;
942     }
943 }
944 
GetBackgroundEffect(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext,std::optional<EffectOption> & effectOption)945 void GetBackgroundEffect(
946     napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext, std::optional<EffectOption>& effectOption)
947 {
948     napi_valuetype valueType = napi_undefined;
949     napi_typeof(env, asyncContext->effectOptionApi, &valueType);
950     if (valueType == napi_object) {
951         EffectOption styleOption;
952         auto delegate = EngineHelper::GetCurrentDelegateSafely();
953         if (delegate) {
954             delegate->GetBackgroundEffect(asyncContext->effectOptionApi, styleOption);
955         }
956         if (!effectOption.has_value()) {
957             effectOption.emplace();
958         }
959         effectOption.value() = styleOption;
960     }
961 }
962 
CheckNapiDimension(CalcDimension value)963 void CheckNapiDimension(CalcDimension value)
964 {
965     if (value.IsNegative()) {
966         value.Reset();
967     }
968 }
969 
GetBorderColorProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)970 std::optional<NG::BorderColorProperty> GetBorderColorProps(
971     napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
972 {
973     napi_valuetype valueType = napi_undefined;
974     NG::BorderColorProperty colorProperty;
975     napi_typeof(env, asyncContext->borderColorApi, &valueType);
976     if (valueType != napi_number && valueType != napi_string && valueType != napi_object) {
977         return std::nullopt;
978     }
979     Color borderColor;
980     if (ParseNapiColor(env, asyncContext->borderColorApi, borderColor)) {
981         colorProperty.SetColor(borderColor);
982         return colorProperty;
983     } else if (valueType == napi_object) {
984         napi_value leftApi = nullptr;
985         napi_value rightApi = nullptr;
986         napi_value topApi = nullptr;
987         napi_value bottomApi = nullptr;
988         napi_get_named_property(env, asyncContext->borderColorApi, "left", &leftApi);
989         napi_get_named_property(env, asyncContext->borderColorApi, "right", &rightApi);
990         napi_get_named_property(env, asyncContext->borderColorApi, "top", &topApi);
991         napi_get_named_property(env, asyncContext->borderColorApi, "bottom", &bottomApi);
992         Color leftColor;
993         Color rightColor;
994         Color topColor;
995         Color bottomColor;
996         if (ParseNapiColor(env, leftApi, leftColor)) {
997             colorProperty.leftColor = leftColor;
998         }
999         if (ParseNapiColor(env, rightApi, rightColor)) {
1000             colorProperty.rightColor = rightColor;
1001         }
1002         if (ParseNapiColor(env, topApi, topColor)) {
1003             colorProperty.topColor = topColor;
1004         }
1005         if (ParseNapiColor(env, bottomApi, bottomColor)) {
1006             colorProperty.bottomColor = bottomColor;
1007         }
1008         colorProperty.multiValued = true;
1009         return colorProperty;
1010     }
1011     return std::nullopt;
1012 }
1013 
GetBorderWidthProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)1014 std::optional<NG::BorderWidthProperty> GetBorderWidthProps(
1015     napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
1016 {
1017     napi_valuetype valueType = napi_undefined;
1018     napi_typeof(env, asyncContext->borderWidthApi, &valueType);
1019     if (valueType != napi_number && valueType != napi_string && valueType != napi_object) {
1020         return std::nullopt;
1021     }
1022     NG::BorderWidthProperty borderWidthProps;
1023     CalcDimension borderWidth;
1024     if (ParseNapiDimensionNG(env, borderWidth, asyncContext->borderWidthApi, DimensionUnit::VP, true)) {
1025         CheckNapiDimension(borderWidth);
1026         borderWidthProps = NG::BorderWidthProperty({ borderWidth, borderWidth, borderWidth, borderWidth });
1027         return borderWidthProps;
1028     } else if (valueType == napi_object) {
1029         napi_value leftApi = nullptr;
1030         napi_value rightApi = nullptr;
1031         napi_value topApi = nullptr;
1032         napi_value bottomApi = nullptr;
1033         napi_get_named_property(env, asyncContext->borderWidthApi, "left", &leftApi);
1034         napi_get_named_property(env, asyncContext->borderWidthApi, "right", &rightApi);
1035         napi_get_named_property(env, asyncContext->borderWidthApi, "top", &topApi);
1036         napi_get_named_property(env, asyncContext->borderWidthApi, "bottom", &bottomApi);
1037         CalcDimension leftDimen;
1038         CalcDimension rightDimen;
1039         CalcDimension topDimen;
1040         CalcDimension bottomDimen;
1041         if (ParseNapiDimensionNG(env, leftDimen, leftApi, DimensionUnit::VP, true)) {
1042             CheckNapiDimension(leftDimen);
1043             borderWidthProps.leftDimen = leftDimen;
1044         }
1045         if (ParseNapiDimensionNG(env, rightDimen, rightApi, DimensionUnit::VP, true)) {
1046             CheckNapiDimension(rightDimen);
1047             borderWidthProps.rightDimen = rightDimen;
1048         }
1049         if (ParseNapiDimensionNG(env, topDimen, topApi, DimensionUnit::VP, true)) {
1050             CheckNapiDimension(topDimen);
1051             borderWidthProps.topDimen = topDimen;
1052         }
1053         if (ParseNapiDimensionNG(env, bottomDimen, bottomApi, DimensionUnit::VP, true)) {
1054             CheckNapiDimension(bottomDimen);
1055             borderWidthProps.bottomDimen = bottomDimen;
1056         }
1057         borderWidthProps.multiValued = true;
1058         return borderWidthProps;
1059     }
1060     return std::nullopt;
1061 }
1062 
GetBorderRadiusProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)1063 std::optional<NG::BorderRadiusProperty> GetBorderRadiusProps(
1064     napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
1065 {
1066     napi_valuetype valueType = napi_undefined;
1067     napi_typeof(env, asyncContext->borderRadiusApi, &valueType);
1068     if (valueType != napi_number && valueType != napi_object && valueType != napi_string) {
1069         return std::nullopt;
1070     }
1071     CalcDimension borderRadius;
1072     if (ParseNapiDimensionNG(env, borderRadius, asyncContext->borderRadiusApi, DimensionUnit::VP, true)) {
1073         CheckNapiDimension(borderRadius);
1074         return NG::BorderRadiusProperty(borderRadius);
1075     } else if (valueType == napi_object) {
1076         NG::BorderRadiusProperty radiusProps;
1077         napi_value topLeft = nullptr;
1078         napi_value topRight = nullptr;
1079         napi_value bottomLeft = nullptr;
1080         napi_value bottomRight = nullptr;
1081         napi_get_named_property(env, asyncContext->borderRadiusApi, "topLeft", &topLeft);
1082         napi_get_named_property(env, asyncContext->borderRadiusApi, "topRight", &topRight);
1083         napi_get_named_property(env, asyncContext->borderRadiusApi, "bottomLeft", &bottomLeft);
1084         napi_get_named_property(env, asyncContext->borderRadiusApi, "bottomRight", &bottomRight);
1085         CalcDimension radiusTopLeft;
1086         CalcDimension radiusTopRight;
1087         CalcDimension radiusBottomLeft;
1088         CalcDimension radiusBottomRight;
1089         if (ParseNapiDimensionNG(env, radiusTopLeft, topLeft, DimensionUnit::VP, true)) {
1090             CheckNapiDimension(radiusTopLeft);
1091             radiusProps.radiusTopLeft = radiusTopLeft;
1092         }
1093         if (ParseNapiDimensionNG(env, radiusTopRight, topRight, DimensionUnit::VP, true)) {
1094             CheckNapiDimension(radiusTopRight);
1095             radiusProps.radiusTopRight = radiusTopRight;
1096         }
1097         if (ParseNapiDimensionNG(env, radiusBottomLeft, bottomLeft, DimensionUnit::VP, true)) {
1098             CheckNapiDimension(radiusBottomLeft);
1099             radiusProps.radiusBottomLeft = radiusBottomLeft;
1100         }
1101         if (ParseNapiDimensionNG(env, radiusBottomRight, bottomRight, DimensionUnit::VP, true)) {
1102             CheckNapiDimension(radiusBottomRight);
1103             radiusProps.radiusBottomRight = radiusBottomRight;
1104         }
1105         radiusProps.multiValued = true;
1106         return radiusProps;
1107     }
1108     return std::nullopt;
1109 }
1110 
GetColorProps(napi_env env,napi_value value)1111 std::optional<Color> GetColorProps(napi_env env, napi_value value)
1112 {
1113     Color color;
1114     if (ParseNapiColor(env, value, color)) {
1115         return color;
1116     }
1117     return std::nullopt;
1118 }
1119 
GetBorderStyleProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)1120 std::optional<NG::BorderStyleProperty> GetBorderStyleProps(
1121     napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
1122 {
1123     NG::BorderStyleProperty styleProps;
1124     napi_valuetype valueType = napi_undefined;
1125     napi_typeof(env, asyncContext->borderStyleApi, &valueType);
1126     if (valueType != napi_number && valueType != napi_object) {
1127         return std::nullopt;
1128     } else if (valueType == napi_object) {
1129         napi_value leftApi = nullptr;
1130         napi_value rightApi = nullptr;
1131         napi_value topApi = nullptr;
1132         napi_value bottomApi = nullptr;
1133         napi_get_named_property(env, asyncContext->borderStyleApi, "left", &leftApi);
1134         napi_get_named_property(env, asyncContext->borderStyleApi, "right", &rightApi);
1135         napi_get_named_property(env, asyncContext->borderStyleApi, "top", &topApi);
1136         napi_get_named_property(env, asyncContext->borderStyleApi, "bottom", &bottomApi);
1137         std::optional<BorderStyle> styleLeft;
1138         std::optional<BorderStyle> styleRight;
1139         std::optional<BorderStyle> styleTop;
1140         std::optional<BorderStyle> styleBottom;
1141         if (ParseStyle(env, leftApi, styleLeft)) {
1142             styleProps.styleLeft = styleLeft;
1143         }
1144         if (ParseStyle(env, rightApi, styleRight)) {
1145             styleProps.styleRight = styleRight;
1146         }
1147         if (ParseStyle(env, topApi, styleTop)) {
1148             styleProps.styleTop = styleTop;
1149         }
1150         if (ParseStyle(env, bottomApi, styleBottom)) {
1151             styleProps.styleBottom = styleBottom;
1152         }
1153         styleProps.multiValued = true;
1154         return styleProps;
1155     }
1156     std::optional<BorderStyle> borderStyle;
1157     if (ParseStyle(env, asyncContext->borderStyleApi, borderStyle)) {
1158         styleProps = NG::BorderStyleProperty({ borderStyle, borderStyle, borderStyle, borderStyle });
1159         return styleProps;
1160     }
1161     return std::nullopt;
1162 }
1163 
GetNapiObjectShadow(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext,Shadow & shadow)1164 void GetNapiObjectShadow(napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext, Shadow& shadow)
1165 {
1166     napi_value radiusApi = nullptr;
1167     napi_value colorApi = nullptr;
1168     napi_value typeApi = nullptr;
1169     napi_value fillApi = nullptr;
1170     napi_get_named_property(env, asyncContext->shadowApi, "radius", &radiusApi);
1171     napi_get_named_property(env, asyncContext->shadowApi, "color", &colorApi);
1172     napi_get_named_property(env, asyncContext->shadowApi, "type", &typeApi);
1173     napi_get_named_property(env, asyncContext->shadowApi, "fill", &fillApi);
1174     double radius = 0.0;
1175     napi_get_value_double(env, radiusApi, &radius);
1176     if (LessNotEqual(radius, 0.0)) {
1177         radius = 0.0;
1178     }
1179     shadow.SetBlurRadius(radius);
1180     Color color;
1181     ShadowColorStrategy shadowColorStrategy;
1182     if (ParseShadowColorStrategy(env, colorApi, shadowColorStrategy)) {
1183         shadow.SetShadowColorStrategy(shadowColorStrategy);
1184     } else if (ParseNapiColor(env, colorApi, color)) {
1185         shadow.SetColor(color);
1186     }
1187     napi_valuetype valueType = GetValueType(env, typeApi);
1188     int32_t shadowType = static_cast<int32_t>(ShadowType::COLOR);
1189     if (valueType == napi_number) {
1190         napi_get_value_int32(env, typeApi, &shadowType);
1191     }
1192     if (shadowType != static_cast<int32_t>(ShadowType::BLUR)) {
1193         shadowType = static_cast<int32_t>(ShadowType::COLOR);
1194     }
1195     shadowType =
1196         std::clamp(shadowType, static_cast<int32_t>(ShadowType::COLOR), static_cast<int32_t>(ShadowType::BLUR));
1197     shadow.SetShadowType(static_cast<ShadowType>(shadowType));
1198     valueType = GetValueType(env, fillApi);
1199     bool isFilled = false;
1200     if (valueType == napi_boolean) {
1201         napi_get_value_bool(env, fillApi, &isFilled);
1202     }
1203     shadow.SetIsFilled(isFilled);
1204 }
1205 
GetShadowProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)1206 std::optional<Shadow> GetShadowProps(napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
1207 {
1208     Shadow shadow;
1209     napi_valuetype valueType = napi_undefined;
1210     napi_typeof(env, asyncContext->shadowApi, &valueType);
1211     if (valueType != napi_object && valueType != napi_number) {
1212         return std::nullopt;
1213     }
1214     if (valueType == napi_number) {
1215         int32_t num = 0;
1216         if (napi_get_value_int32(env, asyncContext->shadowApi, &num) == napi_ok) {
1217             auto style = static_cast<ShadowStyle>(num);
1218             GetShadowFromTheme(style, shadow);
1219             return shadow;
1220         }
1221     } else if (valueType == napi_object) {
1222         napi_value offsetXApi = nullptr;
1223         napi_value offsetYApi = nullptr;
1224         napi_get_named_property(env, asyncContext->shadowApi, "offsetX", &offsetXApi);
1225         napi_get_named_property(env, asyncContext->shadowApi, "offsetY", &offsetYApi);
1226         ResourceInfo recv;
1227         bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
1228         if (ParseResourceParam(env, offsetXApi, recv)) {
1229             auto resourceWrapper = CreateResourceWrapper(recv);
1230             CHECK_NULL_RETURN(resourceWrapper, std::nullopt);
1231             auto offsetX = resourceWrapper->GetDimension(recv.resId);
1232             double xValue = isRtl ? offsetX.Value() * (-1) : offsetX.Value();
1233             shadow.SetOffsetX(xValue);
1234         } else {
1235             CalcDimension offsetX;
1236             if (ParseNapiDimension(env, offsetX, offsetXApi, DimensionUnit::VP)) {
1237                 double xValue = isRtl ? offsetX.Value() * (-1) : offsetX.Value();
1238                 shadow.SetOffsetX(xValue);
1239             }
1240         }
1241         if (ParseResourceParam(env, offsetYApi, recv)) {
1242             auto resourceWrapper = CreateResourceWrapper(recv);
1243             CHECK_NULL_RETURN(resourceWrapper, std::nullopt);
1244             auto offsetY = resourceWrapper->GetDimension(recv.resId);
1245             shadow.SetOffsetY(offsetY.Value());
1246         } else {
1247             CalcDimension offsetY;
1248             if (ParseNapiDimension(env, offsetY, offsetYApi, DimensionUnit::VP)) {
1249                 shadow.SetOffsetY(offsetY.Value());
1250             }
1251         }
1252         GetNapiObjectShadow(env, asyncContext, shadow);
1253         return shadow;
1254     }
1255     return std::nullopt;
1256 }
1257 
GetNapiDialogWidthProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)1258 std::optional<CalcDimension> GetNapiDialogWidthProps(
1259     napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
1260 {
1261     std::optional<CalcDimension> widthProperty;
1262     CalcDimension width;
1263     if (ParseNapiDimensionNG(env, width, asyncContext->widthApi, DimensionUnit::VP, true)) {
1264         widthProperty = width;
1265     }
1266     return widthProperty;
1267 }
1268 
GetKeyboardAvoidDistanceProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)1269 std::optional<CalcDimension> GetKeyboardAvoidDistanceProps(
1270     napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
1271 {
1272     std::optional<CalcDimension> keyboardAvoidDistanceProperty;
1273     napi_valuetype valueType = napi_undefined;
1274     napi_typeof(env, asyncContext->keyboardAvoidDistanceApi, &valueType);
1275     if (valueType != napi_object) {
1276         return keyboardAvoidDistanceProperty;
1277     }
1278     if (valueType == napi_object) {
1279         napi_value avoidDistance = nullptr;
1280         napi_value avoidDistanceUnit = nullptr;
1281         napi_get_named_property(env, asyncContext->keyboardAvoidDistanceApi, "value", &avoidDistance);
1282         napi_get_named_property(env, asyncContext->keyboardAvoidDistanceApi, "unit", &avoidDistanceUnit);
1283         napi_valuetype distanceType = napi_undefined;
1284         napi_valuetype distanceUnitType = napi_undefined;
1285         napi_typeof(env, avoidDistance, &distanceType);
1286         napi_typeof(env, avoidDistanceUnit, &distanceUnitType);
1287         double avoidDistanceValue = 0.0;
1288         int32_t avoidDistanceUnitValue = 0;
1289         if (distanceType == napi_number && distanceUnitType == napi_number) {
1290             napi_get_value_double(env, avoidDistance, &avoidDistanceValue);
1291             napi_get_value_int32(env, avoidDistanceUnit, &avoidDistanceUnitValue);
1292             auto avoidDistanceUnitValueType = static_cast<DimensionUnit>(avoidDistanceUnitValue);
1293             if (avoidDistanceValue >= 0.0 && avoidDistanceUnitValueType >= DimensionUnit::PX &&
1294                 avoidDistanceUnitValueType <= DimensionUnit::CALC &&
1295                 avoidDistanceUnitValueType != DimensionUnit::PERCENT) {
1296                 Dimension dimension(avoidDistanceValue, avoidDistanceUnitValueType);
1297                 keyboardAvoidDistanceProperty = dimension;
1298             } else {
1299                 Dimension dimension(DEFAULT_AVOID_DISTANCE, DimensionUnit::VP);
1300                 keyboardAvoidDistanceProperty = dimension;
1301             }
1302         }
1303     }
1304     return keyboardAvoidDistanceProperty;
1305 }
1306 
GetNapiDialogHeightProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)1307 std::optional<CalcDimension> GetNapiDialogHeightProps(
1308     napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
1309 {
1310     std::optional<CalcDimension> heightProperty;
1311     CalcDimension height;
1312     if (ParseNapiDimensionNG(env, height, asyncContext->heightApi, DimensionUnit::VP, true)) {
1313         heightProperty = height;
1314     }
1315     return heightProperty;
1316 }
1317 
GetDialogKeyboardAvoidMode(napi_env env,napi_value keyboardAvoidModeApi)1318 int32_t GetDialogKeyboardAvoidMode(napi_env env, napi_value keyboardAvoidModeApi)
1319 {
1320     int32_t mode = 0;
1321     napi_valuetype valueType = napi_undefined;
1322     napi_typeof(env, keyboardAvoidModeApi, &valueType);
1323     if (valueType == napi_number) {
1324         napi_get_value_int32(env, keyboardAvoidModeApi, &mode);
1325     }
1326     if (mode >= 0 && mode < static_cast<int32_t>(KEYBOARD_AVOID_MODE.size())) {
1327         return mode;
1328     }
1329     return 0;
1330 }
1331 
GetDialogLevelModeAndUniqueId(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext,LevelMode & dialogLevelMode,int32_t & dialogLevelUniqueId,ImmersiveMode & dialogImmersiveMode)1332 void GetDialogLevelModeAndUniqueId(napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext,
1333     LevelMode& dialogLevelMode, int32_t& dialogLevelUniqueId, ImmersiveMode& dialogImmersiveMode)
1334 {
1335     int32_t mode = 0;
1336     int32_t immersiveMode = 0;
1337     napi_valuetype levelModeValueType = napi_undefined;
1338     napi_typeof(env, asyncContext->dialogLevelModeApi, &levelModeValueType);
1339     if (levelModeValueType == napi_number) {
1340         napi_get_value_int32(env, asyncContext->dialogLevelModeApi, &mode);
1341     }
1342     if (!asyncContext->showInSubWindowBool && mode >= 0 && mode < static_cast<int32_t>(DIALOG_LEVEL_MODE.size())) {
1343         dialogLevelMode = DIALOG_LEVEL_MODE[mode];
1344     }
1345     napi_valuetype levelUniquedIdValueType = napi_undefined;
1346     napi_typeof(env, asyncContext->dialogLevelUniqueId, &levelUniquedIdValueType);
1347     if (levelUniquedIdValueType == napi_number) {
1348         napi_get_value_int32(env, asyncContext->dialogLevelUniqueId, &dialogLevelUniqueId);
1349     }
1350     napi_valuetype immersiveModeValueType = napi_undefined;
1351     napi_typeof(env, asyncContext->dialogImmersiveModeApi, &immersiveModeValueType);
1352     if (immersiveModeValueType == napi_number) {
1353         napi_get_value_int32(env, asyncContext->dialogImmersiveModeApi, &immersiveMode);
1354     }
1355     if (immersiveMode >= 0 && immersiveMode < static_cast<int32_t>(DIALOG_IMMERSIVE_MODE.size())) {
1356         dialogImmersiveMode = DIALOG_IMMERSIVE_MODE[immersiveMode];
1357     }
1358 }
1359 
GetNapiNamedBoolProperties(napi_env env,std::shared_ptr<PromptAsyncContext> & asyncContext)1360 void GetNapiNamedBoolProperties(napi_env env, std::shared_ptr<PromptAsyncContext>& asyncContext)
1361 {
1362     napi_valuetype valueType = napi_undefined;
1363     napi_typeof(env, asyncContext->autoCancel, &valueType);
1364     if (valueType == napi_boolean) {
1365         napi_get_value_bool(env, asyncContext->autoCancel, &asyncContext->autoCancelBool);
1366     }
1367     napi_typeof(env, asyncContext->showInSubWindow, &valueType);
1368     if (valueType == napi_boolean) {
1369         napi_get_value_bool(env, asyncContext->showInSubWindow, &asyncContext->showInSubWindowBool);
1370     }
1371     napi_typeof(env, asyncContext->isModal, &valueType);
1372     if (valueType == napi_boolean) {
1373         napi_get_value_bool(env, asyncContext->isModal, &asyncContext->isModalBool);
1374     }
1375 }
1376 
GetNapiNamedProperties(napi_env env,napi_value * argv,size_t index,std::shared_ptr<PromptAsyncContext> & asyncContext)1377 void GetNapiNamedProperties(napi_env env, napi_value* argv, size_t index,
1378     std::shared_ptr<PromptAsyncContext>& asyncContext)
1379 {
1380     napi_valuetype valueType = napi_undefined;
1381 
1382     if (index == 0) {
1383         napi_get_named_property(env, argv[index], "builder", &asyncContext->builder);
1384         napi_get_named_property(env, argv[index], "backgroundColor", &asyncContext->backgroundColorApi);
1385         napi_get_named_property(env, argv[index], "backgroundBlurStyle", &asyncContext->backgroundBlurStyleApi);
1386         napi_get_named_property(env, argv[index], "backgroundBlurStyleOptions", &asyncContext->blurStyleOptionApi);
1387         napi_get_named_property(env, argv[index], "backgroundEffect", &asyncContext->effectOptionApi);
1388         napi_get_named_property(env, argv[index], "hoverModeArea", &asyncContext->hoverModeAreaApi);
1389         napi_get_named_property(env, argv[index], "cornerRadius", &asyncContext->borderRadiusApi);
1390         napi_get_named_property(env, argv[index], "borderWidth", &asyncContext->borderWidthApi);
1391         napi_get_named_property(env, argv[index], "borderColor", &asyncContext->borderColorApi);
1392         napi_get_named_property(env, argv[index], "borderStyle", &asyncContext->borderStyleApi);
1393         napi_get_named_property(env, argv[index], "shadow", &asyncContext->shadowApi);
1394         napi_get_named_property(env, argv[index], "width", &asyncContext->widthApi);
1395         napi_get_named_property(env, argv[index], "height", &asyncContext->heightApi);
1396 
1397         napi_typeof(env, asyncContext->builder, &valueType);
1398         if (valueType == napi_function) {
1399             napi_create_reference(env, asyncContext->builder, 1, &asyncContext->builderRef);
1400         }
1401     }
1402     napi_get_named_property(env, argv[index], "enableHoverMode", &asyncContext->enableHoverMode);
1403     napi_get_named_property(env, argv[index], "showInSubWindow", &asyncContext->showInSubWindow);
1404     napi_get_named_property(env, argv[index], "isModal", &asyncContext->isModal);
1405     napi_get_named_property(env, argv[index], "alignment", &asyncContext->alignmentApi);
1406     napi_get_named_property(env, argv[index], "offset", &asyncContext->offsetApi);
1407     napi_get_named_property(env, argv[index], "maskRect", &asyncContext->maskRectApi);
1408     napi_get_named_property(env, argv[index], "autoCancel", &asyncContext->autoCancel);
1409     napi_get_named_property(env, argv[index], "maskColor", &asyncContext->maskColorApi);
1410     napi_get_named_property(env, argv[index], "transition", &asyncContext->transitionApi);
1411     napi_get_named_property(env, argv[index], "dialogTransition", &asyncContext->dialogTransitionApi);
1412     napi_get_named_property(env, argv[index], "maskTransition", &asyncContext->maskTransitionApi);
1413     napi_get_named_property(env, argv[index], "onWillDismiss", &asyncContext->onWillDismiss);
1414     napi_get_named_property(env, argv[index], "onDidAppear", &asyncContext->onDidAppear);
1415     napi_get_named_property(env, argv[index], "onDidDisappear", &asyncContext->onDidDisappear);
1416     napi_get_named_property(env, argv[index], "onWillAppear", &asyncContext->onWillAppear);
1417     napi_get_named_property(env, argv[index], "onWillDisappear", &asyncContext->onWillDisappear);
1418     napi_get_named_property(env, argv[index], "keyboardAvoidMode", &asyncContext->keyboardAvoidModeApi);
1419     napi_get_named_property(env, argv[index], "keyboardAvoidDistance", &asyncContext->keyboardAvoidDistanceApi);
1420     napi_get_named_property(env, argv[index], "levelOrder", &asyncContext->levelOrderApi);
1421     napi_get_named_property(env, argv[index], "levelMode", &asyncContext->dialogLevelModeApi);
1422     napi_get_named_property(env, argv[index], "levelUniqueId", &asyncContext->dialogLevelUniqueId);
1423     napi_get_named_property(env, argv[index], "immersiveMode", &asyncContext->dialogImmersiveModeApi);
1424     napi_get_named_property(env, argv[index], "focusable", &asyncContext->focusableApi);
1425 
1426     GetNapiNamedBoolProperties(env, asyncContext);
1427 }
1428 
JSPromptParseParam(napi_env env,size_t argc,napi_value * argv,std::shared_ptr<PromptAsyncContext> & asyncContext)1429 bool JSPromptParseParam(napi_env env, size_t argc, napi_value* argv, std::shared_ptr<PromptAsyncContext>& asyncContext)
1430 {
1431     for (size_t i = 0; i < argc; i++) {
1432         napi_valuetype valueType = napi_undefined;
1433         napi_typeof(env, argv[i], &valueType);
1434         if (i == 0 || i == 1) {
1435             if (valueType != napi_object) {
1436                 DeleteContextAndThrowError(env, asyncContext, "The type of parameters is incorrect.");
1437                 return false;
1438             }
1439             GetNapiNamedProperties(env, argv, i, asyncContext);
1440             auto result = napi_get_named_property(env, argv[0], "nodePtr_", &asyncContext->frameNodePtr);
1441             if (result == napi_ok) {
1442                 napi_get_value_external(env, asyncContext->frameNodePtr, &asyncContext->nativePtr);
1443             }
1444 
1445             napi_typeof(env, asyncContext->onWillDismiss, &valueType);
1446             if (valueType == napi_function) {
1447                 napi_create_reference(env, asyncContext->onWillDismiss, 1, &asyncContext->onWillDismissRef);
1448             }
1449             napi_typeof(env, asyncContext->onDidAppear, &valueType);
1450             if (valueType == napi_function) {
1451                 napi_create_reference(env, asyncContext->onDidAppear, 1, &asyncContext->onDidAppearRef);
1452             }
1453             napi_typeof(env, asyncContext->onDidDisappear, &valueType);
1454             if (valueType == napi_function) {
1455                 napi_create_reference(env, asyncContext->onDidDisappear, 1, &asyncContext->onDidDisappearRef);
1456             }
1457             napi_typeof(env, asyncContext->onWillAppear, &valueType);
1458             if (valueType == napi_function) {
1459                 napi_create_reference(env, asyncContext->onWillAppear, 1, &asyncContext->onWillAppearRef);
1460             }
1461             napi_typeof(env, asyncContext->onWillDisappear, &valueType);
1462             if (valueType == napi_function) {
1463                 napi_create_reference(env, asyncContext->onWillDisappear, 1, &asyncContext->onWillDisappearRef);
1464             }
1465         } else {
1466             DeleteContextAndThrowError(env, asyncContext, "The type of parameters is incorrect.");
1467             return false;
1468         }
1469     }
1470     return true;
1471 }
1472 
JSPromptThrowInterError(napi_env env,std::shared_ptr<PromptAsyncContext> & asyncContext,std::string & strMsg)1473 void JSPromptThrowInterError(napi_env env, std::shared_ptr<PromptAsyncContext>& asyncContext, std::string& strMsg)
1474 {
1475     napi_value code = nullptr;
1476     std::string strCode = std::to_string(ERROR_CODE_INTERNAL_ERROR);
1477     napi_create_string_utf8(env, strCode.c_str(), strCode.length(), &code);
1478     napi_value msg = nullptr;
1479     napi_create_string_utf8(env, strMsg.c_str(), strMsg.length(), &msg);
1480     napi_value error = nullptr;
1481     napi_create_error(env, code, msg, &error);
1482 
1483     if (asyncContext->deferred) {
1484         napi_reject_deferred(env, asyncContext->deferred, error);
1485     }
1486 }
1487 
UpdatePromptAlignment(DialogAlignment & alignment)1488 void UpdatePromptAlignment(DialogAlignment& alignment)
1489 {
1490     bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
1491     if (alignment == DialogAlignment::TOP_START) {
1492         if (isRtl) {
1493             alignment = DialogAlignment::TOP_END;
1494         }
1495     } else if (alignment == DialogAlignment::TOP_END) {
1496         if (isRtl) {
1497             alignment = DialogAlignment::TOP_START;
1498         }
1499     } else if (alignment == DialogAlignment::CENTER_START) {
1500         if (isRtl) {
1501             alignment = DialogAlignment::CENTER_END;
1502         }
1503     } else if (alignment == DialogAlignment::CENTER_END) {
1504         if (isRtl) {
1505             alignment = DialogAlignment::CENTER_START;
1506         }
1507     } else if (alignment == DialogAlignment::BOTTOM_START) {
1508         if (isRtl) {
1509             alignment = DialogAlignment::BOTTOM_END;
1510         }
1511     } else if (alignment == DialogAlignment::BOTTOM_END) {
1512         if (isRtl) {
1513             alignment = DialogAlignment::BOTTOM_START;
1514         }
1515     }
1516 }
1517 
GetLevelOrderParam(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)1518 std::optional<double> GetLevelOrderParam(napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
1519 {
1520     if (asyncContext->showInSubWindowBool) {
1521         return std::nullopt;
1522     }
1523 
1524     napi_value levelOrderApi = asyncContext->levelOrderApi;
1525     NG::LevelOrder* levelOrder = nullptr;
1526     if (levelOrderApi) {
1527         napi_unwrap(env, levelOrderApi, reinterpret_cast<void**>(&levelOrder));
1528     }
1529 
1530     if (levelOrder) {
1531         return std::make_optional(levelOrder->GetOrder());
1532     }
1533     return std::nullopt;
1534 }
1535 
GetDialogLifeCycleCallback(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)1536 PromptDialogAttr GetDialogLifeCycleCallback(napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
1537 {
1538     auto onDidAppear = [env = asyncContext->env, onDidAppearRef = asyncContext->onDidAppearRef]() {
1539         if (onDidAppearRef) {
1540             napi_handle_scope scope = nullptr;
1541             napi_open_handle_scope(env, &scope);
1542             napi_value onDidAppearFunc = nullptr;
1543             napi_get_reference_value(env, onDidAppearRef, &onDidAppearFunc);
1544             napi_call_function(env, nullptr, onDidAppearFunc, 0, nullptr, nullptr);
1545             napi_delete_reference(env, onDidAppearRef);
1546             napi_close_handle_scope(env, scope);
1547         }
1548     };
1549     auto onDidDisappear = [env = asyncContext->env, onDidDisappearRef = asyncContext->onDidDisappearRef]() {
1550         if (onDidDisappearRef) {
1551             napi_handle_scope scope = nullptr;
1552             napi_open_handle_scope(env, &scope);
1553             napi_value onDidDisappearFunc = nullptr;
1554             napi_get_reference_value(env, onDidDisappearRef, &onDidDisappearFunc);
1555             napi_call_function(env, nullptr, onDidDisappearFunc, 0, nullptr, nullptr);
1556             napi_delete_reference(env, onDidDisappearRef);
1557             napi_close_handle_scope(env, scope);
1558         }
1559     };
1560     auto onWillAppear = [env = asyncContext->env, onWillAppearRef = asyncContext->onWillAppearRef]() {
1561         if (onWillAppearRef) {
1562             napi_handle_scope scope = nullptr;
1563             napi_open_handle_scope(env, &scope);
1564             napi_value onWillAppearFunc = nullptr;
1565             napi_get_reference_value(env, onWillAppearRef, &onWillAppearFunc);
1566             napi_call_function(env, nullptr, onWillAppearFunc, 0, nullptr, nullptr);
1567             napi_delete_reference(env, onWillAppearRef);
1568             napi_close_handle_scope(env, scope);
1569         }
1570     };
1571     auto onWillDisappear = [env = asyncContext->env, onWillDisappearRef = asyncContext->onWillDisappearRef]() {
1572         if (onWillDisappearRef) {
1573             napi_handle_scope scope = nullptr;
1574             napi_open_handle_scope(env, &scope);
1575             napi_value onWillDisappearFunc = nullptr;
1576             napi_get_reference_value(env, onWillDisappearRef, &onWillDisappearFunc);
1577             napi_call_function(env, nullptr, onWillDisappearFunc, 0, nullptr, nullptr);
1578             napi_delete_reference(env, onWillDisappearRef);
1579             napi_close_handle_scope(env, scope);
1580         }
1581     };
1582     PromptDialogAttr promptDialogAttr = {
1583         .onDidAppear =  std::move(onDidAppear),
1584         .onDidDisappear = std::move(onDidDisappear),
1585         .onWillAppear = std::move(onWillAppear),
1586         .onWillDisappear = std::move(onWillDisappear) };
1587     return promptDialogAttr;
1588 }
1589 
JSPromptShowDialog(napi_env env,napi_callback_info info)1590 napi_value JSPromptShowDialog(napi_env env, napi_callback_info info)
1591 {
1592     TAG_LOGD(AceLogTag::ACE_DIALOG, "js prompt show dialog enter");
1593     size_t requireArgc = 1;
1594     size_t argc = 2;
1595     napi_value argv[3] = { 0 };
1596     napi_value thisVar = nullptr;
1597     void* data = nullptr;
1598     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1599     if (argc < requireArgc) {
1600         NapiThrow(
1601             env, "The number of parameters must be greater than or equal to 1.", ERROR_CODE_PARAM_INVALID);
1602         return nullptr;
1603     }
1604     if (thisVar == nullptr) {
1605         return nullptr;
1606     }
1607     napi_valuetype valueTypeOfThis = napi_undefined;
1608     napi_typeof(env, thisVar, &valueTypeOfThis);
1609     if (valueTypeOfThis == napi_undefined) {
1610         return nullptr;
1611     }
1612 
1613     auto asyncContext = std::make_shared<PromptAsyncContext>();
1614     asyncContext->env = env;
1615     asyncContext->instanceId = Container::CurrentIdSafely();
1616 
1617     std::optional<DialogAlignment> alignment;
1618     std::optional<DimensionOffset> offset;
1619     std::optional<DimensionRect> maskRect;
1620     std::optional<Shadow> shadowProps;
1621     std::optional<Color> backgroundColor;
1622     std::optional<int32_t> backgroundBlurStyle;
1623     std::optional<BlurStyleOption> blurStyleOption;
1624     std::optional<EffectOption> effectOption;
1625     std::optional<HoverModeAreaType> hoverModeArea;
1626     std::optional<bool> enableHoverMode;
1627     LevelMode dialogLevelMode = LevelMode::OVERLAY;
1628     int32_t dialogLevelUniqueId = -1;
1629     ImmersiveMode dialogImmersiveMode = ImmersiveMode::DEFAULT;
1630     PromptDialogAttr lifeCycleAttr = {};
1631     for (size_t i = 0; i < argc; i++) {
1632         napi_valuetype valueType = napi_undefined;
1633         napi_typeof(env, argv[i], &valueType);
1634         if (i == 0) {
1635             if (valueType != napi_object) {
1636                 DeleteContextAndThrowError(env, asyncContext, "The type of parameters is incorrect.");
1637                 return nullptr;
1638             }
1639             napi_get_named_property(env, argv[0], "title", &asyncContext->titleNApi);
1640             napi_get_named_property(env, argv[0], "message", &asyncContext->messageNApi);
1641             napi_get_named_property(env, argv[0], "buttons", &asyncContext->buttonsNApi);
1642             napi_get_named_property(env, argv[0], "autoCancel", &asyncContext->autoCancel);
1643             napi_get_named_property(env, argv[0], "showInSubWindow", &asyncContext->showInSubWindow);
1644             napi_get_named_property(env, argv[0], "isModal", &asyncContext->isModal);
1645             napi_get_named_property(env, argv[0], "alignment", &asyncContext->alignmentApi);
1646             napi_get_named_property(env, argv[0], "offset", &asyncContext->offsetApi);
1647             napi_get_named_property(env, argv[0], "maskRect", &asyncContext->maskRectApi);
1648             napi_get_named_property(env, argv[0], "shadow", &asyncContext->shadowApi);
1649             napi_get_named_property(env, argv[0], "backgroundColor", &asyncContext->backgroundColorApi);
1650             napi_get_named_property(env, argv[0], "backgroundBlurStyle", &asyncContext->backgroundBlurStyleApi);
1651             napi_get_named_property(env, argv[0], "backgroundBlurStyleOptions", &asyncContext->blurStyleOptionApi);
1652             napi_get_named_property(env, argv[0], "backgroundEffect", &asyncContext->effectOptionApi);
1653             napi_get_named_property(env, argv[0], "enableHoverMode", &asyncContext->enableHoverMode);
1654             napi_get_named_property(env, argv[0], "hoverModeArea", &asyncContext->hoverModeAreaApi);
1655             napi_get_named_property(env, argv[0], "levelOrder", &asyncContext->levelOrderApi);
1656             napi_get_named_property(env, argv[0], "levelMode", &asyncContext->dialogLevelModeApi);
1657             napi_get_named_property(env, argv[0], "levelUniqueId", &asyncContext->dialogLevelUniqueId);
1658             napi_get_named_property(env, argv[0], "immersiveMode", &asyncContext->dialogImmersiveModeApi);
1659             napi_get_named_property(env, argv[0], "onDidAppear", &asyncContext->onDidAppear);
1660             napi_get_named_property(env, argv[0], "onDidDisappear", &asyncContext->onDidDisappear);
1661             napi_get_named_property(env, argv[0], "onWillAppear", &asyncContext->onWillAppear);
1662             napi_get_named_property(env, argv[0], "onWillDisappear", &asyncContext->onWillDisappear);
1663             GetNapiString(env, asyncContext->titleNApi, asyncContext->titleString, valueType);
1664             GetNapiString(env, asyncContext->messageNApi, asyncContext->messageString, valueType);
1665             GetNapiDialogProps(env, asyncContext, alignment, offset, maskRect);
1666             backgroundColor = GetColorProps(env, asyncContext->backgroundColorApi);
1667             shadowProps = GetShadowProps(env, asyncContext);
1668             GetNapiBlurStyleAndHoverModeProps(env, asyncContext, backgroundBlurStyle, hoverModeArea, enableHoverMode);
1669             GetBackgroundBlurStyleOption(env, asyncContext, blurStyleOption);
1670             GetBackgroundEffect(env, asyncContext, effectOption);
1671             if (!ParseButtonsPara(env, asyncContext, SHOW_DIALOG_BUTTON_NUM_MAX, false)) {
1672                 return nullptr;
1673             }
1674             napi_typeof(env, asyncContext->autoCancel, &valueType);
1675             if (valueType == napi_boolean) {
1676                 napi_get_value_bool(env, asyncContext->autoCancel, &asyncContext->autoCancelBool);
1677             }
1678             napi_typeof(env, asyncContext->showInSubWindow, &valueType);
1679             if (valueType == napi_boolean) {
1680                 napi_get_value_bool(env, asyncContext->showInSubWindow, &asyncContext->showInSubWindowBool);
1681             }
1682             napi_typeof(env, asyncContext->isModal, &valueType);
1683             if (valueType == napi_boolean) {
1684                 napi_get_value_bool(env, asyncContext->isModal, &asyncContext->isModalBool);
1685             }
1686             GetDialogLevelModeAndUniqueId(env, asyncContext, dialogLevelMode, dialogLevelUniqueId, dialogImmersiveMode);
1687             napi_typeof(env, asyncContext->onDidAppear, &valueType);
1688             if (valueType == napi_function) {
1689                 napi_create_reference(env, asyncContext->onDidAppear, 1, &asyncContext->onDidAppearRef);
1690             }
1691             napi_typeof(env, asyncContext->onDidDisappear, &valueType);
1692             if (valueType == napi_function) {
1693                 napi_create_reference(env, asyncContext->onDidDisappear, 1, &asyncContext->onDidDisappearRef);
1694             }
1695             napi_typeof(env, asyncContext->onWillAppear, &valueType);
1696             if (valueType == napi_function) {
1697                 napi_create_reference(env, asyncContext->onWillAppear, 1, &asyncContext->onWillAppearRef);
1698             }
1699             napi_typeof(env, asyncContext->onWillDisappear, &valueType);
1700             if (valueType == napi_function) {
1701                 napi_create_reference(env, asyncContext->onWillDisappear, 1, &asyncContext->onWillDisappearRef);
1702             }
1703             lifeCycleAttr = GetDialogLifeCycleCallback(env, asyncContext);
1704         } else if (valueType == napi_function) {
1705             napi_create_reference(env, argv[i], 1, &asyncContext->callbackRef);
1706         } else {
1707             DeleteContextAndThrowError(env, asyncContext, "The type of parameters is incorrect.");
1708             return nullptr;
1709         }
1710     }
1711     auto onLanguageChange = [shadowProps, alignment, offset, maskRect,
1712         updateAlignment = UpdatePromptAlignment](DialogProperties& dialogProps) {
1713         bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
1714         if (shadowProps.has_value()) {
1715             std::optional<Shadow> shadow = shadowProps.value();
1716             double offsetX = isRtl ? shadow->GetOffset().GetX() * (-1) : shadow->GetOffset().GetX();
1717             shadow->SetOffsetX(offsetX);
1718             dialogProps.shadow = shadow.value();
1719         }
1720         if (alignment.has_value()) {
1721             std::optional<DialogAlignment> pmAlign = alignment.value();
1722             updateAlignment(pmAlign.value());
1723             dialogProps.alignment = pmAlign.value();
1724         }
1725         if (offset.has_value()) {
1726             std::optional<DimensionOffset> pmOffset = offset.value();
1727             Dimension offsetX = isRtl ? pmOffset->GetX() * (-1) : pmOffset->GetX();
1728             pmOffset->SetX(offsetX);
1729             dialogProps.offset = pmOffset.value();
1730         }
1731         if (maskRect.has_value()) {
1732             std::optional<DimensionRect> pmMaskRect = maskRect.value();
1733             auto offset = pmMaskRect->GetOffset();
1734             Dimension offsetX = isRtl ? offset.GetX() * (-1) : offset.GetX();
1735             offset.SetX(offsetX);
1736             pmMaskRect->SetOffset(offset);
1737             dialogProps.maskRect = pmMaskRect.value();
1738         }
1739     };
1740     napi_value result = nullptr;
1741     if (asyncContext->callbackRef == nullptr) {
1742         napi_create_promise(env, &asyncContext->deferred, &result);
1743     } else {
1744         napi_get_undefined(env, &result);
1745     }
1746     asyncContext->callbacks.emplace("success");
1747     asyncContext->callbacks.emplace("cancel");
1748 
1749     auto callBack = [asyncContext](int32_t callbackType, int32_t successType) mutable {
1750         if (asyncContext == nullptr) {
1751             return;
1752         }
1753 
1754         asyncContext->callbackType = callbackType;
1755         asyncContext->successType = successType;
1756         auto container = AceEngine::Get().GetContainer(asyncContext->instanceId);
1757         if (!container) {
1758             return;
1759         }
1760 
1761         auto taskExecutor = container->GetTaskExecutor();
1762         if (!taskExecutor) {
1763             return;
1764         }
1765         taskExecutor->PostTask(
1766             [asyncContext]() {
1767                 if (asyncContext == nullptr) {
1768                     return;
1769                 }
1770 
1771                 if (!asyncContext->valid) {
1772                     return;
1773                 }
1774 
1775                 napi_handle_scope scope = nullptr;
1776                 napi_open_handle_scope(asyncContext->env, &scope);
1777                 if (scope == nullptr) {
1778                     return;
1779                 }
1780 
1781                 napi_value ret;
1782                 napi_value successIndex = nullptr;
1783                 napi_create_int32(asyncContext->env, asyncContext->successType, &successIndex);
1784                 napi_value indexObj = nullptr;
1785                 napi_create_object(asyncContext->env, &indexObj);
1786                 napi_set_named_property(asyncContext->env, indexObj, "index", successIndex);
1787                 napi_value result[2] = { 0 };
1788                 napi_create_object(asyncContext->env, &result[1]);
1789                 napi_set_named_property(asyncContext->env, result[1], "index", successIndex);
1790                 bool dialogResult = true;
1791                 switch (asyncContext->callbackType) {
1792                     case 0:
1793                         napi_get_undefined(asyncContext->env, &result[0]);
1794                         dialogResult = true;
1795                         break;
1796                     case 1:
1797                         napi_value message = nullptr;
1798                         napi_create_string_utf8(asyncContext->env, "cancel", strlen("cancel"), &message);
1799                         napi_create_error(asyncContext->env, nullptr, message, &result[0]);
1800                         dialogResult = false;
1801                         break;
1802                 }
1803                 if (asyncContext->deferred) {
1804                     if (dialogResult) {
1805                         napi_resolve_deferred(asyncContext->env, asyncContext->deferred, result[1]);
1806                     } else {
1807                         napi_reject_deferred(asyncContext->env, asyncContext->deferred, result[0]);
1808                     }
1809                 } else {
1810                     napi_value callback = nullptr;
1811                     napi_get_reference_value(asyncContext->env, asyncContext->callbackRef, &callback);
1812                     napi_call_function(
1813                         asyncContext->env, nullptr, callback, sizeof(result) / sizeof(result[0]), result, &ret);
1814                     napi_delete_reference(asyncContext->env, asyncContext->callbackRef);
1815                 }
1816                 napi_close_handle_scope(asyncContext->env, scope);
1817             },
1818             TaskExecutor::TaskType::JS, "ArkUIDialogParseDialogCallback");
1819         asyncContext = nullptr;
1820     };
1821 
1822     PromptDialogAttr promptDialogAttr = {
1823         .title = asyncContext->titleString,
1824         .message = asyncContext->messageString,
1825         .autoCancel = asyncContext->autoCancelBool,
1826         .showInSubWindow = asyncContext->showInSubWindowBool,
1827         .isModal = asyncContext->isModalBool,
1828         .enableHoverMode = enableHoverMode,
1829         .alignment = alignment,
1830         .offset = offset,
1831         .maskRect = maskRect,
1832         .backgroundColor = backgroundColor,
1833         .backgroundBlurStyle = backgroundBlurStyle,
1834         .blurStyleOption = blurStyleOption,
1835         .effectOption = effectOption,
1836         .shadow = shadowProps,
1837         .hoverModeArea = hoverModeArea,
1838         .onLanguageChange = onLanguageChange,
1839         .levelOrder = GetLevelOrderParam(asyncContext->env, asyncContext),
1840         .onDidAppear = lifeCycleAttr.onDidAppear,
1841         .onDidDisappear = lifeCycleAttr.onDidDisappear,
1842         .onWillAppear = lifeCycleAttr.onWillAppear,
1843         .onWillDisappear = lifeCycleAttr.onWillDisappear,
1844         .dialogLevelMode = dialogLevelMode,
1845         .dialogLevelUniqueId = dialogLevelUniqueId,
1846         .dialogImmersiveMode = dialogImmersiveMode,
1847     };
1848 
1849 #ifdef OHOS_STANDARD_SYSTEM
1850     // NG
1851     if (SystemProperties::GetExtSurfaceEnabled() || !ContainerIsService()) {
1852         auto delegate = EngineHelper::GetCurrentDelegateSafely();
1853         if (delegate) {
1854             delegate->ShowDialog(promptDialogAttr, asyncContext->buttons, std::move(callBack), asyncContext->callbacks);
1855         } else {
1856             // throw internal error
1857             napi_value code = nullptr;
1858             std::string strCode = std::to_string(ERROR_CODE_INTERNAL_ERROR);
1859             napi_create_string_utf8(env, strCode.c_str(), strCode.length(), &code);
1860             napi_value msg = nullptr;
1861             std::string strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "Can not get delegate.";
1862             napi_create_string_utf8(env, strMsg.c_str(), strMsg.length(), &msg);
1863             napi_value error = nullptr;
1864             napi_create_error(env, code, msg, &error);
1865 
1866             if (asyncContext->deferred) {
1867                 napi_reject_deferred(env, asyncContext->deferred, error);
1868             } else {
1869                 napi_value ret1;
1870                 napi_value callback = nullptr;
1871                 napi_get_reference_value(env, asyncContext->callbackRef, &callback);
1872                 napi_call_function(env, nullptr, callback, 1, &error, &ret1);
1873                 napi_delete_reference(env, asyncContext->callbackRef);
1874             }
1875         }
1876     } else if (SubwindowManager::GetInstance() != nullptr) {
1877         SubwindowManager::GetInstance()->ShowDialog(
1878             promptDialogAttr, asyncContext->buttons, std::move(callBack), asyncContext->callbacks);
1879     }
1880 #else
1881     auto delegate = EngineHelper::GetCurrentDelegateSafely();
1882     if (delegate) {
1883         delegate->ShowDialog(promptDialogAttr, asyncContext->buttons, std::move(callBack), asyncContext->callbacks);
1884     } else {
1885         // throw internal error
1886         napi_value code = nullptr;
1887         std::string strCode = std::to_string(ERROR_CODE_INTERNAL_ERROR);
1888         napi_create_string_utf8(env, strCode.c_str(), strCode.length(), &code);
1889         napi_value msg = nullptr;
1890         std::string strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "UI execution context not found.";
1891         napi_create_string_utf8(env, strMsg.c_str(), strMsg.length(), &msg);
1892         napi_value error = nullptr;
1893         napi_create_error(env, code, msg, &error);
1894 
1895         if (asyncContext->deferred) {
1896             napi_reject_deferred(env, asyncContext->deferred, error);
1897         } else {
1898             napi_value ret1;
1899             napi_value callback = nullptr;
1900             napi_get_reference_value(env, asyncContext->callbackRef, &callback);
1901             napi_call_function(env, nullptr, callback, 1, &error, &ret1);
1902             napi_delete_reference(env, asyncContext->callbackRef);
1903         }
1904     }
1905 #endif
1906     return result;
1907 }
1908 
CreateActionMenuLifeCycleCallback(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)1909 void CreateActionMenuLifeCycleCallback(napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
1910 {
1911     napi_valuetype valueType = napi_undefined;
1912     napi_typeof(env, asyncContext->onDidAppear, &valueType);
1913     if (valueType == napi_function) {
1914         napi_create_reference(env, asyncContext->onDidAppear, 1, &asyncContext->onDidAppearRef);
1915     }
1916     napi_typeof(env, asyncContext->onDidDisappear, &valueType);
1917     if (valueType == napi_function) {
1918         napi_create_reference(env, asyncContext->onDidDisappear, 1, &asyncContext->onDidDisappearRef);
1919     }
1920     napi_typeof(env, asyncContext->onWillAppear, &valueType);
1921     if (valueType == napi_function) {
1922         napi_create_reference(env, asyncContext->onWillAppear, 1, &asyncContext->onWillAppearRef);
1923     }
1924     napi_typeof(env, asyncContext->onWillDisappear, &valueType);
1925     if (valueType == napi_function) {
1926         napi_create_reference(env, asyncContext->onWillDisappear, 1, &asyncContext->onWillDisappearRef);
1927     }
1928 }
1929 
GetActionMenuAppearLifeCycleCallback(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext,PromptDialogAttr & promptDialogAttr)1930 void GetActionMenuAppearLifeCycleCallback(napi_env env,
1931     const std::shared_ptr<PromptAsyncContext>& asyncContext, PromptDialogAttr& promptDialogAttr)
1932 {
1933     auto onDidAppear = [env = asyncContext->env, onDidAppearRef = asyncContext->onDidAppearRef]() {
1934         if (onDidAppearRef) {
1935             napi_handle_scope scope = nullptr;
1936             napi_open_handle_scope(env, &scope);
1937             napi_value onDidAppearFunc = nullptr;
1938             napi_get_reference_value(env, onDidAppearRef, &onDidAppearFunc);
1939             napi_call_function(env, nullptr, onDidAppearFunc, 0, nullptr, nullptr);
1940             napi_delete_reference(env, onDidAppearRef);
1941             napi_close_handle_scope(env, scope);
1942         }
1943     };
1944     auto onWillAppear = [env = asyncContext->env, onWillAppearRef = asyncContext->onWillAppearRef]() {
1945         if (onWillAppearRef) {
1946             napi_handle_scope scope = nullptr;
1947             napi_open_handle_scope(env, &scope);
1948             napi_value onWillAppearFunc = nullptr;
1949             napi_get_reference_value(env, onWillAppearRef, &onWillAppearFunc);
1950             napi_call_function(env, nullptr, onWillAppearFunc, 0, nullptr, nullptr);
1951             napi_delete_reference(env, onWillAppearRef);
1952             napi_close_handle_scope(env, scope);
1953         }
1954     };
1955     promptDialogAttr.onDidAppear = std::move(onDidAppear);
1956     promptDialogAttr.onWillAppear = std::move(onWillAppear);
1957 }
1958 
GetActionMenuDisappearLifeCycleCallback(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext,PromptDialogAttr & promptDialogAttr)1959 void GetActionMenuDisappearLifeCycleCallback(napi_env env,
1960     const std::shared_ptr<PromptAsyncContext>& asyncContext, PromptDialogAttr& promptDialogAttr)
1961 {
1962     auto onDidDisappear = [env = asyncContext->env, onDidDisappearRef = asyncContext->onDidDisappearRef]() {
1963         if (onDidDisappearRef) {
1964             napi_handle_scope scope = nullptr;
1965             napi_open_handle_scope(env, &scope);
1966             napi_value onDidDisappearFunc = nullptr;
1967             napi_get_reference_value(env, onDidDisappearRef, &onDidDisappearFunc);
1968             napi_call_function(env, nullptr, onDidDisappearFunc, 0, nullptr, nullptr);
1969             napi_delete_reference(env, onDidDisappearRef);
1970             napi_close_handle_scope(env, scope);
1971         }
1972     };
1973     auto onWillDisappear = [env = asyncContext->env, onWillDisappearRef = asyncContext->onWillDisappearRef]() {
1974         if (onWillDisappearRef) {
1975             napi_handle_scope scope = nullptr;
1976             napi_open_handle_scope(env, &scope);
1977             napi_value onWillDisappearFunc = nullptr;
1978             napi_get_reference_value(env, onWillDisappearRef, &onWillDisappearFunc);
1979             napi_call_function(env, nullptr, onWillDisappearFunc, 0, nullptr, nullptr);
1980             napi_delete_reference(env, onWillDisappearRef);
1981             napi_close_handle_scope(env, scope);
1982         }
1983     };
1984     promptDialogAttr.onDidDisappear = std::move(onDidDisappear);
1985     promptDialogAttr.onWillDisappear = std::move(onWillDisappear);
1986 }
1987 
JSPromptShowActionMenu(napi_env env,napi_callback_info info)1988 napi_value JSPromptShowActionMenu(napi_env env, napi_callback_info info)
1989 {
1990     TAG_LOGD(AceLogTag::ACE_DIALOG, "js prompt show action menu enter");
1991     size_t requireArgc = 1;
1992     size_t argc = 2;
1993     napi_value argv[3] = { 0 };
1994     napi_value thisVar = nullptr;
1995     void* data = nullptr;
1996     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1997     if (argc < requireArgc) {
1998         NapiThrow(
1999             env, "The number of parameters must be greater than or equal to 1.", ERROR_CODE_PARAM_INVALID);
2000         return nullptr;
2001     }
2002     if (thisVar == nullptr) {
2003         return nullptr;
2004     }
2005     napi_valuetype valueTypeOfThis = napi_undefined;
2006     napi_typeof(env, thisVar, &valueTypeOfThis);
2007     if (valueTypeOfThis == napi_undefined) {
2008         return nullptr;
2009     }
2010 
2011     auto asyncContext = std::make_shared<PromptAsyncContext>();
2012     asyncContext->env = env;
2013     asyncContext->instanceId = Container::CurrentIdSafely();
2014     LevelMode dialogLevelMode = LevelMode::OVERLAY;
2015     int32_t dialogLevelUniqueId = -1;
2016     ImmersiveMode dialogImmersiveMode = ImmersiveMode::DEFAULT;
2017 
2018     PromptDialogAttr lifeCycleAttr;
2019     for (size_t i = 0; i < argc; i++) {
2020         napi_valuetype valueType = napi_undefined;
2021         napi_typeof(env, argv[i], &valueType);
2022         if (i == 0) {
2023             if (valueType != napi_object) {
2024                 DeleteContextAndThrowError(env, asyncContext, "The type of parameters is incorrect.");
2025                 return nullptr;
2026             }
2027 
2028             napi_get_named_property(env, argv[0], "onDidAppear", &asyncContext->onDidAppear);
2029             napi_get_named_property(env, argv[0], "onDidDisappear", &asyncContext->onDidDisappear);
2030             napi_get_named_property(env, argv[0], "onWillAppear", &asyncContext->onWillAppear);
2031             napi_get_named_property(env, argv[0], "onWillDisappear", &asyncContext->onWillDisappear);
2032             CreateActionMenuLifeCycleCallback(env, asyncContext);
2033             GetActionMenuAppearLifeCycleCallback(env, asyncContext, lifeCycleAttr);
2034             GetActionMenuDisappearLifeCycleCallback(env, asyncContext, lifeCycleAttr);
2035             napi_get_named_property(env, argv[0], "title", &asyncContext->titleNApi);
2036             napi_get_named_property(env, argv[0], "showInSubWindow", &asyncContext->showInSubWindow);
2037             napi_get_named_property(env, argv[0], "isModal", &asyncContext->isModal);
2038             napi_get_named_property(env, argv[0], "levelMode", &asyncContext->dialogLevelModeApi);
2039             napi_get_named_property(env, argv[0], "levelUniqueId", &asyncContext->dialogLevelUniqueId);
2040             napi_get_named_property(env, argv[0], "immersiveMode", &asyncContext->dialogImmersiveModeApi);
2041             GetNapiString(env, asyncContext->titleNApi, asyncContext->titleString, valueType);
2042             if (!HasProperty(env, argv[0], "buttons")) {
2043                 DeleteContextAndThrowError(env, asyncContext, "Required input parameters are missing.");
2044                 return nullptr;
2045             }
2046             napi_get_named_property(env, argv[0], "buttons", &asyncContext->buttonsNApi);
2047             if (!ParseButtonsPara(env, asyncContext, SHOW_ACTION_MENU_BUTTON_NUM_MAX, true)) {
2048                 return nullptr;
2049             }
2050             napi_typeof(env, asyncContext->showInSubWindow, &valueType);
2051             if (valueType == napi_boolean) {
2052                 napi_get_value_bool(env, asyncContext->showInSubWindow, &asyncContext->showInSubWindowBool);
2053             }
2054             napi_typeof(env, asyncContext->isModal, &valueType);
2055             if (valueType == napi_boolean) {
2056                 napi_get_value_bool(env, asyncContext->isModal, &asyncContext->isModalBool);
2057             }
2058             GetDialogLevelModeAndUniqueId(env, asyncContext, dialogLevelMode, dialogLevelUniqueId, dialogImmersiveMode);
2059         } else if (valueType == napi_function) {
2060             napi_create_reference(env, argv[i], 1, &asyncContext->callbackRef);
2061         } else {
2062             DeleteContextAndThrowError(env, asyncContext, "The type of parameters is incorrect.");
2063             return nullptr;
2064         }
2065     }
2066     napi_value result = nullptr;
2067     if (asyncContext->callbackRef == nullptr) {
2068         napi_create_promise(env, &asyncContext->deferred, &result);
2069     } else {
2070         napi_get_undefined(env, &result);
2071     }
2072 
2073     auto callBack = [asyncContext](int32_t callbackType, int32_t successType) mutable {
2074         if (asyncContext == nullptr) {
2075             return;
2076         }
2077 
2078         asyncContext->callbackType = callbackType;
2079         asyncContext->successType = successType;
2080         auto container = AceEngine::Get().GetContainer(asyncContext->instanceId);
2081         if (!container) {
2082             return;
2083         }
2084 
2085         auto taskExecutor = container->GetTaskExecutor();
2086         if (!taskExecutor) {
2087             return;
2088         }
2089         taskExecutor->PostTask(
2090             [asyncContext]() {
2091                 if (asyncContext == nullptr) {
2092                     return;
2093                 }
2094 
2095                 if (!asyncContext->valid) {
2096                     return;
2097                 }
2098 
2099                 napi_handle_scope scope = nullptr;
2100                 napi_open_handle_scope(asyncContext->env, &scope);
2101                 if (scope == nullptr) {
2102                     return;
2103                 }
2104 
2105                 napi_value ret;
2106                 napi_value successIndex = nullptr;
2107                 napi_create_int32(asyncContext->env, asyncContext->successType, &successIndex);
2108                 asyncContext->callbackSuccessString = "showActionMenu:ok";
2109                 napi_value indexObj = GetReturnObject(asyncContext->env, asyncContext->callbackSuccessString);
2110                 napi_set_named_property(asyncContext->env, indexObj, "index", successIndex);
2111                 napi_value result[2] = { 0 };
2112                 napi_create_object(asyncContext->env, &result[1]);
2113                 napi_set_named_property(asyncContext->env, result[1], "index", successIndex);
2114                 bool dialogResult = true;
2115                 switch (asyncContext->callbackType) {
2116                     case 0:
2117                         napi_get_undefined(asyncContext->env, &result[0]);
2118                         dialogResult = true;
2119                         break;
2120                     case 1:
2121                         napi_value message = nullptr;
2122                         napi_create_string_utf8(asyncContext->env, "cancel", strlen("cancel"), &message);
2123                         napi_create_error(asyncContext->env, nullptr, message, &result[0]);
2124                         dialogResult = false;
2125                         break;
2126                 }
2127                 if (asyncContext->deferred) {
2128                     if (dialogResult) {
2129                         napi_resolve_deferred(asyncContext->env, asyncContext->deferred, result[1]);
2130                     } else {
2131                         napi_reject_deferred(asyncContext->env, asyncContext->deferred, result[0]);
2132                     }
2133                 } else {
2134                     napi_value callback = nullptr;
2135                     napi_get_reference_value(asyncContext->env, asyncContext->callbackRef, &callback);
2136                     napi_call_function(
2137                         asyncContext->env, nullptr, callback, sizeof(result) / sizeof(result[0]), result, &ret);
2138                     napi_delete_reference(asyncContext->env, asyncContext->callbackRef);
2139                 }
2140                 napi_close_handle_scope(asyncContext->env, scope);
2141             },
2142             TaskExecutor::TaskType::JS, "ArkUIDialogParseActionMenuCallback");
2143         asyncContext = nullptr;
2144     };
2145 
2146     DimensionRect rect;
2147     rect.SetOffset(DimensionOffset(CalcDimension(0, DimensionUnit::VP), CalcDimension(0, DimensionUnit::VP)));
2148     rect.SetSize(DimensionSize(CalcDimension(1, DimensionUnit::PERCENT), CalcDimension(1, DimensionUnit::PERCENT)));
2149 
2150     PromptDialogAttr promptDialogAttr = {
2151         .title = asyncContext->titleString,
2152         .showInSubWindow = asyncContext->showInSubWindowBool,
2153         .isModal = asyncContext->isModalBool,
2154         .maskRect = rect,
2155         .onDidAppear = std::move(lifeCycleAttr.onDidAppear),
2156         .onDidDisappear = std::move(lifeCycleAttr.onDidDisappear),
2157         .onWillAppear = std::move(lifeCycleAttr.onWillAppear),
2158         .onWillDisappear = std::move(lifeCycleAttr.onWillDisappear),
2159         .dialogLevelMode = dialogLevelMode,
2160         .dialogLevelUniqueId = dialogLevelUniqueId,
2161         .dialogImmersiveMode = dialogImmersiveMode,
2162     };
2163 #ifdef OHOS_STANDARD_SYSTEM
2164     if (SystemProperties::GetExtSurfaceEnabled() || !ContainerIsService()) {
2165         auto delegate = EngineHelper::GetCurrentDelegateSafely();
2166         if (delegate) {
2167             delegate->ShowActionMenu(promptDialogAttr, asyncContext->buttons, std::move(callBack));
2168         } else {
2169             napi_value code = nullptr;
2170             std::string strCode = std::to_string(ERROR_CODE_INTERNAL_ERROR);
2171             napi_create_string_utf8(env, strCode.c_str(), strCode.length(), &code);
2172             napi_value msg = nullptr;
2173             std::string strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "Can not get delegate.";
2174             napi_create_string_utf8(env, strMsg.c_str(), strMsg.length(), &msg);
2175             napi_value error = nullptr;
2176             napi_create_error(env, code, msg, &error);
2177 
2178             if (asyncContext->deferred) {
2179                 napi_reject_deferred(env, asyncContext->deferred, error);
2180             } else {
2181                 napi_value ret1;
2182                 napi_value callback = nullptr;
2183                 napi_get_reference_value(env, asyncContext->callbackRef, &callback);
2184                 napi_call_function(env, nullptr, callback, 1, &error, &ret1);
2185                 napi_delete_reference(env, asyncContext->callbackRef);
2186             }
2187         }
2188     } else if (SubwindowManager::GetInstance() != nullptr) {
2189         SubwindowManager::GetInstance()->ShowActionMenu(
2190             asyncContext->titleString, asyncContext->buttons, std::move(callBack));
2191     }
2192 #else
2193     auto delegate = EngineHelper::GetCurrentDelegateSafely();
2194     if (delegate) {
2195         delegate->ShowActionMenu(promptDialogAttr, asyncContext->buttons, std::move(callBack));
2196     } else {
2197         napi_value code = nullptr;
2198         std::string strCode = std::to_string(ERROR_CODE_INTERNAL_ERROR);
2199         napi_create_string_utf8(env, strCode.c_str(), strCode.length(), &code);
2200         napi_value msg = nullptr;
2201         std::string strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "UI execution context not found.";
2202         napi_create_string_utf8(env, strMsg.c_str(), strMsg.length(), &msg);
2203         napi_value error = nullptr;
2204         napi_create_error(env, code, msg, &error);
2205 
2206         if (asyncContext->deferred) {
2207             napi_reject_deferred(env, asyncContext->deferred, error);
2208         } else {
2209             napi_value ret1;
2210             napi_value callback = nullptr;
2211             napi_get_reference_value(env, asyncContext->callbackRef, &callback);
2212             napi_call_function(env, nullptr, callback, 1, &error, &ret1);
2213             napi_delete_reference(env, asyncContext->callbackRef);
2214         }
2215     }
2216 #endif
2217     return result;
2218 }
2219 
JSRemoveCustomDialog(napi_env env,napi_callback_info info)2220 napi_value JSRemoveCustomDialog(napi_env env, napi_callback_info info)
2221 {
2222     size_t argc = 1;
2223     napi_value argv = nullptr;
2224     napi_value thisVar = nullptr;
2225     void* data = nullptr;
2226     napi_get_cb_info(env, info, &argc, &argv, &thisVar, &data);
2227     int32_t instanceId = Container::CurrentIdSafely();
2228     if (data) {
2229         int32_t* instanceIdPtr = reinterpret_cast<int32_t*>(data);
2230         instanceId = *instanceIdPtr;
2231     }
2232     auto delegate = EngineHelper::GetCurrentDelegateSafely();
2233     if (delegate) {
2234         delegate->RemoveCustomDialog(instanceId);
2235     }
2236     return nullptr;
2237 }
2238 
ParseDialogReleaseCallback(std::shared_ptr<PromptAsyncContext> & asyncContext,std::function<void ()> & onWillDismissRelease)2239 void ParseDialogReleaseCallback(std::shared_ptr<PromptAsyncContext>& asyncContext,
2240     std::function<void()>& onWillDismissRelease)
2241 {
2242     onWillDismissRelease = [env = asyncContext->env, onWillDismissRef = asyncContext->onWillDismissRef]() {
2243         if (onWillDismissRef) {
2244             napi_handle_scope scope = nullptr;
2245             napi_open_handle_scope(env, &scope);
2246             napi_delete_reference(env, onWillDismissRef);
2247             napi_close_handle_scope(env, scope);
2248         }
2249     };
2250 }
2251 
ParseDialogCallback(std::shared_ptr<PromptAsyncContext> & asyncContext,std::function<void (const int32_t & info,const int32_t & instanceId)> & onWillDismiss)2252 void ParseDialogCallback(std::shared_ptr<PromptAsyncContext>& asyncContext,
2253     std::function<void(const int32_t& info, const int32_t& instanceId)>& onWillDismiss)
2254 {
2255     onWillDismiss = [env = asyncContext->env, onWillDismissRef = asyncContext->onWillDismissRef]
2256         (const int32_t& info, const int32_t& instanceId) {
2257         if (onWillDismissRef) {
2258             napi_handle_scope scope = nullptr;
2259             napi_open_handle_scope(env, &scope);
2260             napi_value onWillDismissFunc = nullptr;
2261             napi_value value = nullptr;
2262             napi_value funcValue = nullptr;
2263             napi_value paramObj = nullptr;
2264             napi_create_object(env, &paramObj);
2265 
2266             int32_t* id = new int32_t(instanceId);
2267             napi_create_function(env, "dismiss", strlen("dismiss"), JSRemoveCustomDialog, id, &funcValue);
2268             napi_set_named_property(env, paramObj, "dismiss", funcValue);
2269             napi_status status = napi_add_finalizer(
2270                 env, funcValue, id,
2271                 [](napi_env env, void* data, void* hint) {
2272                     int32_t* id = reinterpret_cast<int32_t*>(data);
2273                     CHECK_NULL_VOID(id);
2274                     delete id;
2275                 },
2276                 nullptr, nullptr);
2277             if (status != napi_ok) {
2278                 delete id;
2279                 LOGE("Fail to add the finalizer method for instanceId.");
2280                 napi_close_handle_scope(env, scope);
2281                 return;
2282             }
2283             napi_create_int32(env, info, &value);
2284             napi_set_named_property(env, paramObj, "reason", value);
2285             napi_get_reference_value(env, onWillDismissRef, &onWillDismissFunc);
2286             napi_call_function(env, nullptr, onWillDismissFunc, 1, &paramObj, nullptr);
2287             napi_close_handle_scope(env, scope);
2288         }
2289     };
2290 }
2291 
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)2292 void ParseBorderColorAndStyle(napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext,
2293     std::optional<NG::BorderWidthProperty>& borderWidthProps, std::optional<NG::BorderColorProperty>& borderColorProps,
2294     std::optional<NG::BorderStyleProperty>& borderStyleProps)
2295 {
2296     if (borderWidthProps.has_value()) {
2297         borderColorProps = GetBorderColorProps(env, asyncContext);
2298         if (!borderColorProps.has_value()) {
2299             NG::BorderColorProperty borderColor;
2300             borderColor.SetColor(Color::BLACK);
2301             borderColorProps = borderColor;
2302         }
2303         borderStyleProps = GetBorderStyleProps(env, asyncContext);
2304         if (!borderStyleProps.has_value()) {
2305             borderStyleProps = NG::BorderStyleProperty(
2306                 { BorderStyle::SOLID, BorderStyle::SOLID, BorderStyle::SOLID, BorderStyle::SOLID });
2307         }
2308     }
2309 }
2310 
GetTransitionProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)2311 RefPtr<NG::ChainedTransitionEffect> GetTransitionProps(
2312     napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
2313 {
2314     RefPtr<NG::ChainedTransitionEffect> transitionEffect = nullptr;
2315     auto delegate = EngineHelper::GetCurrentDelegateSafely();
2316     if (delegate) {
2317         napi_valuetype valueType = napi_undefined;
2318         napi_typeof(env, asyncContext->transitionApi, &valueType);
2319         if (valueType == napi_object) {
2320             transitionEffect = delegate->GetTransitionEffect(asyncContext->transitionApi);
2321         }
2322     }
2323     return transitionEffect;
2324 }
2325 
GetDialogTransitionProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)2326 RefPtr<NG::ChainedTransitionEffect> GetDialogTransitionProps(
2327     napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
2328 {
2329     RefPtr<NG::ChainedTransitionEffect> dialogTransitionEffect = nullptr;
2330     auto delegate = EngineHelper::GetCurrentDelegateSafely();
2331     if (delegate) {
2332         napi_valuetype valueType = napi_undefined;
2333         napi_typeof(env, asyncContext->dialogTransitionApi, &valueType);
2334         if (valueType == napi_object) {
2335             dialogTransitionEffect = delegate->GetTransitionEffect(asyncContext->dialogTransitionApi);
2336         }
2337     }
2338     return dialogTransitionEffect;
2339 }
2340 
GetMaskTransitionProps(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)2341 RefPtr<NG::ChainedTransitionEffect> GetMaskTransitionProps(
2342     napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
2343 {
2344     RefPtr<NG::ChainedTransitionEffect> maskTransitionEffect = nullptr;
2345     auto delegate = EngineHelper::GetCurrentDelegateSafely();
2346     if (delegate) {
2347         napi_valuetype valueType = napi_undefined;
2348         napi_typeof(env, asyncContext->maskTransitionApi, &valueType);
2349         if (valueType == napi_object) {
2350             maskTransitionEffect = delegate->GetTransitionEffect(asyncContext->maskTransitionApi);
2351         }
2352     }
2353     return maskTransitionEffect;
2354 }
2355 
GetCustomBuilder(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)2356 std::function<void()> GetCustomBuilder(napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
2357 {
2358     auto builder = [env = asyncContext->env, builderRef = asyncContext->builderRef]() {
2359         if (builderRef) {
2360             napi_value builderFunc = nullptr;
2361             napi_get_reference_value(env, builderRef, &builderFunc);
2362             napi_call_function(env, nullptr, builderFunc, 0, nullptr, nullptr);
2363             napi_delete_reference(env, builderRef);
2364         }
2365     };
2366     return builder;
2367 }
2368 
GetCustomBuilderWithId(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)2369 std::function<void(const int32_t& dialogId)> GetCustomBuilderWithId(
2370     napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
2371 {
2372     auto builder = [env = asyncContext->env, builderRef = asyncContext->builderRef](const int32_t dialogId) {
2373         if (builderRef) {
2374             napi_value builderFunc = nullptr;
2375             napi_get_reference_value(env, builderRef, &builderFunc);
2376             napi_value dialogIdArg = nullptr;
2377             napi_create_int32(env, dialogId, &dialogIdArg);
2378             napi_call_function(env, nullptr, builderFunc, 1, &dialogIdArg, nullptr);
2379             napi_delete_reference(env, builderRef);
2380         }
2381     };
2382     return builder;
2383 }
2384 
GetFocusableParam(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext)2385 bool GetFocusableParam(napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext)
2386 {
2387     bool focusable = true;
2388     napi_valuetype valueType = napi_undefined;
2389     napi_typeof(env, asyncContext->focusableApi, &valueType);
2390     if (valueType != napi_boolean) {
2391         return focusable;
2392     }
2393 
2394     napi_get_value_bool(env, asyncContext->focusableApi, &focusable);
2395     return focusable;
2396 }
2397 
GetPromptActionDialog(napi_env env,const std::shared_ptr<PromptAsyncContext> & asyncContext,std::function<void (const int32_t & info,const int32_t & instanceId)> onWillDismiss)2398 PromptDialogAttr GetPromptActionDialog(napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext,
2399     std::function<void(const int32_t& info, const int32_t& instanceId)> onWillDismiss)
2400 {
2401     std::optional<DialogAlignment> alignment;
2402     std::optional<DimensionOffset> offset;
2403     std::optional<DimensionRect> maskRect;
2404     std::optional<int32_t> backgroundBlurStyle;
2405     std::optional<HoverModeAreaType> hoverModeArea;
2406     std::optional<BlurStyleOption> blurStyleOption;
2407     std::optional<EffectOption> effectOption;
2408     std::optional<bool> enableHoverMode;
2409     GetNapiDialogProps(env, asyncContext, alignment, offset, maskRect);
2410     GetNapiBlurStyleAndHoverModeProps(env, asyncContext, backgroundBlurStyle, hoverModeArea, enableHoverMode);
2411     GetBackgroundBlurStyleOption(env, asyncContext, blurStyleOption);
2412     GetBackgroundEffect(env, asyncContext, effectOption);
2413     auto borderWidthProps = GetBorderWidthProps(env, asyncContext);
2414     std::optional<NG::BorderColorProperty> borderColorProps;
2415     std::optional<NG::BorderStyleProperty> borderStyleProps;
2416     ParseBorderColorAndStyle(env, asyncContext, borderWidthProps, borderColorProps, borderStyleProps);
2417     auto backgroundColorProps = GetColorProps(env, asyncContext->backgroundColorApi);
2418     auto builder = GetCustomBuilder(env, asyncContext);
2419     auto* nodePtr = reinterpret_cast<OHOS::Ace::NG::UINode*>(asyncContext->nativePtr);
2420     auto maskColorProps = GetColorProps(env, asyncContext->maskColorApi);
2421     auto transitionEffectProps = GetTransitionProps(env, asyncContext);
2422     auto dialogTransitionEffectProps = GetDialogTransitionProps(env, asyncContext);
2423     auto maskTransitionEffectProps = GetMaskTransitionProps(env, asyncContext);
2424     PromptDialogAttr lifeCycleAttr = GetDialogLifeCycleCallback(env, asyncContext);
2425     int32_t mode = GetDialogKeyboardAvoidMode(env, asyncContext->keyboardAvoidModeApi);
2426     LevelMode dialogLevelMode = LevelMode::OVERLAY;
2427     int32_t dialogLevelUniqueId = -1;
2428     ImmersiveMode dialogImmersiveMode = ImmersiveMode::DEFAULT;
2429     GetDialogLevelModeAndUniqueId(env, asyncContext, dialogLevelMode, dialogLevelUniqueId, dialogImmersiveMode);
2430     PromptDialogAttr promptDialogAttr = { .autoCancel = asyncContext->autoCancelBool,
2431         .showInSubWindow = asyncContext->showInSubWindowBool,
2432         .isModal = asyncContext->isModalBool,
2433         .enableHoverMode = enableHoverMode,
2434         .customBuilder = std::move(builder),
2435         .customOnWillDismiss = std::move(onWillDismiss),
2436         .alignment = alignment,
2437         .offset = offset,
2438         .maskRect = maskRect,
2439         .backgroundColor = backgroundColorProps,
2440         .backgroundBlurStyle = backgroundBlurStyle,
2441         .blurStyleOption = blurStyleOption,
2442         .effectOption = effectOption,
2443         .borderWidth = borderWidthProps,
2444         .borderColor = borderColorProps,
2445         .borderStyle = borderStyleProps,
2446         .borderRadius = GetBorderRadiusProps(env, asyncContext),
2447         .shadow = GetShadowProps(env, asyncContext),
2448         .width = GetNapiDialogWidthProps(env, asyncContext),
2449         .height = GetNapiDialogHeightProps(env, asyncContext),
2450         .hoverModeArea = hoverModeArea,
2451         .contentNode = AceType::WeakClaim(nodePtr),
2452         .maskColor = maskColorProps,
2453         .transitionEffect = transitionEffectProps,
2454         .dialogTransitionEffect = dialogTransitionEffectProps,
2455         .maskTransitionEffect = maskTransitionEffectProps,
2456         .onDidAppear = lifeCycleAttr.onDidAppear,
2457         .onDidDisappear = lifeCycleAttr.onDidDisappear,
2458         .onWillAppear = lifeCycleAttr.onWillAppear,
2459         .onWillDisappear = lifeCycleAttr.onWillDisappear,
2460         .keyboardAvoidMode = KEYBOARD_AVOID_MODE[mode],
2461         .keyboardAvoidDistance = GetKeyboardAvoidDistanceProps(env, asyncContext),
2462         .levelOrder = GetLevelOrderParam(env, asyncContext),
2463         .focusable = GetFocusableParam(env, asyncContext),
2464         .dialogLevelMode = dialogLevelMode,
2465         .dialogLevelUniqueId = dialogLevelUniqueId,
2466         .dialogImmersiveMode = dialogImmersiveMode,
2467     };
2468     return promptDialogAttr;
2469 }
2470 
GetErrorMsg(int32_t errorCode)2471 std::string GetErrorMsg(int32_t errorCode)
2472 {
2473     std::string strMsg;
2474     if (errorCode == ERROR_CODE_DIALOG_CONTENT_ERROR) {
2475         strMsg = ErrorToMessage(ERROR_CODE_DIALOG_CONTENT_ERROR) + "The ComponentContent is incorrect.";
2476     } else if (errorCode == ERROR_CODE_DIALOG_CONTENT_ALREADY_EXIST) {
2477         strMsg = ErrorToMessage(ERROR_CODE_DIALOG_CONTENT_ALREADY_EXIST) +
2478             "The ComponentContent has already been opened.";
2479     } else if (errorCode == ERROR_CODE_DIALOG_CONTENT_NOT_FOUND) {
2480         strMsg = ErrorToMessage(ERROR_CODE_DIALOG_CONTENT_NOT_FOUND) + "The ComponentContent cannot be found.";
2481     } else {
2482         strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "Build custom dialog failed.";
2483     }
2484     return strMsg;
2485 }
2486 
GetErrorCode(int32_t errorCode)2487 std::string GetErrorCode(int32_t errorCode)
2488 {
2489     std::string strCode;
2490     if (errorCode == ERROR_CODE_DIALOG_CONTENT_ERROR) {
2491         strCode = std::to_string(ERROR_CODE_DIALOG_CONTENT_ERROR);
2492     } else if (errorCode == ERROR_CODE_DIALOG_CONTENT_ALREADY_EXIST) {
2493         strCode = std::to_string(ERROR_CODE_DIALOG_CONTENT_ALREADY_EXIST);
2494     } else if (errorCode == ERROR_CODE_DIALOG_CONTENT_NOT_FOUND) {
2495         strCode = std::to_string(ERROR_CODE_DIALOG_CONTENT_NOT_FOUND);
2496     } else {
2497         strCode = std::to_string(ERROR_CODE_INTERNAL_ERROR);
2498     }
2499     return strCode;
2500 }
2501 
ParseCustomDialogContentCallback(std::shared_ptr<PromptAsyncContext> & asyncContext,std::function<void (int32_t)> & callBack)2502 void ParseCustomDialogContentCallback(std::shared_ptr<PromptAsyncContext>& asyncContext,
2503     std::function<void(int32_t)>& callBack)
2504 {
2505     callBack = [asyncContext](int32_t errorCode) mutable {
2506         if (!asyncContext) {
2507             return;
2508         }
2509         auto container = AceEngine::Get().GetContainer(asyncContext->instanceId);
2510         if (!container) {
2511             return;
2512         }
2513         auto taskExecutor = container->GetTaskExecutor();
2514         if (!taskExecutor) {
2515             return;
2516         }
2517         taskExecutor->PostTask(
2518             [asyncContext, errorCode]() {
2519                 if (asyncContext == nullptr || !asyncContext->valid) {
2520                     return;
2521                 }
2522                 napi_handle_scope scope = nullptr;
2523                 napi_open_handle_scope(asyncContext->env, &scope);
2524                 if (scope == nullptr) {
2525                     return;
2526                 }
2527                 if (!asyncContext->deferred) {
2528                     return;
2529                 }
2530                 if (errorCode == ERROR_CODE_NO_ERROR) {
2531                     napi_value result = nullptr;
2532                     napi_get_undefined(asyncContext->env, &result);
2533                     napi_resolve_deferred(asyncContext->env, asyncContext->deferred, result);
2534                 } else {
2535                     std::string strMsg = GetErrorMsg(errorCode);
2536                     std::string strCode = GetErrorCode(errorCode);
2537                     napi_value code = nullptr;
2538                     napi_create_string_utf8(asyncContext->env, strCode.c_str(), strCode.length(), &code);
2539                     napi_value msg = nullptr;
2540                     napi_create_string_utf8(asyncContext->env, strMsg.c_str(), strMsg.length(), &msg);
2541                     napi_value error = nullptr;
2542                     napi_create_error(asyncContext->env, code, msg, &error);
2543                     napi_reject_deferred(asyncContext->env, asyncContext->deferred, error);
2544                 }
2545                 napi_close_handle_scope(asyncContext->env, scope);
2546             },
2547             TaskExecutor::TaskType::JS, "ArkUIDialogParseCustomDialogContentCallback");
2548         asyncContext = nullptr;
2549     };
2550 }
2551 
ParseCustomDialogIdCallback(std::shared_ptr<PromptAsyncContext> & asyncContext,std::function<void (int32_t)> & callBack)2552 void ParseCustomDialogIdCallback(std::shared_ptr<PromptAsyncContext>& asyncContext,
2553     std::function<void(int32_t)>& callBack)
2554 {
2555     callBack = [asyncContext](int32_t dialogId) mutable {
2556         if (!asyncContext) {
2557             return;
2558         }
2559         auto container = AceEngine::Get().GetContainer(asyncContext->instanceId);
2560         if (!container) {
2561             return;
2562         }
2563         auto taskExecutor = container->GetTaskExecutor();
2564         if (!taskExecutor) {
2565             return;
2566         }
2567         taskExecutor->PostTask(
2568             [asyncContext, dialogId]() {
2569                 if (asyncContext == nullptr || !asyncContext->valid) {
2570                     return;
2571                 }
2572 
2573                 napi_handle_scope scope = nullptr;
2574                 napi_open_handle_scope(asyncContext->env, &scope);
2575                 if (scope == nullptr) {
2576                     return;
2577                 }
2578 
2579                 napi_value ret = nullptr;
2580                 if (!asyncContext->deferred) {
2581                     return;
2582                 }
2583                 if (dialogId > 0) {
2584                     napi_create_int32(asyncContext->env, dialogId, &ret);
2585                     napi_resolve_deferred(asyncContext->env, asyncContext->deferred, ret);
2586                 } else {
2587                     std::string strMsg = GetErrorMsg(dialogId);
2588                     std::string strCode = GetErrorCode(dialogId);
2589                     napi_value code = nullptr;
2590                     napi_create_string_utf8(asyncContext->env, strCode.c_str(), strCode.length(), &code);
2591                     napi_value msg = nullptr;
2592                     napi_create_string_utf8(asyncContext->env, strMsg.c_str(), strMsg.length(), &msg);
2593                     napi_value error = nullptr;
2594                     napi_create_error(asyncContext->env, code, msg, &error);
2595                     napi_reject_deferred(asyncContext->env, asyncContext->deferred, error);
2596                 }
2597                 napi_close_handle_scope(asyncContext->env, scope);
2598             },
2599             TaskExecutor::TaskType::JS, "ArkUIDialogParseCustomDialogIdCallback");
2600         asyncContext = nullptr;
2601     };
2602 }
2603 
OpenCustomDialog(napi_env env,std::shared_ptr<PromptAsyncContext> & asyncContext,PromptDialogAttr & promptDialogAttr,std::function<void (int32_t)> & openCallback)2604 void OpenCustomDialog(napi_env env, std::shared_ptr<PromptAsyncContext>& asyncContext,
2605     PromptDialogAttr& promptDialogAttr, std::function<void(int32_t)>& openCallback)
2606 {
2607     promptDialogAttr.isUserCreatedDialog = true;
2608 #ifdef OHOS_STANDARD_SYSTEM
2609     // NG
2610     if (SystemProperties::GetExtSurfaceEnabled() || !ContainerIsService()) {
2611         auto delegate = EngineHelper::GetCurrentDelegateSafely();
2612         if (delegate) {
2613             delegate->OpenCustomDialog(promptDialogAttr, std::move(openCallback));
2614         } else {
2615             // throw internal error
2616             std::string strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "Can not get delegate.";
2617             JSPromptThrowInterError(env, asyncContext, strMsg);
2618         }
2619     } else if (SubwindowManager::GetInstance() != nullptr) {
2620         SubwindowManager::GetInstance()->OpenCustomDialog(promptDialogAttr, std::move(openCallback));
2621     }
2622 #else
2623     auto delegate = EngineHelper::GetCurrentDelegateSafely();
2624     if (delegate) {
2625         delegate->OpenCustomDialog(promptDialogAttr, std::move(openCallback));
2626     } else {
2627         // throw internal error
2628         std::string strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "UI execution context not found.";
2629         JSPromptThrowInterError(env, asyncContext, strMsg);
2630     }
2631 #endif
2632 }
2633 
JSPromptOpenCustomDialog(napi_env env,napi_callback_info info)2634 napi_value JSPromptOpenCustomDialog(napi_env env, napi_callback_info info)
2635 {
2636     TAG_LOGD(AceLogTag::ACE_DIALOG, "openCustomDialog enter");
2637     size_t argc = 2;
2638     napi_value argv[2] = { nullptr };
2639     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
2640     if (argc < 1) {
2641         NapiThrow(
2642             env, "The number of parameters must be greater than or equal to 1.", ERROR_CODE_PARAM_INVALID);
2643         return nullptr;
2644     }
2645 
2646     auto asyncContext = std::make_shared<PromptAsyncContext>();
2647     asyncContext->env = env;
2648     asyncContext->instanceId = Container::CurrentIdSafely();
2649     bool parseOK = JSPromptParseParam(env, argc, argv, asyncContext);
2650     if (!parseOK) {
2651         return nullptr;
2652     }
2653     napi_value result = nullptr;
2654     napi_create_promise(env, &asyncContext->deferred, &result);
2655 
2656     std::function<void(const int32_t& info, const int32_t& instanceId)> onWillDismiss = nullptr;
2657     std::function<void()> onWillDismissRelease = nullptr;
2658     if (asyncContext->onWillDismissRef) {
2659         ParseDialogCallback(asyncContext, onWillDismiss);
2660         ParseDialogReleaseCallback(asyncContext, onWillDismissRelease);
2661     }
2662     std::function<void(int32_t)> openCallback = nullptr;
2663     PromptDialogAttr promptDialogAttr = GetPromptActionDialog(env, asyncContext, onWillDismiss);
2664     promptDialogAttr.customOnWillDismissRelease = std::move(onWillDismissRelease);
2665     if (!asyncContext->builderRef) {
2666         ParseCustomDialogContentCallback(asyncContext, openCallback);
2667         promptDialogAttr.customStyle = true;
2668         promptDialogAttr.customBuilder = nullptr;
2669     } else {
2670         ParseCustomDialogIdCallback(asyncContext, openCallback);
2671     }
2672 
2673     OpenCustomDialog(env, asyncContext, promptDialogAttr, openCallback);
2674 
2675     return result;
2676 }
2677 
ParseBaseDialogOptionsEvent(napi_env env,napi_value arg,std::shared_ptr<PromptAsyncContext> & asyncContext)2678 void ParseBaseDialogOptionsEvent(napi_env env, napi_value arg, std::shared_ptr<PromptAsyncContext>& asyncContext)
2679 {
2680     napi_get_named_property(env, arg, "onWillDismiss", &asyncContext->onWillDismiss);
2681     napi_valuetype valueType = napi_undefined;
2682     napi_typeof(env, asyncContext->onWillDismiss, &valueType);
2683     if (valueType == napi_function) {
2684         napi_create_reference(env, asyncContext->onWillDismiss, 1, &asyncContext->onWillDismissRef);
2685     }
2686     napi_get_named_property(env, arg, "onDidAppear", &asyncContext->onDidAppear);
2687     napi_typeof(env, asyncContext->onDidAppear, &valueType);
2688     if (valueType == napi_function) {
2689         napi_create_reference(env, asyncContext->onDidAppear, 1, &asyncContext->onDidAppearRef);
2690     }
2691     napi_get_named_property(env, arg, "onDidDisappear", &asyncContext->onDidDisappear);
2692     napi_typeof(env, asyncContext->onDidDisappear, &valueType);
2693     if (valueType == napi_function) {
2694         napi_create_reference(env, asyncContext->onDidDisappear, 1, &asyncContext->onDidDisappearRef);
2695     }
2696     napi_get_named_property(env, arg, "onWillAppear", &asyncContext->onWillAppear);
2697     napi_typeof(env, asyncContext->onWillAppear, &valueType);
2698     if (valueType == napi_function) {
2699         napi_create_reference(env, asyncContext->onWillAppear, 1, &asyncContext->onWillAppearRef);
2700     }
2701     napi_get_named_property(env, arg, "onWillDisappear", &asyncContext->onWillDisappear);
2702     napi_typeof(env, asyncContext->onWillDisappear, &valueType);
2703     if (valueType == napi_function) {
2704         napi_create_reference(env, asyncContext->onWillDisappear, 1, &asyncContext->onWillDisappearRef);
2705     }
2706 }
2707 
ParseBaseDialogOptions(napi_env env,napi_value arg,std::shared_ptr<PromptAsyncContext> & asyncContext)2708 void ParseBaseDialogOptions(napi_env env, napi_value arg, std::shared_ptr<PromptAsyncContext>& asyncContext)
2709 {
2710     napi_get_named_property(env, arg, "maskRect", &asyncContext->maskRectApi);
2711     napi_get_named_property(env, arg, "alignment", &asyncContext->alignmentApi);
2712     napi_get_named_property(env, arg, "offset", &asyncContext->offsetApi);
2713     napi_get_named_property(env, arg, "showInSubWindow", &asyncContext->showInSubWindow);
2714     napi_valuetype valueType = napi_undefined;
2715     napi_typeof(env, asyncContext->showInSubWindow, &valueType);
2716     if (valueType == napi_boolean) {
2717         napi_get_value_bool(env, asyncContext->showInSubWindow, &asyncContext->showInSubWindowBool);
2718     }
2719     napi_get_named_property(env, arg, "isModal", &asyncContext->isModal);
2720     napi_typeof(env, asyncContext->isModal, &valueType);
2721     if (valueType == napi_boolean) {
2722         napi_get_value_bool(env, asyncContext->isModal, &asyncContext->isModalBool);
2723     }
2724     napi_get_named_property(env, arg, "autoCancel", &asyncContext->autoCancel);
2725     napi_typeof(env, asyncContext->autoCancel, &valueType);
2726     if (valueType == napi_boolean) {
2727         napi_get_value_bool(env, asyncContext->autoCancel, &asyncContext->autoCancelBool);
2728     }
2729     napi_get_named_property(env, arg, "transition", &asyncContext->transitionApi);
2730     napi_get_named_property(env, arg, "dialogTransition", &asyncContext->dialogTransitionApi);
2731     napi_get_named_property(env, arg, "maskTransition", &asyncContext->maskTransitionApi);
2732     napi_get_named_property(env, arg, "maskColor", &asyncContext->maskColorApi);
2733     napi_get_named_property(env, arg, "keyboardAvoidMode", &asyncContext->keyboardAvoidModeApi);
2734     napi_get_named_property(env, arg, "keyboardAvoidDistance", &asyncContext->keyboardAvoidDistanceApi);
2735     napi_get_named_property(env, arg, "enableHoverMode", &asyncContext->enableHoverMode);
2736     napi_get_named_property(env, arg, "hoverModeArea", &asyncContext->hoverModeAreaApi);
2737     napi_get_named_property(env, arg, "levelOrder", &asyncContext->levelOrderApi);
2738     napi_get_named_property(env, arg, "backgroundBlurStyleOptions", &asyncContext->blurStyleOptionApi);
2739     napi_get_named_property(env, arg, "backgroundEffect", &asyncContext->effectOptionApi);
2740     napi_get_named_property(env, arg, "levelMode", &asyncContext->dialogLevelModeApi);
2741     napi_get_named_property(env, arg, "levelUniqueId", &asyncContext->dialogLevelUniqueId);
2742     napi_get_named_property(env, arg, "immersiveMode", &asyncContext->dialogImmersiveModeApi);
2743     napi_get_named_property(env, arg, "focusable", &asyncContext->focusableApi);
2744 
2745     ParseBaseDialogOptionsEvent(env, arg, asyncContext);
2746 }
2747 
GetDialogCallback(PromptDialogController * controller)2748 std::function<void(RefPtr<NG::FrameNode> dialogNode)> GetDialogCallback(PromptDialogController* controller)
2749 {
2750     auto builder = [controller](RefPtr<NG::FrameNode> dialogNode) {
2751         if (controller) {
2752             controller->SetNode(dialogNode);
2753         }
2754     };
2755     return builder;
2756 }
2757 
JSPromptOpenCustomDialogWithController(napi_env env,napi_callback_info info)2758 napi_value JSPromptOpenCustomDialogWithController(napi_env env, napi_callback_info info)
2759 {
2760     TAG_LOGD(AceLogTag::ACE_DIALOG, "openCustomDialogWithController enter");
2761     size_t argc = OPEN_CUSTOM_DIALOG_WITH_CONTROLLER_PARAM_TOTAL;
2762     napi_value argv[OPEN_CUSTOM_DIALOG_WITH_CONTROLLER_PARAM_TOTAL] = { nullptr };
2763     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
2764     if (argc < OPEN_CUSTOM_DIALOG_WITH_CONTROLLER_PARAM_MAND_COUNT
2765         || argc > OPEN_CUSTOM_DIALOG_WITH_CONTROLLER_PARAM_TOTAL) {
2766         NapiThrow(env, "The number of parameters must be between 2 and 3.", ERROR_CODE_PARAM_INVALID);
2767         return nullptr;
2768     }
2769 
2770     for (size_t i = 0; i < argc; i++) {
2771         napi_valuetype valueType = napi_undefined;
2772         napi_typeof(env, argv[i], &valueType);
2773         if (valueType != napi_object) {
2774             NapiThrow(env, "The type of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
2775             return nullptr;
2776         }
2777     }
2778 
2779     auto asyncContext = std::make_shared<PromptAsyncContext>();
2780     asyncContext->env = env;
2781     asyncContext->instanceId = Container::CurrentIdSafely();
2782     auto nodeResult = napi_get_named_property(env, argv[0], "nodePtr_", &asyncContext->frameNodePtr);
2783     if (nodeResult != napi_ok) {
2784         NapiThrow(env, "The type of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
2785         return nullptr;
2786     }
2787     napi_get_value_external(env, asyncContext->frameNodePtr, &asyncContext->nativePtr);
2788 
2789     PromptDialogController* controller = nullptr;
2790     napi_unwrap(env, argv[OPEN_CUSTOM_DIALOG_WITH_CONTROLLER_PARAM_INDEX_CONTROLLER], (void**)&controller);
2791     if (!controller) {
2792         NapiThrow(env, "The type of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
2793         return nullptr;
2794     }
2795 
2796     if (argc > OPEN_CUSTOM_DIALOG_WITH_CONTROLLER_PARAM_INDEX_OPTIONS) {
2797         ParseBaseDialogOptions(env, argv[OPEN_CUSTOM_DIALOG_WITH_CONTROLLER_PARAM_INDEX_OPTIONS], asyncContext);
2798     }
2799 
2800     napi_value result = nullptr;
2801     napi_create_promise(env, &asyncContext->deferred, &result);
2802 
2803     std::function<void(const int32_t& info, const int32_t& instanceId)> onWillDismiss = nullptr;
2804     std::function<void()> onWillDismissRelease = nullptr;
2805     if (asyncContext->onWillDismissRef) {
2806         ParseDialogCallback(asyncContext, onWillDismiss);
2807         ParseDialogReleaseCallback(asyncContext, onWillDismissRelease);
2808     }
2809 
2810     PromptDialogAttr promptDialogAttr = GetPromptActionDialog(env, asyncContext, onWillDismiss);
2811     promptDialogAttr.customStyle = true;
2812     promptDialogAttr.customBuilder = nullptr;
2813     promptDialogAttr.dialogCallback = GetDialogCallback(controller);
2814     promptDialogAttr.customOnWillDismissRelease = std::move(onWillDismissRelease);
2815 
2816     std::function<void(int32_t)> openCallback = nullptr;
2817     ParseCustomDialogContentCallback(asyncContext, openCallback);
2818     OpenCustomDialog(env, asyncContext, promptDialogAttr, openCallback);
2819     return result;
2820 }
2821 
ParseDialogOptions(napi_env env,napi_value arg,std::shared_ptr<PromptAsyncContext> & asyncContext)2822 void ParseDialogOptions(napi_env env, napi_value arg, std::shared_ptr<PromptAsyncContext>& asyncContext)
2823 {
2824     ParseBaseDialogOptions(env, arg, asyncContext);
2825     napi_get_named_property(env, arg, "backgroundColor", &asyncContext->backgroundColorApi);
2826     napi_get_named_property(env, arg, "cornerRadius", &asyncContext->borderRadiusApi);
2827     napi_get_named_property(env, arg, "width", &asyncContext->widthApi);
2828     napi_get_named_property(env, arg, "height", &asyncContext->heightApi);
2829     napi_get_named_property(env, arg, "borderWidth", &asyncContext->borderWidthApi);
2830     napi_get_named_property(env, arg, "borderColor", &asyncContext->borderColorApi);
2831     napi_get_named_property(env, arg, "borderStyle", &asyncContext->borderStyleApi);
2832     napi_get_named_property(env, arg, "shadow", &asyncContext->shadowApi);
2833     napi_get_named_property(env, arg, "backgroundBlurStyle", &asyncContext->backgroundBlurStyleApi);
2834 }
2835 
JSPromptPresentCustomDialog(napi_env env,napi_callback_info info)2836 napi_value JSPromptPresentCustomDialog(napi_env env, napi_callback_info info)
2837 {
2838     TAG_LOGD(AceLogTag::ACE_DIALOG, "presentCustomDialog enter");
2839     size_t argc = PRESENT_CUSTOM_DIALOG_PARAM_TOTAL;
2840     napi_value argv[PRESENT_CUSTOM_DIALOG_PARAM_TOTAL] = { nullptr };
2841     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
2842     if (argc < PRESENT_CUSTOM_DIALOG_PARAM_MAND_COUNT || argc > PRESENT_CUSTOM_DIALOG_PARAM_TOTAL) {
2843         NapiThrow(env, "The number of parameters must be between 1 and 3.", ERROR_CODE_PARAM_INVALID);
2844         return nullptr;
2845     }
2846 
2847     napi_valuetype paramTypes[PRESENT_CUSTOM_DIALOG_PARAM_TOTAL] = { napi_function, napi_object, napi_object };
2848     for (size_t i = 0; i < argc; i++) {
2849         napi_valuetype valueType = napi_undefined;
2850         napi_typeof(env, argv[i], &valueType);
2851         if (valueType != paramTypes[i]) {
2852             NapiThrow(env, "The type of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
2853             return nullptr;
2854         }
2855     }
2856 
2857     auto asyncContext = std::make_shared<PromptAsyncContext>();
2858     asyncContext->env = env;
2859     asyncContext->instanceId = Container::CurrentIdSafely();
2860     napi_create_reference(env, argv[0], 1, &asyncContext->builderRef);
2861 
2862     PromptDialogController* controller = nullptr;
2863     if (argc > PRESENT_CUSTOM_DIALOG_PARAM_INDEX_CONTROLLER) {
2864         napi_unwrap(env, argv[PRESENT_CUSTOM_DIALOG_PARAM_INDEX_CONTROLLER], (void**)&controller);
2865     }
2866 
2867     if (argc > PRESENT_CUSTOM_DIALOG_PARAM_INDEX_OPTIONS) {
2868         ParseDialogOptions(env, argv[PRESENT_CUSTOM_DIALOG_PARAM_INDEX_OPTIONS], asyncContext);
2869     }
2870 
2871     napi_value result = nullptr;
2872     napi_create_promise(env, &asyncContext->deferred, &result);
2873 
2874     std::function<void(const int32_t& info, const int32_t& instanceId)> onWillDismiss = nullptr;
2875     std::function<void()> onWillDismissRelease = nullptr;
2876     if (asyncContext->onWillDismissRef) {
2877         ParseDialogCallback(asyncContext, onWillDismiss);
2878         ParseDialogReleaseCallback(asyncContext, onWillDismissRelease);
2879     }
2880 
2881     PromptDialogAttr promptDialogAttr = GetPromptActionDialog(env, asyncContext, onWillDismiss);
2882     auto builder = GetCustomBuilderWithId(env, asyncContext);
2883     promptDialogAttr.customBuilderWithId = std::move(builder);
2884     promptDialogAttr.customOnWillDismissRelease = std::move(onWillDismissRelease);
2885     if (controller) {
2886         promptDialogAttr.dialogCallback = GetDialogCallback(controller);
2887     }
2888 
2889     std::function<void(int32_t)> openCallback = nullptr;
2890     ParseCustomDialogIdCallback(asyncContext, openCallback);
2891     OpenCustomDialog(env, asyncContext, promptDialogAttr, openCallback);
2892     return result;
2893 }
2894 
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)2895 void CloseCustomDialog(napi_env env, std::shared_ptr<PromptAsyncContext>& asyncContext, bool useDialogId,
2896     int32_t dialogId, const WeakPtr<NG::UINode>& nodeWk, std::function<void(int32_t)>& contentCallback)
2897 {
2898 #ifdef OHOS_STANDARD_SYSTEM
2899     // NG
2900     if (SystemProperties::GetExtSurfaceEnabled() || !ContainerIsService()) {
2901         auto delegate = EngineHelper::GetCurrentDelegateSafely();
2902         if (delegate) {
2903             if (useDialogId) {
2904                 delegate->CloseCustomDialog(dialogId);
2905             } else {
2906                 delegate->CloseCustomDialog(nodeWk, std::move(contentCallback));
2907             }
2908         } else {
2909             // throw internal error
2910             napi_create_promise(env, &asyncContext->deferred, nullptr);
2911             std::string strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "Can not get delegate.";
2912             JSPromptThrowInterError(env, asyncContext, strMsg);
2913         }
2914     } else if (SubwindowManager::GetInstance() != nullptr) {
2915         if (useDialogId) {
2916             SubwindowManager::GetInstance()->CloseCustomDialogNG(dialogId);
2917         } else {
2918             SubwindowManager::GetInstance()->CloseCustomDialogNG(nodeWk, std::move(contentCallback));
2919         }
2920     }
2921 #else
2922     auto delegate = EngineHelper::GetCurrentDelegateSafely();
2923     if (delegate) {
2924         if (useDialogId) {
2925             delegate->CloseCustomDialog(dialogId);
2926         } else {
2927             delegate->CloseCustomDialog(nodeWk, std::move(contentCallback));
2928         }
2929     } else {
2930         // throw internal error
2931         napi_create_promise(env, &asyncContext->deferred, nullptr);
2932         std::string strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "UI execution context not found.";
2933         JSPromptThrowInterError(env, asyncContext, strMsg);
2934     }
2935 #endif
2936 }
2937 
JSPromptCloseCustomDialog(napi_env env,napi_callback_info info)2938 napi_value JSPromptCloseCustomDialog(napi_env env, napi_callback_info info)
2939 {
2940     TAG_LOGD(AceLogTag::ACE_DIALOG, "closeCustomDialog enter");
2941     size_t argc = 1;
2942     napi_value argv[1] = { 0 };
2943     int32_t dialogId = -1;
2944     WeakPtr<NG::UINode> nodeWk;
2945     bool useDialogId = true;
2946     std::function<void(int32_t)> contentCallback = nullptr;
2947     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
2948     auto asyncContext = std::make_shared<PromptAsyncContext>();
2949     asyncContext->env = env;
2950     asyncContext->instanceId = Container::CurrentIdSafely();
2951     napi_value ret = nullptr;
2952     if (argc > 1) {
2953         NapiThrow(env, "The number of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
2954         return nullptr;
2955     } else if (argc == 0) {
2956         dialogId = -1;
2957     } else {
2958         napi_valuetype valueType = napi_undefined;
2959         napi_typeof(env, argv[0], &valueType);
2960         if (valueType == napi_number) {
2961             napi_get_value_int32(env, argv[0], &dialogId);
2962         } else if (valueType == napi_object) {
2963             napi_value frameNodePtr = nullptr;
2964             auto result = napi_get_named_property(env, argv[0], "nodePtr_", &frameNodePtr);
2965             if (result != napi_ok) {
2966                 NapiThrow(env, "The type of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
2967                 return nullptr;
2968             }
2969             void* nativePtr = nullptr;
2970             result = napi_get_value_external(env, frameNodePtr, &nativePtr);
2971             if (result != napi_ok) {
2972                 NapiThrow(env, "The type of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
2973                 return nullptr;
2974             }
2975             auto* uiNodePtr = reinterpret_cast<OHOS::Ace::NG::UINode*>(nativePtr);
2976             nodeWk = AceType::WeakClaim(uiNodePtr);
2977             useDialogId = false;
2978             napi_create_promise(env, &asyncContext->deferred, &ret);
2979             ParseCustomDialogContentCallback(asyncContext, contentCallback);
2980         } else {
2981             NapiThrow(env, "The type of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
2982             return nullptr;
2983         }
2984     }
2985 
2986     CloseCustomDialog(env, asyncContext, useDialogId, dialogId, nodeWk, contentCallback);
2987 
2988     return ret;
2989 }
2990 
UpdateCustomDialog(napi_env env,std::shared_ptr<PromptAsyncContext> & asyncContext,PromptDialogAttr & promptDialogAttr,const WeakPtr<NG::UINode> & nodeWk,std::function<void (int32_t)> & contentCallback)2991 void UpdateCustomDialog(napi_env env, std::shared_ptr<PromptAsyncContext>& asyncContext,
2992     PromptDialogAttr& promptDialogAttr, const WeakPtr<NG::UINode>& nodeWk,
2993     std::function<void(int32_t)>& contentCallback)
2994 {
2995 #ifdef OHOS_STANDARD_SYSTEM
2996     // NG
2997     if (SystemProperties::GetExtSurfaceEnabled() || !ContainerIsService()) {
2998         auto delegate = EngineHelper::GetCurrentDelegateSafely();
2999         if (delegate) {
3000             delegate->UpdateCustomDialog(nodeWk, promptDialogAttr, std::move(contentCallback));
3001         } else {
3002             // throw internal error
3003             napi_create_promise(env, &asyncContext->deferred, nullptr);
3004             std::string strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "Can not get delegate.";
3005             JSPromptThrowInterError(env, asyncContext, strMsg);
3006         }
3007     } else if (SubwindowManager::GetInstance() != nullptr) {
3008         SubwindowManager::GetInstance()->UpdateCustomDialogNG(nodeWk, promptDialogAttr, std::move(contentCallback));
3009     }
3010 #else
3011     auto delegate = EngineHelper::GetCurrentDelegateSafely();
3012     if (delegate) {
3013         delegate->UpdateCustomDialog(nodeWk, promptDialogAttr, std::move(contentCallback));
3014     } else {
3015         // throw internal error
3016         napi_create_promise(env, &asyncContext->deferred, nullptr);
3017         std::string strMsg = ErrorToMessage(ERROR_CODE_INTERNAL_ERROR) + "UI execution context not found.";
3018         JSPromptThrowInterError(env, asyncContext, strMsg);
3019     }
3020 #endif
3021 }
3022 
JSPromptUpdateCustomDialog(napi_env env,napi_callback_info info)3023 napi_value JSPromptUpdateCustomDialog(napi_env env, napi_callback_info info)
3024 {
3025     TAG_LOGD(AceLogTag::ACE_DIALOG, "updateCustomDialog enter");
3026     size_t argc = CUSTOM_DIALOG_PARAM_NUM;
3027     napi_value argv[CUSTOM_DIALOG_PARAM_NUM] = { nullptr };
3028     WeakPtr<NG::UINode> nodeWk;
3029     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
3030     if (argc != CUSTOM_DIALOG_PARAM_NUM) {
3031         NapiThrow(env, "The number of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
3032         return nullptr;
3033     }
3034     auto asyncContext = std::make_shared<PromptAsyncContext>();
3035     asyncContext->env = env;
3036     asyncContext->instanceId = Container::CurrentIdSafely();
3037     napi_value ret = nullptr;
3038 
3039     napi_valuetype valueType = napi_undefined;
3040     napi_typeof(env, argv[0], &valueType);
3041     if (valueType == napi_object) {
3042         napi_value frameNodePtr = nullptr;
3043         auto result = napi_get_named_property(env, argv[0], "nodePtr_", &frameNodePtr);
3044         if (result != napi_ok) {
3045             NapiThrow(env, "The type of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
3046             return nullptr;
3047         }
3048         void* nativePtr = nullptr;
3049         result = napi_get_value_external(env, frameNodePtr, &nativePtr);
3050         if (result != napi_ok) {
3051             NapiThrow(env, "The type of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
3052             return nullptr;
3053         }
3054         auto* uiNodePtr = reinterpret_cast<OHOS::Ace::NG::UINode*>(nativePtr);
3055         nodeWk = AceType::WeakClaim(uiNodePtr);
3056     } else {
3057         NapiThrow(env, "The type of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
3058         return nullptr;
3059     }
3060 
3061     napi_typeof(env, argv[1], &valueType);
3062     if (valueType != napi_object) {
3063         NapiThrow(env, "The type of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
3064         return nullptr;
3065     }
3066     GetNapiNamedProperties(env, argv, 1, asyncContext);
3067 
3068     napi_create_promise(env, &asyncContext->deferred, &ret);
3069     std::function<void(int32_t)> contentCallback = nullptr;
3070     ParseCustomDialogContentCallback(asyncContext, contentCallback);
3071     PromptDialogAttr promptDialogAttr = GetPromptActionDialog(env, asyncContext, nullptr);
3072 
3073     UpdateCustomDialog(env, asyncContext, promptDialogAttr, nodeWk, contentCallback);
3074 
3075     return ret;
3076 }
3077 
3078 } // namespace OHOS::Ace::Napi
3079