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