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