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