1 /*
2 * Copyright (c) 2021-2023 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 "bridge/declarative_frontend/jsview/js_datepicker.h"
17
18 #include <utility>
19
20 #include "base/log/ace_scoring_log.h"
21 #include "base/utils/utils.h"
22 #include "bridge/common/utils/engine_helper.h"
23 #include "bridge/declarative_frontend/engine/functions/js_function.h"
24 #include "bridge/declarative_frontend/jsview/js_interactable_view.h"
25 #include "bridge/declarative_frontend/jsview/js_utils.h"
26 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
27 #include "bridge/declarative_frontend/jsview/models/picker_model_impl.h"
28 #include "bridge/declarative_frontend/jsview/models/timepicker_model_impl.h"
29 #include "bridge/declarative_frontend/view_stack_processor.h"
30 #include "core/components/picker/picker_data.h"
31 #include "core/components/picker/picker_date_component.h"
32 #include "core/components/picker/picker_theme.h"
33 #include "core/components/picker/picker_time_component.h"
34 #include "core/components_ng/base/view_stack_processor.h"
35 #include "core/components_ng/pattern/picker/datepicker_model_ng.h"
36 #include "core/components_ng/pattern/time_picker/timepicker_model.h"
37 #include "core/components_ng/pattern/time_picker/timepicker_model_ng.h"
38 #include "core/components_v2/inspector/inspector_constants.h"
39 #include "core/event/ace_event_helper.h"
40 #include "core/pipeline_ng/pipeline_context.h"
41
42 namespace OHOS::Ace {
43 namespace {
44 const DimensionOffset DATEPICKER_OFFSET_DEFAULT_TOP = DimensionOffset(0.0_vp, 40.0_vp);
45 const std::vector<DialogAlignment> DIALOG_ALIGNMENT = { DialogAlignment::TOP, DialogAlignment::CENTER,
46 DialogAlignment::BOTTOM, DialogAlignment::DEFAULT, DialogAlignment::TOP_START, DialogAlignment::TOP_END,
47 DialogAlignment::CENTER_START, DialogAlignment::CENTER_END, DialogAlignment::BOTTOM_START,
48 DialogAlignment::BOTTOM_END };
49 const std::vector<HoverModeAreaType> HOVER_MODE_AREA_TYPE = { HoverModeAreaType::TOP_SCREEN,
50 HoverModeAreaType::BOTTOM_SCREEN };
51 const char TIMEPICKER_OPTIONS_HOUR[] = "hour";
52 const char TIMEPICKER_OPTIONS_MINUTE[] = "minute";
53 const char TIMEPICKER_OPTIONS_SECOND[] = "second";
54 const std::string TIMEPICKER_OPTIONS_NUMERIC_VAL = "numeric";
55 const std::string TIMEPICKER_OPTIONS_TWO_DIGIT_VAL = "2-digit";
56 } // namespace
57
58 std::unique_ptr<DatePickerModel> DatePickerModel::datePickerInstance_ = nullptr;
59 std::unique_ptr<DatePickerDialogModel> DatePickerDialogModel::datePickerDialogInstance_ = nullptr;
60 std::unique_ptr<TimePickerModel> TimePickerModel::timePickerInstance_ = nullptr;
61 std::unique_ptr<TimePickerDialogModel> TimePickerDialogModel::timePickerDialogInstance_ = nullptr;
62 std::once_flag DatePickerModel::onceFlag_;
63 std::once_flag DatePickerDialogModel::onceFlag_;
64 std::once_flag TimePickerModel::onceFlag_;
65 std::once_flag TimePickerDialogModel::onceFlag_;
66
GetInstance()67 DatePickerModel* DatePickerModel::GetInstance()
68 {
69 std::call_once(onceFlag_, []() {
70 #ifdef NG_BUILD
71 datePickerInstance_.reset(new NG::DatePickerModelNG());
72 #else
73 if (Container::IsCurrentUseNewPipeline()) {
74 datePickerInstance_.reset(new NG::DatePickerModelNG());
75 } else {
76 datePickerInstance_.reset(new Framework::DatePickerModelImpl());
77 }
78 #endif
79 });
80
81 return datePickerInstance_.get();
82 }
83
GetInstance()84 DatePickerDialogModel* DatePickerDialogModel::GetInstance()
85 {
86 std::call_once(onceFlag_, []() {
87 #ifdef NG_BUILD
88 datePickerDialogInstance_.reset(new NG::DatePickerDialogModelNG());
89 #else
90 if (Container::IsCurrentUseNewPipeline()) {
91 datePickerDialogInstance_.reset(new NG::DatePickerDialogModelNG());
92 } else {
93 datePickerDialogInstance_.reset(new Framework::DatePickerDialogModelImpl());
94 }
95 #endif
96 });
97
98 return datePickerDialogInstance_.get();
99 }
100
GetInstance()101 TimePickerModel* TimePickerModel::GetInstance()
102 {
103 std::call_once(onceFlag_, []() {
104 #ifdef NG_BUILD
105 timePickerInstance_.reset(new NG::TimePickerModelNG());
106 #else
107 if (Container::IsCurrentUseNewPipeline()) {
108 timePickerInstance_.reset(new NG::TimePickerModelNG());
109 } else {
110 timePickerInstance_.reset(new Framework::TimePickerModelImpl());
111 }
112 #endif
113 });
114
115 return timePickerInstance_.get();
116 }
117
GetInstance()118 TimePickerDialogModel* TimePickerDialogModel::GetInstance()
119 {
120 std::call_once(onceFlag_, []() {
121 #ifdef NG_BUILD
122 timePickerDialogInstance_.reset(new NG::TimePickerDialogModelNG());
123 #else
124 if (Container::IsCurrentUseNewPipeline()) {
125 timePickerDialogInstance_.reset(new NG::TimePickerDialogModelNG());
126 } else {
127 timePickerDialogInstance_.reset(new Framework::TimePickerDialogModelImpl());
128 }
129 #endif
130 });
131
132 return timePickerDialogInstance_.get();
133 }
134 } // namespace OHOS::Ace
135
136 namespace OHOS::Ace::Framework {
137 namespace {
DatePickerChangeEventToJSValue(const DatePickerChangeEvent & eventInfo)138 JSRef<JSVal> DatePickerChangeEventToJSValue(const DatePickerChangeEvent& eventInfo)
139 {
140 JSRef<JSObject> obj = JSRef<JSObject>::New();
141 std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(eventInfo.GetSelectedStr());
142 if (!argsPtr) {
143 return JSRef<JSVal>::Cast(obj);
144 }
145 std::vector<std::string> keys = { "year", "month", "day", "hour", "minute", "second" };
146 for (auto iter = keys.begin(); iter != keys.end(); iter++) {
147 const std::string key = *iter;
148 const auto value = argsPtr->GetValue(key);
149 if (!value || value->ToString().empty()) {
150 continue;
151 }
152 obj->SetProperty<int32_t>(key.c_str(), value->GetInt());
153 }
154 return JSRef<JSVal>::Cast(obj);
155 }
156
DatePickerDateChangeEventToJSValue(const DatePickerChangeEvent & eventInfo)157 JSRef<JSVal> DatePickerDateChangeEventToJSValue(const DatePickerChangeEvent& eventInfo)
158 {
159 JSRef<JSObject> obj = JSRef<JSObject>::New();
160 std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(eventInfo.GetSelectedStr());
161 if (!argsPtr) {
162 return JSRef<JSVal>::Cast(obj);
163 }
164 auto dateObj = JSDatePickerDialog::GetDateObj(argsPtr);
165 return JSRef<JSVal>::Cast(dateObj);
166 }
167
ParseFontOfButtonStyle(const JSRef<JSObject> & pickerButtonParamObject,ButtonInfo & buttonInfo)168 void ParseFontOfButtonStyle(const JSRef<JSObject>& pickerButtonParamObject, ButtonInfo& buttonInfo)
169 {
170 CalcDimension fontSize;
171 JSRef<JSVal> sizeProperty = pickerButtonParamObject->GetProperty("fontSize");
172 if (JSViewAbstract::ParseJsDimensionVpNG(sizeProperty, fontSize) && fontSize.Unit() != DimensionUnit::PERCENT &&
173 GreatOrEqual(fontSize.Value(), 0.0)) {
174 if (JSViewAbstract::ParseJsDimensionFp(sizeProperty, fontSize)) {
175 buttonInfo.fontSize = fontSize;
176 }
177 }
178 Color fontColor;
179 if (JSViewAbstract::ParseJsColor(pickerButtonParamObject->GetProperty("fontColor"), fontColor)) {
180 buttonInfo.fontColor = fontColor;
181 }
182 auto fontWeight = pickerButtonParamObject->GetProperty("fontWeight");
183 if (fontWeight->IsString() || fontWeight->IsNumber()) {
184 buttonInfo.fontWeight = ConvertStrToFontWeight(fontWeight->ToString(), FontWeight::MEDIUM);
185 }
186 JSRef<JSVal> style = pickerButtonParamObject->GetProperty("fontStyle");
187 if (style->IsNumber()) {
188 auto value = style->ToNumber<int32_t>();
189 if (value >= 0 && value < static_cast<int32_t>(FontStyle::NONE)) {
190 buttonInfo.fontStyle = static_cast<FontStyle>(value);
191 }
192 }
193 JSRef<JSVal> family = pickerButtonParamObject->GetProperty("fontFamily");
194 std::vector<std::string> fontFamilies;
195 if (JSViewAbstract::ParseJsFontFamilies(family, fontFamilies)) {
196 buttonInfo.fontFamily = fontFamilies;
197 }
198 }
199
ParseButtonStyle(const JSRef<JSObject> & pickerButtonParamObject)200 ButtonInfo ParseButtonStyle(const JSRef<JSObject>& pickerButtonParamObject)
201 {
202 ButtonInfo buttonInfo;
203 if (pickerButtonParamObject->GetProperty("type")->IsNumber()) {
204 auto buttonTypeIntValue = pickerButtonParamObject->GetProperty("type")->ToNumber<int32_t>();
205 if (buttonTypeIntValue == static_cast<int32_t>(ButtonType::CAPSULE) ||
206 buttonTypeIntValue == static_cast<int32_t>(ButtonType::CIRCLE) ||
207 buttonTypeIntValue == static_cast<int32_t>(ButtonType::ARC) ||
208 buttonTypeIntValue == static_cast<int32_t>(ButtonType::NORMAL) ||
209 buttonTypeIntValue == static_cast<int32_t>(ButtonType::ROUNDED_RECTANGLE)) {
210 buttonInfo.type = static_cast<ButtonType>(buttonTypeIntValue);
211 }
212 }
213 if (pickerButtonParamObject->GetProperty("style")->IsNumber()) {
214 auto styleModeIntValue = pickerButtonParamObject->GetProperty("style")->ToNumber<int32_t>();
215 if (styleModeIntValue >= static_cast<int32_t>(ButtonStyleMode::NORMAL) &&
216 styleModeIntValue <= static_cast<int32_t>(ButtonStyleMode::TEXT)) {
217 buttonInfo.buttonStyle = static_cast<ButtonStyleMode>(styleModeIntValue);
218 }
219 }
220 if (pickerButtonParamObject->GetProperty("role")->IsNumber()) {
221 auto buttonRoleIntValue = pickerButtonParamObject->GetProperty("role")->ToNumber<int32_t>();
222 if (buttonRoleIntValue >= static_cast<int32_t>(ButtonRole::NORMAL) &&
223 buttonRoleIntValue <= static_cast<int32_t>(ButtonRole::ERROR)) {
224 buttonInfo.role = static_cast<ButtonRole>(buttonRoleIntValue);
225 }
226 }
227 ParseFontOfButtonStyle(pickerButtonParamObject, buttonInfo);
228 Color backgroundColor;
229 if (JSViewAbstract::ParseJsColor(pickerButtonParamObject->GetProperty("backgroundColor"), backgroundColor)) {
230 buttonInfo.backgroundColor = backgroundColor;
231 }
232 auto radius = ParseBorderRadiusAttr(pickerButtonParamObject->GetProperty("borderRadius"));
233 if (radius.has_value()) {
234 buttonInfo.borderRadius = radius.value();
235 }
236
237 auto primaryValue = pickerButtonParamObject->GetProperty("primary");
238 if (primaryValue->IsBoolean()) {
239 buttonInfo.isPrimary = primaryValue->ToBoolean();
240 }
241
242 return buttonInfo;
243 }
244
ParseButtonStyles(const JSRef<JSObject> & paramObject)245 std::vector<ButtonInfo> ParseButtonStyles(const JSRef<JSObject>& paramObject)
246 {
247 std::vector<ButtonInfo> buttonInfos;
248 auto acceptButtonStyle = paramObject->GetProperty("acceptButtonStyle");
249 if (acceptButtonStyle->IsObject()) {
250 auto acceptButtonStyleParamObject = JSRef<JSObject>::Cast(acceptButtonStyle);
251 buttonInfos.emplace_back(ParseButtonStyle(acceptButtonStyleParamObject));
252 buttonInfos[0].isAcceptButton = true;
253 } else {
254 ButtonInfo buttonInfo;
255 buttonInfos.emplace_back(buttonInfo);
256 }
257 auto cancelButtonStyle = paramObject->GetProperty("cancelButtonStyle");
258 if (cancelButtonStyle->IsObject()) {
259 auto cancelButtonStyleParamObject = JSRef<JSObject>::Cast(cancelButtonStyle);
260 buttonInfos.emplace_back(ParseButtonStyle(cancelButtonStyleParamObject));
261 }
262
263 return buttonInfos;
264 }
265
ParseDatePickerHoverMode(PickerDialogInfo & pickerDialog,const JSRef<JSObject> & paramObject)266 void ParseDatePickerHoverMode(PickerDialogInfo& pickerDialog, const JSRef<JSObject>& paramObject)
267 {
268 auto enableHoverModeValue = paramObject->GetProperty("enableHoverMode");
269 if (enableHoverModeValue->IsBoolean()) {
270 pickerDialog.enableHoverMode = enableHoverModeValue->ToBoolean();
271 }
272
273 auto hoverModeAreaValue = paramObject->GetProperty("hoverModeArea");
274 if (hoverModeAreaValue->IsNumber()) {
275 auto hoverModeArea = hoverModeAreaValue->ToNumber<int32_t>();
276 if (hoverModeArea >= 0 && hoverModeArea < static_cast<int32_t>(HOVER_MODE_AREA_TYPE.size())) {
277 pickerDialog.hoverModeArea = HOVER_MODE_AREA_TYPE[hoverModeArea];
278 }
279 }
280 }
281
ParseDatePickerBlurStyleOption(PickerDialogInfo & pickerDialog,const JSRef<JSObject> & paramObject)282 void ParseDatePickerBlurStyleOption(PickerDialogInfo& pickerDialog, const JSRef<JSObject>& paramObject)
283 {
284 auto blurStyleValue = paramObject->GetProperty("backgroundBlurStyleOptions");
285 if (blurStyleValue->IsObject()) {
286 if (!pickerDialog.blurStyleOption.has_value()) {
287 pickerDialog.blurStyleOption.emplace();
288 }
289 JSViewAbstract::ParseBlurStyleOption(blurStyleValue, pickerDialog.blurStyleOption.value());
290 }
291 }
292
ParseDatePickerEffectOption(PickerDialogInfo & pickerDialog,const JSRef<JSObject> & paramObject)293 void ParseDatePickerEffectOption(PickerDialogInfo& pickerDialog, const JSRef<JSObject>& paramObject)
294 {
295 auto effectOptionValue = paramObject->GetProperty("backgroundEffect");
296 if (effectOptionValue->IsObject()) {
297 if (!pickerDialog.effectOption.has_value()) {
298 pickerDialog.effectOption.emplace();
299 }
300 JSViewAbstract::ParseEffectOption(effectOptionValue, pickerDialog.effectOption.value());
301 }
302 }
303 } // namespace
304
JSBind(BindingTarget globalObj)305 void JSDatePicker::JSBind(BindingTarget globalObj)
306 {
307 JSClass<JSDatePicker>::Declare("DatePicker");
308 MethodOptions opt = MethodOptions::NONE;
309 JSClass<JSDatePicker>::StaticMethod("create", &JSDatePicker::Create, opt);
310 JSClass<JSDatePicker>::StaticMethod("lunar", &JSDatePicker::SetLunar);
311 JSClass<JSDatePicker>::StaticMethod("onChange", &JSDatePicker::OnChange);
312 JSClass<JSDatePicker>::StaticMethod("onDateChange", &JSDatePicker::OnDateChange);
313 JSClass<JSDatePicker>::StaticMethod("backgroundColor", &JSDatePicker::PickerBackgroundColor);
314 JSClass<JSDatePicker>::StaticMethod("opacity", &JSDatePicker::JsOpacity);
315 // keep compatible, need remove after
316 JSClass<JSDatePicker>::StaticMethod("useMilitaryTime", &JSDatePicker::UseMilitaryTime);
317 JSClass<JSDatePicker>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
318 JSClass<JSDatePicker>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
319 JSClass<JSDatePicker>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
320 JSClass<JSDatePicker>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
321 JSClass<JSDatePicker>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
322 JSClass<JSDatePicker>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
323 JSClass<JSDatePicker>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
324 JSClass<JSDatePicker>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
325 JSClass<JSDatePicker>::StaticMethod("disappearTextStyle", &JSDatePicker::SetDisappearTextStyle);
326 JSClass<JSDatePicker>::StaticMethod("textStyle", &JSDatePicker::SetTextStyle);
327 JSClass<JSDatePicker>::StaticMethod("selectedTextStyle", &JSDatePicker::SetSelectedTextStyle);
328 JSClass<JSDatePicker>::StaticMethod("enableHapticFeedback", &JSDatePicker::SetEnableHapticFeedback);
329 JSClass<JSDatePicker>::StaticMethod("digitalCrownSensitivity", &JSDatePicker::SetDigitalCrownSensitivity);
330 JSClass<JSDatePicker>::InheritAndBind<JSViewAbstract>(globalObj);
331 }
332
SetDigitalCrownSensitivity(const JSCallbackInfo & info)333 void JSDatePicker::SetDigitalCrownSensitivity(const JSCallbackInfo& info)
334 {
335 int32_t value = OHOS::Ace::NG::DEFAULT_CROWNSENSITIVITY;
336 if (info.Length() >= 1 && info[0]->IsNumber()) {
337 value = info[0]->ToNumber<int32_t>();
338 }
339 DatePickerModel::GetInstance()->SetDigitalCrownSensitivity(value);
340 }
341
Create(const JSCallbackInfo & info)342 void JSDatePicker::Create(const JSCallbackInfo& info)
343 {
344 DatePickerType pickerType = DatePickerType::DATE;
345 JSRef<JSObject> paramObject;
346 if (info.Length() >= 1 && info[0]->IsObject()) {
347 paramObject = JSRef<JSObject>::Cast(info[0]);
348 auto type = paramObject->GetProperty("type");
349 if (type->IsNumber()) {
350 pickerType = static_cast<DatePickerType>(type->ToNumber<int32_t>());
351 }
352 }
353 switch (pickerType) {
354 case DatePickerType::TIME: {
355 CreateTimePicker(info, paramObject);
356 break;
357 }
358 case DatePickerType::DATE: {
359 CreateDatePicker(info, paramObject);
360 break;
361 }
362 default: {
363 break;
364 }
365 }
366 }
367
SetLunar(bool isLunar)368 void JSDatePicker::SetLunar(bool isLunar)
369 {
370 DatePickerModel::GetInstance()->SetShowLunar(isLunar);
371 }
372
UseMilitaryTime(bool isUseMilitaryTime)373 void JSDatePicker::UseMilitaryTime(bool isUseMilitaryTime)
374 {
375 DatePickerModel::GetInstance()->SetHour24(isUseMilitaryTime);
376 }
377
ParseTextProperties(const JSRef<JSObject> & paramObj,NG::PickerTextProperties & result)378 void JSDatePicker::ParseTextProperties(const JSRef<JSObject>& paramObj, NG::PickerTextProperties& result)
379 {
380 auto disappearProperty = paramObj->GetProperty("disappearTextStyle");
381 auto normalProperty = paramObj->GetProperty("textStyle");
382 auto selectedProperty = paramObj->GetProperty("selectedTextStyle");
383
384 if (!disappearProperty->IsNull() && disappearProperty->IsObject()) {
385 JSRef<JSObject> disappearObj = JSRef<JSObject>::Cast(disappearProperty);
386 JSDatePicker::ParseTextStyle(disappearObj, result.disappearTextStyle_, "disappearTextStyle");
387 }
388
389 if (!normalProperty->IsNull() && normalProperty->IsObject()) {
390 JSRef<JSObject> noramlObj = JSRef<JSObject>::Cast(normalProperty);
391 JSDatePicker::ParseTextStyle(noramlObj, result.normalTextStyle_, "textStyle");
392 }
393
394 if (!selectedProperty->IsNull() && selectedProperty->IsObject()) {
395 JSRef<JSObject> selectedObj = JSRef<JSObject>::Cast(selectedProperty);
396 JSDatePicker::ParseTextStyle(selectedObj, result.selectedTextStyle_, "selectedTextStyle");
397 }
398 }
399
IsUserDefinedFontFamily(const std::string & pos)400 void JSDatePicker::IsUserDefinedFontFamily(const std::string& pos)
401 {
402 if (pos == "disappearTextStyle") {
403 DatePickerModel::GetInstance()->HasUserDefinedDisappearFontFamily(true);
404 } else if (pos == "textStyle") {
405 DatePickerModel::GetInstance()->HasUserDefinedNormalFontFamily(true);
406 } else if (pos == "selectedTextStyle") {
407 DatePickerModel::GetInstance()->HasUserDefinedSelectedFontFamily(true);
408 } else if (pos == "disappearTextStyleTime") {
409 TimePickerModel::GetInstance()->HasUserDefinedDisappearFontFamily(true);
410 } else if (pos == "textStyleTime") {
411 TimePickerModel::GetInstance()->HasUserDefinedNormalFontFamily(true);
412 } else if (pos == "selectedTextStyleTime") {
413 TimePickerModel::GetInstance()->HasUserDefinedSelectedFontFamily(true);
414 }
415 }
416
ParseTextStyle(const JSRef<JSObject> & paramObj,NG::PickerTextStyle & textStyle,const std::string & pos)417 void JSDatePicker::ParseTextStyle(
418 const JSRef<JSObject>& paramObj, NG::PickerTextStyle& textStyle, const std::string& pos)
419 {
420 auto fontColor = paramObj->GetProperty("color");
421 auto fontOptions = paramObj->GetProperty("font");
422
423 Color textColor;
424 if (JSViewAbstract::ParseJsColor(fontColor, textColor)) {
425 textStyle.textColor = textColor;
426 }
427
428 if (!fontOptions->IsObject()) {
429 return;
430 }
431 JSRef<JSObject> fontObj = JSRef<JSObject>::Cast(fontOptions);
432 auto fontSize = fontObj->GetProperty("size");
433 auto fontWeight = fontObj->GetProperty("weight");
434 auto fontFamily = fontObj->GetProperty("family");
435 auto fontStyle = fontObj->GetProperty("style");
436 if (fontSize->IsNull() || fontSize->IsUndefined()) {
437 textStyle.fontSize = Dimension(-1);
438 } else {
439 CalcDimension size;
440 if (!ParseJsDimensionFp(fontSize, size) || size.Unit() == DimensionUnit::PERCENT) {
441 textStyle.fontSize = Dimension(-1);
442 } else {
443 textStyle.fontSize = size;
444 }
445 }
446
447 if (!fontWeight->IsNull() && !fontWeight->IsUndefined()) {
448 std::string weight;
449 if (fontWeight->IsNumber()) {
450 weight = std::to_string(fontWeight->ToNumber<int32_t>());
451 } else {
452 ParseJsString(fontWeight, weight);
453 }
454 textStyle.fontWeight = ConvertStrToFontWeight(weight);
455 }
456
457 if (!fontFamily->IsNull() && !fontFamily->IsUndefined()) {
458 std::vector<std::string> families;
459 if (ParseJsFontFamilies(fontFamily, families)) {
460 textStyle.fontFamily = families;
461 IsUserDefinedFontFamily(pos);
462 }
463 }
464
465 if (fontStyle->IsNumber()) {
466 auto style = fontStyle->ToNumber<int32_t>();
467 if (style < 0 || style > 1) {
468 return;
469 }
470 textStyle.fontStyle = static_cast<FontStyle>(style);
471 }
472 }
473
SetDisappearTextStyle(const JSCallbackInfo & info)474 void JSDatePicker::SetDisappearTextStyle(const JSCallbackInfo& info)
475 {
476 auto theme = GetTheme<PickerTheme>();
477 CHECK_NULL_VOID(theme);
478 NG::PickerTextStyle textStyle;
479 if (info[0]->IsObject()) {
480 JSDatePicker::ParseTextStyle(info[0], textStyle, "disappearTextStyle");
481 }
482 DatePickerModel::GetInstance()->SetDisappearTextStyle(theme, textStyle);
483 }
484
SetTextStyle(const JSCallbackInfo & info)485 void JSDatePicker::SetTextStyle(const JSCallbackInfo& info)
486 {
487 auto theme = GetTheme<PickerTheme>();
488 CHECK_NULL_VOID(theme);
489 NG::PickerTextStyle textStyle;
490 if (info[0]->IsObject()) {
491 JSDatePicker::ParseTextStyle(info[0], textStyle, "textStyle");
492 }
493 DatePickerModel::GetInstance()->SetNormalTextStyle(theme, textStyle);
494 }
495
SetEnableHapticFeedback(const JSCallbackInfo & info)496 void JSDatePicker::SetEnableHapticFeedback(const JSCallbackInfo& info)
497 {
498 bool isEnableHapticFeedback = true;
499 if (info[0]->IsBoolean()) {
500 isEnableHapticFeedback = info[0]->ToBoolean();
501 }
502 DatePickerModel::GetInstance()->SetEnableHapticFeedback(isEnableHapticFeedback);
503 }
504
SetSelectedTextStyle(const JSCallbackInfo & info)505 void JSDatePicker::SetSelectedTextStyle(const JSCallbackInfo& info)
506 {
507 auto theme = GetTheme<PickerTheme>();
508 CHECK_NULL_VOID(theme);
509 NG::PickerTextStyle textStyle;
510 if (info[0]->IsObject()) {
511 JSDatePicker::ParseTextStyle(info[0], textStyle, "selectedTextStyle");
512 }
513 DatePickerModel::GetInstance()->SetSelectedTextStyle(theme, textStyle);
514 if (textStyle.textColor.has_value() && theme->IsCircleDial()) {
515 DatePickerModel::GetInstance()->UpdateUserSetSelectColor();
516 }
517 }
518
JsOpacity(const JSCallbackInfo & info)519 void JSDatePicker::JsOpacity(const JSCallbackInfo& info)
520 {
521 JSViewAbstract::JsOpacity(info);
522 DatePickerModel::GetInstance()->HasUserDefinedOpacity();
523 }
524
OnChange(const JSCallbackInfo & info)525 void JSDatePicker::OnChange(const JSCallbackInfo& info)
526 {
527 if (!info[0]->IsFunction()) {
528 return;
529 }
530
531 auto jsFunc = AceType::MakeRefPtr<JsEventFunction<DatePickerChangeEvent, 1>>(
532 JSRef<JSFunc>::Cast(info[0]), DatePickerChangeEventToJSValue);
533 WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
534 auto onChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
535 const BaseEventInfo* info) {
536 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
537 ACE_SCORING_EVENT("datePicker.onChange");
538 PipelineContext::SetCallBackNode(node);
539 const auto* eventInfo = TypeInfoHelper::DynamicCast<DatePickerChangeEvent>(info);
540 func->Execute(*eventInfo);
541 };
542 DatePickerModel::GetInstance()->SetOnChange(std::move(onChange));
543 }
544
OnDateChange(const JSCallbackInfo & info)545 void JSDatePicker::OnDateChange(const JSCallbackInfo& info)
546 {
547 if (!info[0]->IsFunction()) {
548 return;
549 }
550 auto jsFunc = AceType::MakeRefPtr<JsEventFunction<DatePickerChangeEvent, 1>>(
551 JSRef<JSFunc>::Cast(info[0]), DatePickerDateChangeEventToJSValue);
552 WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
553 auto onDateChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
554 const BaseEventInfo* info) {
555 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
556 ACE_SCORING_EVENT("datePicker.onDateChange");
557 PipelineContext::SetCallBackNode(node);
558 const auto* eventInfo = TypeInfoHelper::DynamicCast<DatePickerChangeEvent>(info);
559 func->Execute(*eventInfo);
560 };
561 DatePickerModel::GetInstance()->SetOnDateChange(std::move(onDateChange));
562 }
563
OnChange(const JSCallbackInfo & info)564 void JSTimePicker::OnChange(const JSCallbackInfo& info)
565 {
566 if (!info[0]->IsFunction()) {
567 return;
568 }
569
570 auto jsFunc = AceType::MakeRefPtr<JsEventFunction<DatePickerChangeEvent, 1>>(
571 JSRef<JSFunc>::Cast(info[0]), DatePickerChangeEventToJSValue);
572 WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
573 auto onChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
574 const BaseEventInfo* index) {
575 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
576 ACE_SCORING_EVENT("datePicker.onChange");
577 PipelineContext::SetCallBackNode(node);
578 const auto* eventInfo = TypeInfoHelper::DynamicCast<DatePickerChangeEvent>(index);
579 func->Execute(*eventInfo);
580 };
581 TimePickerModel::GetInstance()->SetOnChange(std::move(onChange));
582 }
583
OnEnterSelectedArea(const JSCallbackInfo & info)584 void JSTimePicker::OnEnterSelectedArea(const JSCallbackInfo& info)
585 {
586 if (!info[0]->IsFunction()) {
587 return;
588 }
589
590 auto jsFunc = AceType::MakeRefPtr<JsEventFunction<DatePickerChangeEvent, 1>>(
591 JSRef<JSFunc>::Cast(info[0]), DatePickerChangeEventToJSValue);
592 WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
593 auto onEnterSelectedArea = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
594 const BaseEventInfo* index) {
595 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
596 ACE_SCORING_EVENT("datePicker.onEnterSelectedArea");
597 PipelineContext::SetCallBackNode(node);
598 const auto* eventInfo = TypeInfoHelper::DynamicCast<DatePickerChangeEvent>(index);
599 func->Execute(*eventInfo);
600 };
601 TimePickerModel::GetInstance()->SetOnEnterSelectedArea(std::move(onEnterSelectedArea));
602 }
603
PickerBackgroundColor(const JSCallbackInfo & info)604 void JSDatePicker::PickerBackgroundColor(const JSCallbackInfo& info)
605 {
606 JSViewAbstract::JsBackgroundColor(info);
607
608 if (info.Length() < 1) {
609 return;
610 }
611 Color backgroundColor;
612 if (!ParseJsColor(info[0], backgroundColor)) {
613 return;
614 }
615 DatePickerModel::GetInstance()->SetBackgroundColor(backgroundColor);
616 }
617
ParseDate(const JSRef<JSVal> & dateVal)618 PickerDate JSDatePicker::ParseDate(const JSRef<JSVal>& dateVal)
619 {
620 auto pickerDate = PickerDate();
621 if (!dateVal->IsObject()) {
622 return pickerDate;
623 }
624 auto dateObj = JSRef<JSObject>::Cast(dateVal);
625 auto yearFuncJsVal = dateObj->GetProperty("getFullYear");
626 auto monthFuncJsVal = dateObj->GetProperty("getMonth");
627 auto dateFuncJsVal = dateObj->GetProperty("getDate");
628 if (!(yearFuncJsVal->IsFunction() && monthFuncJsVal->IsFunction() && dateFuncJsVal->IsFunction())) {
629 return pickerDate;
630 }
631 auto yearFunc = JSRef<JSFunc>::Cast(yearFuncJsVal);
632 auto monthFunc = JSRef<JSFunc>::Cast(monthFuncJsVal);
633 auto dateFunc = JSRef<JSFunc>::Cast(dateFuncJsVal);
634 JSRef<JSVal> year = yearFunc->Call(dateObj);
635 JSRef<JSVal> month = monthFunc->Call(dateObj);
636 JSRef<JSVal> date = dateFunc->Call(dateObj);
637
638 if (year->IsNumber() && month->IsNumber() && date->IsNumber()) {
639 pickerDate.SetYear(year->ToNumber<int32_t>());
640 pickerDate.SetMonth(month->ToNumber<int32_t>() + 1); // 0-11 means 1 to 12 months
641 pickerDate.SetDay(date->ToNumber<int32_t>());
642 }
643 return pickerDate;
644 }
645
ParseTime(const JSRef<JSVal> & timeVal)646 PickerTime JSDatePicker::ParseTime(const JSRef<JSVal>& timeVal)
647 {
648 auto pickerTime = PickerTime();
649 if (!timeVal->IsObject()) {
650 return pickerTime;
651 }
652 auto timeObj = JSRef<JSObject>::Cast(timeVal);
653 auto hourFuncJsVal = timeObj->GetProperty("getHours");
654 auto minuteFuncJsVal = timeObj->GetProperty("getMinutes");
655 auto secondFuncJsVal = timeObj->GetProperty("getSeconds");
656 if (!(hourFuncJsVal->IsFunction() && minuteFuncJsVal->IsFunction() && secondFuncJsVal->IsFunction())) {
657 return pickerTime;
658 }
659 auto hourFunc = JSRef<JSFunc>::Cast(hourFuncJsVal);
660 auto minuteFunc = JSRef<JSFunc>::Cast(minuteFuncJsVal);
661 auto secondFunc = JSRef<JSFunc>::Cast(secondFuncJsVal);
662 JSRef<JSVal> hour = hourFunc->Call(timeObj);
663 JSRef<JSVal> minute = minuteFunc->Call(timeObj);
664 JSRef<JSVal> second = secondFunc->Call(timeObj);
665
666 if (hour->IsNumber() && minute->IsNumber() && second->IsNumber()) {
667 pickerTime.SetHour(hour->ToNumber<int32_t>());
668 pickerTime.SetMinute(minute->ToNumber<int32_t>());
669 pickerTime.SetSecond(second->ToNumber<int32_t>());
670 }
671 return pickerTime;
672 }
673
ParseSelectedDateTimeObject(const JSCallbackInfo & info,const JSRef<JSObject> & selectedObject,bool isDatePicker)674 void ParseSelectedDateTimeObject(const JSCallbackInfo& info, const JSRef<JSObject>& selectedObject, bool isDatePicker)
675 {
676 JSRef<JSVal> changeEventVal = selectedObject->GetProperty("changeEvent");
677 if (changeEventVal->IsUndefined() || !changeEventVal->IsFunction()) {
678 return;
679 }
680 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(changeEventVal));
681 WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
682 auto changeEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
683 node = targetNode, isDatePicker](const BaseEventInfo* info) {
684 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
685 ACE_SCORING_EVENT("DatePicker.SelectedDateTimeChangeEvent");
686 const auto* eventInfo = TypeInfoHelper::DynamicCast<DatePickerChangeEvent>(info);
687 CHECK_NULL_VOID(eventInfo);
688 auto selectedStr = eventInfo->GetSelectedStr();
689 auto sourceJson = JsonUtil::ParseJsonString(selectedStr);
690 if (!sourceJson || sourceJson->IsNull()) {
691 return;
692 }
693
694 auto dateObj = JSDatePickerDialog::GetDateObj(sourceJson, isDatePicker);
695 PipelineContext::SetCallBackNode(node);
696 func->ExecuteJS(1, &dateObj);
697 };
698 if (isDatePicker) {
699 DatePickerModel::GetInstance()->SetChangeEvent(std::move(changeEvent));
700 } else {
701 TimePickerModel::GetInstance()->SetChangeEvent(std::move(changeEvent));
702 }
703 }
704
CreateDatePicker(const JSCallbackInfo & info,const JSRef<JSObject> & paramObj)705 void JSDatePicker::CreateDatePicker(const JSCallbackInfo& info, const JSRef<JSObject>& paramObj)
706 {
707 JSRef<JSVal> startDate;
708 JSRef<JSVal> endDate;
709 JSRef<JSVal> selectedDate;
710 JSRef<JSVal> mode;
711 if (!paramObj->IsUndefined()) {
712 startDate = paramObj->GetProperty("start");
713 endDate = paramObj->GetProperty("end");
714 selectedDate = paramObj->GetProperty("selected");
715 mode = paramObj->GetProperty("mode");
716 }
717 ParseStartEndDate(startDate, endDate);
718
719 PickerDate parseSelectedDate = PickerDate::Current();
720 if (selectedDate->IsObject()) {
721 JSRef<JSObject> selectedDateObj = JSRef<JSObject>::Cast(selectedDate);
722 JSRef<JSVal> changeEventVal = selectedDateObj->GetProperty("changeEvent");
723 if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
724 ParseSelectedDateTimeObject(info, selectedDateObj, true);
725 parseSelectedDate = ParseDate(selectedDateObj->GetProperty("value"));
726 } else {
727 parseSelectedDate = ParseDate(selectedDate);
728 }
729 }
730 DatePickerModel::GetInstance()->SetSelectedDate(parseSelectedDate);
731
732 ParseDatePickerMode(mode);
733 SetDefaultAttributes();
734 }
735
SetDefaultAttributes()736 void JSDatePicker::SetDefaultAttributes()
737 {
738 auto theme = GetTheme<PickerTheme>();
739 CHECK_NULL_VOID(theme);
740 NG::PickerTextStyle textStyle;
741 auto selectedStyle = theme->GetOptionStyle(true, false);
742 textStyle.fontSize = selectedStyle.GetFontSize();
743 textStyle.fontWeight = selectedStyle.GetFontWeight();
744 DatePickerModel::GetInstance()->SetSelectedTextStyle(theme, textStyle);
745
746 auto disappearStyle = theme->GetDisappearOptionStyle();
747 textStyle.fontSize = disappearStyle.GetFontSize();
748 textStyle.fontWeight = disappearStyle.GetFontWeight();
749 DatePickerModel::GetInstance()->SetDisappearTextStyle(theme, textStyle);
750
751 auto normalStyle = theme->GetOptionStyle(false, false);
752 textStyle.fontSize = normalStyle.GetFontSize();
753 textStyle.fontWeight = normalStyle.GetFontWeight();
754 DatePickerModel::GetInstance()->SetNormalTextStyle(theme, textStyle);
755 }
756
ParseDatePickerMode(JSRef<JSVal> mode)757 void JSDatePicker::ParseDatePickerMode(JSRef<JSVal> mode)
758 {
759 auto datePickerMode = DatePickerMode::DATE;
760 if (!mode->IsNull() && mode->IsNumber()) {
761 auto parseMode = mode->ToNumber<int32_t>();
762 if (parseMode >= static_cast<int32_t>(DatePickerMode::DATE) &&
763 parseMode <= static_cast<int32_t>(DatePickerMode::MONTH_AND_DAY)) {
764 datePickerMode = static_cast<DatePickerMode>(parseMode);
765 }
766 }
767 DatePickerModel::GetInstance()->SetMode(datePickerMode);
768 }
769
ParseStartEndDate(JSRef<JSVal> startDate,JSRef<JSVal> endDate)770 void JSDatePicker::ParseStartEndDate(JSRef<JSVal> startDate, JSRef<JSVal> endDate)
771 {
772 auto theme = GetTheme<PickerTheme>();
773 CHECK_NULL_VOID(theme);
774 auto parseStartDate = ParseDate(startDate);
775 auto parseEndDate = ParseDate(endDate);
776 if (parseStartDate.GetYear() <= 0) {
777 parseStartDate = theme->GetDefaultStartDate();
778 }
779 if (parseEndDate.GetYear() <= 0) {
780 parseEndDate = theme->GetDefaultEndDate();
781 }
782 auto startDays = parseStartDate.ToDays();
783 auto endDays = parseEndDate.ToDays();
784 if (startDays > endDays) {
785 parseStartDate = theme->GetDefaultStartDate();
786 parseEndDate = theme->GetDefaultEndDate();
787 }
788 DatePickerModel::GetInstance()->CreateDatePicker(theme);
789 if (startDate->IsObject()) {
790 DatePickerModel::GetInstance()->SetStartDate(parseStartDate);
791 }
792 if (endDate->IsObject()) {
793 DatePickerModel::GetInstance()->SetEndDate(parseEndDate);
794 }
795 }
796
CreateTimePicker(const JSCallbackInfo & info,const JSRef<JSObject> & paramObj)797 void JSDatePicker::CreateTimePicker(const JSCallbackInfo& info, const JSRef<JSObject>& paramObj)
798 {
799 auto theme = GetTheme<PickerTheme>();
800 CHECK_NULL_VOID(theme);
801 DatePickerModel::GetInstance()->CreateTimePicker(theme);
802 auto selectedTime = paramObj->GetProperty("selected");
803 if (selectedTime->IsObject()) {
804 JSRef<JSObject> selectedTimeObj = JSRef<JSObject>::Cast(selectedTime);
805 JSRef<JSVal> changeEventVal = selectedTimeObj->GetProperty("changeEvent");
806 if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
807 ParseSelectedDateTimeObject(info, selectedTimeObj, true);
808 auto parseSelectedTime = ParseTime(selectedTimeObj->GetProperty("value"));
809 DatePickerModel::GetInstance()->SetSelectedTime(parseSelectedTime);
810 } else {
811 DatePickerModel::GetInstance()->SetSelectedTime(ParseTime(selectedTime));
812 }
813 }
814 }
815
JSBind(BindingTarget globalObj)816 void JSDatePickerDialog::JSBind(BindingTarget globalObj)
817 {
818 JSClass<JSDatePickerDialog>::Declare("DatePickerDialog");
819 JSClass<JSDatePickerDialog>::StaticMethod("show", &JSDatePickerDialog::Show);
820
821 JSClass<JSDatePickerDialog>::Bind<>(globalObj);
822 }
823
DatePickerDialogAppearEvent(const JSCallbackInfo & info,PickerDialogEvent & pickerDialogEvent)824 void DatePickerDialogAppearEvent(const JSCallbackInfo& info, PickerDialogEvent& pickerDialogEvent)
825 {
826 std::function<void()> didAppearEvent;
827 std::function<void()> willAppearEvent;
828 if (info.Length() == 0 || !info[0]->IsObject()) {
829 return;
830 }
831 auto paramObject = JSRef<JSObject>::Cast(info[0]);
832 WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
833 auto onDidAppear = paramObject->GetProperty("onDidAppear");
834 if (!onDidAppear->IsUndefined() && onDidAppear->IsFunction()) {
835 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onDidAppear));
836 didAppearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode]() {
837 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
838 ACE_SCORING_EVENT("DatePickerDialog.onDidAppear");
839 PipelineContext::SetCallBackNode(node);
840 func->Execute();
841 };
842 }
843 auto onWillAppear = paramObject->GetProperty("onWillAppear");
844 if (!onWillAppear->IsUndefined() && onWillAppear->IsFunction()) {
845 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onWillAppear));
846 willAppearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode]() {
847 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
848 ACE_SCORING_EVENT("DatePickerDialog.onWillAppear");
849 PipelineContext::SetCallBackNode(node);
850 func->Execute();
851 };
852 }
853 pickerDialogEvent.onDidAppear = std::move(didAppearEvent);
854 pickerDialogEvent.onWillAppear = std::move(willAppearEvent);
855 }
856
DatePickerDialogDisappearEvent(const JSCallbackInfo & info,PickerDialogEvent & pickerDialogEvent)857 void DatePickerDialogDisappearEvent(const JSCallbackInfo& info, PickerDialogEvent& pickerDialogEvent)
858 {
859 std::function<void()> didDisappearEvent;
860 std::function<void()> willDisappearEvent;
861 if (info.Length() == 0 || !info[0]->IsObject()) {
862 return;
863 }
864 auto paramObject = JSRef<JSObject>::Cast(info[0]);
865 WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
866 auto onDidDisappear = paramObject->GetProperty("onDidDisappear");
867 if (!onDidDisappear->IsUndefined() && onDidDisappear->IsFunction()) {
868 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onDidDisappear));
869 didDisappearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode]() {
870 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
871 ACE_SCORING_EVENT("DatePickerDialog.onDidDisappear");
872 PipelineContext::SetCallBackNode(node);
873 func->Execute();
874 };
875 }
876 auto onWillDisappear = paramObject->GetProperty("onWillDisappear");
877 if (!onWillDisappear->IsUndefined() && onWillDisappear->IsFunction()) {
878 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onWillDisappear));
879 willDisappearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode]() {
880 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
881 ACE_SCORING_EVENT("DatePickerDialog.onWillDisappear");
882 PipelineContext::SetCallBackNode(node);
883 func->Execute();
884 };
885 }
886 pickerDialogEvent.onDidDisappear = std::move(didDisappearEvent);
887 pickerDialogEvent.onWillDisappear = std::move(willDisappearEvent);
888 }
889
GetDateChangeEvent(const JSRef<JSObject> & paramObject,const JSCallbackInfo & info,const DatePickerType & pickerType,const WeakPtr<NG::FrameNode> & frameNode)890 std::function<void(const std::string&)> JSDatePickerDialog::GetDateChangeEvent(const JSRef<JSObject>& paramObject,
891 const JSCallbackInfo& info, const DatePickerType& pickerType, const WeakPtr<NG::FrameNode>& frameNode)
892 {
893 std::function<void(const std::string&)> dateChangeEvent;
894 auto onDateChange = paramObject->GetProperty("onDateChange");
895 if (!onDateChange->IsUndefined() && onDateChange->IsFunction()) {
896 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onDateChange));
897 dateChangeEvent = [execCtx = info.GetExecutionContext(), type = pickerType, func = std::move(jsFunc),
898 node = frameNode](const std::string& info) {
899 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
900 ACE_SCORING_EVENT("DatePickerDialog.onDateChange");
901 auto selectedJson = JsonUtil::ParseJsonString(info);
902 if (!selectedJson || selectedJson->IsNull()) {
903 return;
904 }
905 auto dateObj = GetDateObj(selectedJson);
906 PipelineContext::SetCallBackNode(node);
907 func->ExecuteJS(1, &dateObj);
908 };
909 }
910 return dateChangeEvent;
911 }
912
GetDateAcceptEvent(const JSRef<JSObject> & paramObject,const JSCallbackInfo & info,const DatePickerType & pickerType,const WeakPtr<NG::FrameNode> & frameNode)913 std::function<void(const std::string&)> JSDatePickerDialog::GetDateAcceptEvent(const JSRef<JSObject>& paramObject,
914 const JSCallbackInfo& info, const DatePickerType& pickerType, const WeakPtr<NG::FrameNode>& frameNode)
915 {
916 std::function<void(const std::string&)> dateAcceptEvent;
917 auto onDateAccept = paramObject->GetProperty("onDateAccept");
918 if (!onDateAccept->IsUndefined() && onDateAccept->IsFunction()) {
919 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onDateAccept));
920 dateAcceptEvent = [execCtx = info.GetExecutionContext(), type = pickerType, func = std::move(jsFunc),
921 node = frameNode](const std::string& info) {
922 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
923 ACE_SCORING_EVENT("DatePickerDialog.onDateAccept");
924 auto selectedJson = JsonUtil::ParseJsonString(info);
925 if (!selectedJson || selectedJson->IsNull()) {
926 return;
927 }
928 auto dateObj = GetDateObj(selectedJson);
929 PipelineContext::SetCallBackNode(node);
930 func->ExecuteJS(1, &dateObj);
931 };
932 }
933 return dateAcceptEvent;
934 }
935
GetDateObj(const std::unique_ptr<JsonValue> & selectedJson,bool isDatePicker)936 JsiRef<JsiValue> JSDatePickerDialog::GetDateObj(const std::unique_ptr<JsonValue>& selectedJson, bool isDatePicker)
937 {
938 std::tm dateTime {};
939 auto year = selectedJson->GetValue("year");
940 if (year && year->IsNumber()) {
941 dateTime.tm_year = year->GetInt() - 1900; // local date start from 1900
942 }
943 auto month = selectedJson->GetValue("month");
944 if (month && month->IsNumber()) {
945 dateTime.tm_mon = month->GetInt();
946 }
947 auto day = selectedJson->GetValue("day");
948 if (day && day->IsNumber()) {
949 dateTime.tm_mday = day->GetInt();
950 }
951 auto hour = selectedJson->GetValue("hour");
952 if (hour && hour->IsNumber()) {
953 dateTime.tm_hour = hour->GetInt();
954 }
955 auto minute = selectedJson->GetValue("minute");
956 if (minute && minute->IsNumber()) {
957 dateTime.tm_min = minute->GetInt();
958 }
959 auto second = selectedJson->GetValue("second");
960 if (second && second->IsNumber()) {
961 dateTime.tm_sec = second->GetInt();
962 }
963 if (!isDatePicker) {
964 auto milliseconds = Date::GetMilliSecondsByDateTime(dateTime);
965 auto dateObj = JSDate::New(milliseconds);
966 return dateObj;
967 }
968 auto timestamp = std::chrono::system_clock::from_time_t(std::mktime(&dateTime));
969 auto duration = timestamp.time_since_epoch();
970 auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
971 auto dateObj = JSDate::New(milliseconds);
972 return dateObj;
973 }
974
GetChangeEvent(const JSRef<JSObject> & paramObject,const JSCallbackInfo & info,const DatePickerType & pickerType,const WeakPtr<NG::FrameNode> & frameNode)975 std::function<void(const std::string&)> JSDatePickerDialog::GetChangeEvent(const JSRef<JSObject>& paramObject,
976 const JSCallbackInfo& info, const DatePickerType& pickerType, const WeakPtr<NG::FrameNode>& frameNode)
977 {
978 std::function<void(const std::string&)> changeEvent;
979 auto onChange = paramObject->GetProperty("onChange");
980 if (!onChange->IsUndefined() && onChange->IsFunction()) {
981 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onChange));
982 changeEvent = [execCtx = info.GetExecutionContext(), type = pickerType, func = std::move(jsFunc),
983 node = frameNode](const std::string& info) {
984 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
985 std::vector<std::string> keys;
986 keys = { "year", "month", "day" };
987 ACE_SCORING_EVENT("DatePickerDialog.onChange");
988 PipelineContext::SetCallBackNode(node);
989 func->Execute(keys, info);
990 };
991 }
992 return changeEvent;
993 }
994
GetAcceptEvent(const JSRef<JSObject> & paramObject,const JSCallbackInfo & info,const WeakPtr<NG::FrameNode> & frameNode)995 std::function<void(const std::string&)> JSDatePickerDialog::GetAcceptEvent(
996 const JSRef<JSObject>& paramObject, const JSCallbackInfo& info, const WeakPtr<NG::FrameNode>& frameNode)
997 {
998 std::function<void(const std::string&)> acceptEvent;
999 auto onAccept = paramObject->GetProperty("onAccept");
1000 if (!onAccept->IsUndefined() && onAccept->IsFunction()) {
1001 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onAccept));
1002 acceptEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode](
1003 const std::string& info) {
1004 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1005 std::vector<std::string> keys = { "year", "month", "day", "hour", "minute", "second" };
1006 ACE_SCORING_EVENT("DatePickerDialog.onAccept");
1007 PipelineContext::SetCallBackNode(node);
1008 func->Execute(keys, info);
1009 };
1010 }
1011 return acceptEvent;
1012 }
1013
GetCancelEvent(const JSRef<JSObject> & paramObject,const JSCallbackInfo & info,const WeakPtr<NG::FrameNode> & frameNode)1014 std::function<void()> JSDatePickerDialog::GetCancelEvent(
1015 const JSRef<JSObject>& paramObject, const JSCallbackInfo& info, const WeakPtr<NG::FrameNode>& frameNode)
1016 {
1017 std::function<void()> cancelEvent;
1018 auto onCancel = paramObject->GetProperty("onCancel");
1019 if (!onCancel->IsUndefined() && onCancel->IsFunction()) {
1020 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onCancel));
1021 cancelEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode]() {
1022 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1023 ACE_SCORING_EVENT("DatePickerDialog.onCancel");
1024 PipelineContext::SetCallBackNode(node);
1025 func->Execute();
1026 };
1027 }
1028 return cancelEvent;
1029 }
1030
UpdateLunarSwitchSettingData(const JSRef<JSObject> & paramObject,NG::DatePickerSettingData & settingData)1031 void JSDatePickerDialog::UpdateLunarSwitchSettingData(
1032 const JSRef<JSObject>& paramObject, NG::DatePickerSettingData& settingData)
1033 {
1034 auto selectedColorValue = paramObject->GetProperty("selectedColor");
1035 auto unselectedColorValue = paramObject->GetProperty("unselectedColor");
1036 auto strokeColorValue = paramObject->GetProperty("strokeColor");
1037 Color selectedColor;
1038 if (JSViewAbstract::ParseJsColor(selectedColorValue, selectedColor)) {
1039 settingData.checkboxSettingData.selectedColor = selectedColor;
1040 }
1041 Color unselectedColor;
1042 if (JSViewAbstract::ParseJsColor(unselectedColorValue, unselectedColor)) {
1043 settingData.checkboxSettingData.unselectedColor = unselectedColor;
1044 }
1045 Color strokeColor;
1046 if (JSViewAbstract::ParseJsColor(strokeColorValue, strokeColor)) {
1047 settingData.checkboxSettingData.strokeColor = strokeColor;
1048 }
1049 }
1050
UpdateDatePickerSettingData(const JSRef<JSObject> & paramObject,NG::DatePickerSettingData & settingData)1051 void JSDatePickerDialog::UpdateDatePickerSettingData(
1052 const JSRef<JSObject>& paramObject, NG::DatePickerSettingData& settingData)
1053 {
1054 auto lunar = paramObject->GetProperty("lunar");
1055 auto lunarSwitch = paramObject->GetProperty("lunarSwitch");
1056 auto sTime = paramObject->GetProperty("showTime");
1057 auto useMilitary = paramObject->GetProperty("useMilitaryTime");
1058 settingData.isLunar = lunar->ToBoolean();
1059 settingData.lunarswitch = lunarSwitch->ToBoolean();
1060 if (settingData.lunarswitch) {
1061 auto lunarSwitchStyle = paramObject->GetProperty("lunarSwitchStyle");
1062 if ((!lunarSwitchStyle->IsUndefined()) && lunarSwitchStyle->IsObject()) {
1063 auto style = JSRef<JSObject>::Cast(lunarSwitchStyle);
1064 UpdateLunarSwitchSettingData(style, settingData);
1065 }
1066 }
1067 auto enableHapticFeedbackValue = paramObject->GetProperty("enableHapticFeedback");
1068 if (enableHapticFeedbackValue->IsBoolean()) {
1069 settingData.isEnableHapticFeedback = enableHapticFeedbackValue->ToBoolean();
1070 }
1071 settingData.showTime = sTime->ToBoolean();
1072 settingData.useMilitary = useMilitary->ToBoolean();
1073
1074 auto mode = paramObject->GetProperty("mode");
1075 auto datePickerMode = DatePickerMode::DATE;
1076 if (!mode->IsNull() && mode->IsNumber()) {
1077 auto parseMode = mode->ToNumber<int32_t>();
1078 if (parseMode >= static_cast<int32_t>(DatePickerMode::DATE) &&
1079 parseMode <= static_cast<int32_t>(DatePickerMode::MONTH_AND_DAY)) {
1080 datePickerMode = static_cast<DatePickerMode>(parseMode);
1081 }
1082 }
1083 settingData.mode = datePickerMode;
1084
1085 auto dateTimeOptionsValue = paramObject->GetProperty("dateTimeOptions");
1086 if (dateTimeOptionsValue->IsObject()) {
1087 auto dateTimeOptionsObj = JSRef<JSObject>::Cast(dateTimeOptionsValue);
1088 JSDatePickerDialog::ParseDateTimeOptions(dateTimeOptionsObj, settingData.dateTimeOptions);
1089 }
1090 JSDatePicker::ParseTextProperties(paramObject, settingData.properties);
1091 }
1092
UpdatePickerDialogTimeInfo(const JSRef<JSObject> & paramObject,PickerDialogInfo & pickerDialog)1093 void JSDatePickerDialog::UpdatePickerDialogTimeInfo(const JSRef<JSObject>& paramObject, PickerDialogInfo& pickerDialog)
1094 {
1095 auto theme = GetTheme<PickerTheme>();
1096 CHECK_NULL_VOID(theme);
1097
1098 auto startDate = paramObject->GetProperty("start");
1099 if (startDate->IsObject()) {
1100 pickerDialog.isStartDate = true;
1101 }
1102 auto endDate = paramObject->GetProperty("end");
1103 if (endDate->IsObject()) {
1104 pickerDialog.isEndDate = true;
1105 }
1106 auto selectedDate = paramObject->GetProperty("selected");
1107 if (selectedDate->IsObject()) {
1108 pickerDialog.isSelectedDate = true;
1109 }
1110 auto parseStartDate = ParseDate(startDate);
1111 auto parseEndDate = ParseDate(endDate);
1112 if (parseStartDate.GetYear() <= 0) {
1113 parseStartDate = theme->GetDefaultStartDate();
1114 }
1115 if (parseEndDate.GetYear() <= 0) {
1116 parseEndDate = theme->GetDefaultEndDate();
1117 }
1118 auto startDays = parseStartDate.ToDays();
1119 auto endDays = parseEndDate.ToDays();
1120 if (startDays > endDays) {
1121 parseStartDate = theme->GetDefaultStartDate();
1122 parseEndDate = theme->GetDefaultEndDate();
1123 }
1124 pickerDialog.parseStartDate = parseStartDate;
1125 pickerDialog.parseEndDate = parseEndDate;
1126 pickerDialog.parseSelectedDate = ParseDate(selectedDate);
1127 pickerDialog.pickerTime = ParseTime(selectedDate);
1128 }
1129
UpdatePickerDialogPositionInfo(const JSRef<JSObject> & paramObject,PickerDialogInfo & pickerDialog)1130 void JSDatePickerDialog::UpdatePickerDialogPositionInfo(
1131 const JSRef<JSObject>& paramObject, PickerDialogInfo& pickerDialog)
1132 {
1133 // Parse alignment
1134 auto alignmentValue = paramObject->GetProperty("alignment");
1135 if (alignmentValue->IsNumber()) {
1136 auto alignment = alignmentValue->ToNumber<int32_t>();
1137 if (alignment >= 0 && alignment < static_cast<int32_t>(DIALOG_ALIGNMENT.size())) {
1138 pickerDialog.alignment = DIALOG_ALIGNMENT[alignment];
1139 }
1140 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1141 if (alignment == static_cast<int32_t>(DialogAlignment::TOP) ||
1142 alignment == static_cast<int32_t>(DialogAlignment::TOP_START) ||
1143 alignment == static_cast<int32_t>(DialogAlignment::TOP_END)) {
1144 pickerDialog.offset = DATEPICKER_OFFSET_DEFAULT_TOP;
1145 }
1146 }
1147 }
1148
1149 // Parse offset
1150 auto offsetValue = paramObject->GetProperty("offset");
1151 if (offsetValue->IsObject()) {
1152 auto offsetObj = JSRef<JSObject>::Cast(offsetValue);
1153 CalcDimension dx;
1154 auto dxValue = offsetObj->GetProperty("dx");
1155 ParseJsDimensionVp(dxValue, dx);
1156 CalcDimension dy;
1157 auto dyValue = offsetObj->GetProperty("dy");
1158 ParseJsDimensionVp(dyValue, dy);
1159 pickerDialog.offset = DimensionOffset(dx, dy);
1160 }
1161 }
1162
UpdatePickerDialogInfo(const JSRef<JSObject> & paramObject,PickerDialogInfo & pickerDialog)1163 void JSDatePickerDialog::UpdatePickerDialogInfo(const JSRef<JSObject>& paramObject, PickerDialogInfo& pickerDialog)
1164 {
1165 UpdatePickerDialogTimeInfo(paramObject, pickerDialog);
1166 UpdatePickerDialogPositionInfo(paramObject, pickerDialog);
1167 // Parse maskRect.
1168 auto maskRectValue = paramObject->GetProperty("maskRect");
1169 DimensionRect maskRect;
1170 if (JSViewAbstract::ParseJsDimensionRect(maskRectValue, maskRect)) {
1171 pickerDialog.maskRect = maskRect;
1172 }
1173
1174 auto backgroundColorValue = paramObject->GetProperty("backgroundColor");
1175 Color backgroundColor;
1176 if (JSViewAbstract::ParseJsColor(backgroundColorValue, backgroundColor)) {
1177 pickerDialog.backgroundColor = backgroundColor;
1178 }
1179
1180 auto backgroundBlurStyle = paramObject->GetProperty("backgroundBlurStyle");
1181 if (backgroundBlurStyle->IsNumber()) {
1182 auto blurStyle = backgroundBlurStyle->ToNumber<int32_t>();
1183 if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
1184 blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
1185 pickerDialog.backgroundBlurStyle = blurStyle;
1186 }
1187 }
1188
1189 auto shadowValue = paramObject->GetProperty("shadow");
1190 Shadow shadow;
1191 if ((shadowValue->IsObject() || shadowValue->IsNumber()) && JSViewAbstract::ParseShadowProps(shadowValue, shadow)) {
1192 pickerDialog.shadow = shadow;
1193 }
1194
1195 ParseDatePickerHoverMode(pickerDialog, paramObject);
1196 ParseDatePickerBlurStyleOption(pickerDialog, paramObject);
1197 ParseDatePickerEffectOption(pickerDialog, paramObject);
1198 }
1199
Show(const JSCallbackInfo & info)1200 void JSDatePickerDialog::Show(const JSCallbackInfo& info)
1201 {
1202 auto scopedDelegate = EngineHelper::GetCurrentDelegateSafely();
1203 CHECK_NULL_VOID(scopedDelegate);
1204 if ((Container::LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN) && !info[0]->IsObject()) ||
1205 (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN) && !info[0]->IsObject()
1206 && !info[0]->IsEmpty())) {
1207 return;
1208 }
1209
1210 auto paramObject = info[0]->IsEmpty() ? (JSRef<JSObject>::New()) : JSRef<JSObject>::Cast(info[0]);
1211 DatePickerType pickerType = DatePickerType::DATE;
1212 auto type = paramObject->GetProperty("type");
1213 if (type->IsNumber()) {
1214 pickerType = static_cast<DatePickerType>(type->ToNumber<int32_t>());
1215 }
1216 std::function<void()> cancelEvent;
1217 std::function<void(const std::string&)> acceptEvent;
1218 std::function<void(const std::string&)> changeEvent;
1219 std::function<void(const std::string&)> dateChangeEvent;
1220 std::function<void(const std::string&)> dateAcceptEvent;
1221 WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1222 changeEvent = GetChangeEvent(paramObject, info, pickerType, frameNode);
1223 acceptEvent = GetAcceptEvent(paramObject, info, frameNode);
1224 cancelEvent = GetCancelEvent(paramObject, info, frameNode);
1225 dateChangeEvent = GetDateChangeEvent(paramObject, info, pickerType, frameNode);
1226 dateAcceptEvent = GetDateAcceptEvent(paramObject, info, pickerType, frameNode);
1227 NG::DatePickerSettingData settingData;
1228 UpdateDatePickerSettingData(paramObject, settingData);
1229 PickerDialogInfo pickerDialog;
1230 UpdatePickerDialogInfo(paramObject, pickerDialog);
1231
1232 auto buttonInfos = ParseButtonStyles(paramObject);
1233 PickerDialogEvent pickerDialogEvent { nullptr, nullptr, nullptr, nullptr };
1234 DatePickerDialogAppearEvent(info, pickerDialogEvent);
1235 DatePickerDialogDisappearEvent(info, pickerDialogEvent);
1236 DatePickerDialogModel::GetInstance()->SetDatePickerDialogShow(pickerDialog, settingData, std::move(cancelEvent),
1237 std::move(acceptEvent), std::move(changeEvent), std::move(dateAcceptEvent), std::move(dateChangeEvent),
1238 pickerType, pickerDialogEvent, buttonInfos);
1239 }
1240
DatePickerDialogShow(const JSRef<JSObject> & paramObj,const std::map<std::string,NG::DialogEvent> & dialogEvent,const std::map<std::string,NG::DialogGestureEvent> & dialogCancelEvent)1241 void JSDatePickerDialog::DatePickerDialogShow(const JSRef<JSObject>& paramObj,
1242 const std::map<std::string, NG::DialogEvent>& dialogEvent,
1243 const std::map<std::string, NG::DialogGestureEvent>& dialogCancelEvent)
1244 {
1245 auto container = Container::CurrentSafely();
1246 if (!container) {
1247 return;
1248 }
1249 auto pipelineContext = AccessibilityManager::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
1250 if (!pipelineContext) {
1251 return;
1252 }
1253
1254 auto executor = pipelineContext->GetTaskExecutor();
1255 if (!executor) {
1256 return;
1257 }
1258
1259 NG::DatePickerSettingData settingData;
1260 auto startDate = paramObj->GetProperty("start");
1261 auto endDate = paramObj->GetProperty("end");
1262 auto selectedDate = paramObj->GetProperty("selected");
1263 auto lunar = paramObj->GetProperty("lunar");
1264 auto sTime = paramObj->GetProperty("showTime");
1265 auto useMilitary = paramObj->GetProperty("useMilitaryTime");
1266 settingData.isLunar = lunar->ToBoolean();
1267 settingData.showTime = sTime->ToBoolean();
1268 settingData.useMilitary = useMilitary->ToBoolean();
1269 auto parseStartDate = ParseDate(startDate);
1270 auto parseEndDate = ParseDate(endDate);
1271 auto parseSelectedDate = ParseDate(selectedDate);
1272
1273 auto theme = GetTheme<DialogTheme>();
1274 CHECK_NULL_VOID(theme);
1275
1276 DialogProperties properties;
1277 properties.alignment = theme->GetAlignment();
1278 if (properties.alignment == DialogAlignment::BOTTOM &&
1279 Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_ELEVEN)) {
1280 properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx()));
1281 }
1282 properties.customStyle = false;
1283 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1284 properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx()));
1285 }
1286
1287 std::map<std::string, PickerDate> datePickerProperty;
1288 std::map<std::string, PickerTime> timePickerProperty;
1289 if (startDate->IsObject()) {
1290 settingData.datePickerProperty["start"] = parseStartDate;
1291 }
1292 if (endDate->IsObject()) {
1293 settingData.datePickerProperty["end"] = parseEndDate;
1294 }
1295 if (selectedDate->IsObject()) {
1296 settingData.datePickerProperty["selected"] = parseSelectedDate;
1297 settingData.timePickerProperty["selected"] = ParseTime(selectedDate);
1298 }
1299 auto enableHapticFeedbackValue = paramObj->GetProperty("enableHapticFeedback");
1300 if (enableHapticFeedbackValue->IsBoolean()) {
1301 settingData.isEnableHapticFeedback = enableHapticFeedbackValue->ToBoolean();
1302 }
1303
1304 JSDatePicker::ParseTextProperties(paramObj, settingData.properties);
1305 auto context = AccessibilityManager::DynamicCast<NG::PipelineContext>(pipelineContext);
1306 auto overlayManager = context ? context->GetOverlayManager() : nullptr;
1307 executor->PostTask(
1308 [properties, settingData, dialogEvent, dialogCancelEvent, weak = WeakPtr<NG::OverlayManager>(overlayManager)] {
1309 auto overlayManager = weak.Upgrade();
1310 CHECK_NULL_VOID(overlayManager);
1311 overlayManager->ShowDateDialog(properties, settingData, dialogEvent, dialogCancelEvent);
1312 },
1313 TaskExecutor::TaskType::UI, "ArkUIDialogShowDatePicker",
1314 TaskExecutor::GetPriorityTypeWithCheck(PriorityType::VIP));
1315 }
1316
CreateDatePicker(RefPtr<Component> & component,const JSRef<JSObject> & paramObj)1317 void JSDatePickerDialog::CreateDatePicker(RefPtr<Component>& component, const JSRef<JSObject>& paramObj)
1318 {
1319 auto datePicker = AceType::MakeRefPtr<PickerDateComponent>();
1320 auto startDate = paramObj->GetProperty("start");
1321 auto endDate = paramObj->GetProperty("end");
1322 auto selectedDate = paramObj->GetProperty("selected");
1323 auto lunar = paramObj->GetProperty("lunar");
1324 bool isLunar = lunar->ToBoolean();
1325 auto parseStartDate = ParseDate(startDate);
1326 auto parseEndDate = ParseDate(endDate);
1327 auto parseSelectedDate = ParseDate(selectedDate);
1328 auto startDays = parseStartDate.ToDays();
1329 auto endDays = parseEndDate.ToDays();
1330 if (startDays > endDays) {
1331 parseStartDate.SetYear(0);
1332 parseEndDate.SetYear(0);
1333 }
1334 if (startDate->IsObject()) {
1335 datePicker->SetStartDate(parseStartDate);
1336 }
1337 if (endDate->IsObject()) {
1338 datePicker->SetEndDate(parseEndDate);
1339 }
1340 if (selectedDate->IsObject()) {
1341 datePicker->SetSelectedDate(parseSelectedDate);
1342 }
1343 datePicker->SetIsDialog(true);
1344 datePicker->SetIsCreateDialogComponent(true);
1345 datePicker->SetShowLunar(isLunar);
1346
1347 component = datePicker;
1348 }
1349
CreateTimePicker(RefPtr<Component> & component,const JSRef<JSObject> & paramObj)1350 void JSDatePickerDialog::CreateTimePicker(RefPtr<Component>& component, const JSRef<JSObject>& paramObj)
1351 {
1352 auto timePicker = AceType::MakeRefPtr<PickerTimeComponent>();
1353 auto selectedTime = paramObj->GetProperty("selected");
1354 auto useMilitaryTime = paramObj->GetProperty("useMilitaryTime");
1355 bool isUseMilitaryTime = useMilitaryTime->ToBoolean();
1356 if (selectedTime->IsObject()) {
1357 timePicker->SetSelectedTime(ParseTime(selectedTime));
1358 }
1359 timePicker->SetIsDialog(true);
1360 timePicker->SetIsCreateDialogComponent(true);
1361 timePicker->SetHour24(isUseMilitaryTime);
1362 component = timePicker;
1363 }
1364
ParseDate(const JSRef<JSVal> & dateVal)1365 PickerDate JSDatePickerDialog::ParseDate(const JSRef<JSVal>& dateVal)
1366 {
1367 auto pickerDate = PickerDate();
1368 if (!dateVal->IsObject()) {
1369 return pickerDate;
1370 }
1371 auto dateObj = JSRef<JSObject>::Cast(dateVal);
1372 auto yearFuncJsVal = dateObj->GetProperty("getFullYear");
1373 auto monthFuncJsVal = dateObj->GetProperty("getMonth");
1374 auto dateFuncJsVal = dateObj->GetProperty("getDate");
1375 if (!(yearFuncJsVal->IsFunction() && monthFuncJsVal->IsFunction() && dateFuncJsVal->IsFunction())) {
1376 return pickerDate;
1377 }
1378 auto yearFunc = JSRef<JSFunc>::Cast(yearFuncJsVal);
1379 auto monthFunc = JSRef<JSFunc>::Cast(monthFuncJsVal);
1380 auto dateFunc = JSRef<JSFunc>::Cast(dateFuncJsVal);
1381 JSRef<JSVal> year = yearFunc->Call(dateObj);
1382 JSRef<JSVal> month = monthFunc->Call(dateObj);
1383 JSRef<JSVal> date = dateFunc->Call(dateObj);
1384
1385 if (year->IsNumber() && month->IsNumber() && date->IsNumber()) {
1386 pickerDate.SetYear(year->ToNumber<int32_t>());
1387 pickerDate.SetMonth(month->ToNumber<int32_t>() + 1); // 0-11 means 1 to 12 months
1388 pickerDate.SetDay(date->ToNumber<int32_t>());
1389 }
1390 return pickerDate;
1391 }
1392
ParseTime(const JSRef<JSVal> & timeVal)1393 PickerTime JSDatePickerDialog::ParseTime(const JSRef<JSVal>& timeVal)
1394 {
1395 auto pickerTime = PickerTime();
1396 if (!timeVal->IsObject()) {
1397 return pickerTime;
1398 }
1399 auto timeObj = JSRef<JSObject>::Cast(timeVal);
1400 auto hourFuncJsVal = timeObj->GetProperty("getHours");
1401 auto minuteFuncJsVal = timeObj->GetProperty("getMinutes");
1402 auto secondFuncJsVal = timeObj->GetProperty("getSeconds");
1403 if (!(hourFuncJsVal->IsFunction() && minuteFuncJsVal->IsFunction() && secondFuncJsVal->IsFunction())) {
1404 return pickerTime;
1405 }
1406 auto hourFunc = JSRef<JSFunc>::Cast(hourFuncJsVal);
1407 auto minuteFunc = JSRef<JSFunc>::Cast(minuteFuncJsVal);
1408 auto secondFunc = JSRef<JSFunc>::Cast(secondFuncJsVal);
1409 JSRef<JSVal> hour = hourFunc->Call(timeObj);
1410 JSRef<JSVal> minute = minuteFunc->Call(timeObj);
1411 JSRef<JSVal> second = secondFunc->Call(timeObj);
1412
1413 if (hour->IsNumber() && minute->IsNumber() && second->IsNumber()) {
1414 pickerTime.SetHour(hour->ToNumber<int32_t>());
1415 pickerTime.SetMinute(minute->ToNumber<int32_t>());
1416 pickerTime.SetSecond(second->ToNumber<int32_t>());
1417 }
1418 return pickerTime;
1419 }
1420
ParseDateTimeOptions(const JSRef<JSObject> & paramObj,DateTimeType & dateTimeOptions)1421 void JSDatePickerDialog::ParseDateTimeOptions(const JSRef<JSObject>& paramObj, DateTimeType& dateTimeOptions)
1422 {
1423 dateTimeOptions.hourType = ZeroPrefixType::AUTO;
1424 dateTimeOptions.minuteType = ZeroPrefixType::AUTO;
1425 dateTimeOptions.secondType = ZeroPrefixType::AUTO;
1426
1427 auto hourValue = paramObj->GetProperty(TIMEPICKER_OPTIONS_HOUR);
1428 if (hourValue->IsString()) {
1429 std::string hour = hourValue->ToString();
1430 if (hour == TIMEPICKER_OPTIONS_TWO_DIGIT_VAL) {
1431 dateTimeOptions.hourType = ZeroPrefixType::SHOW;
1432 } else if (hour == TIMEPICKER_OPTIONS_NUMERIC_VAL) {
1433 dateTimeOptions.hourType = ZeroPrefixType::HIDE;
1434 }
1435 }
1436 auto minuteValue = paramObj->GetProperty(TIMEPICKER_OPTIONS_MINUTE);
1437 if (minuteValue->IsString()) {
1438 dateTimeOptions.minuteType = ZeroPrefixType::SHOW;
1439 std::string minute = minuteValue->ToString();
1440 if (minute == TIMEPICKER_OPTIONS_NUMERIC_VAL) {
1441 dateTimeOptions.minuteType = ZeroPrefixType::HIDE;
1442 }
1443 }
1444 }
1445
JSBind(BindingTarget globalObj)1446 void JSTimePicker::JSBind(BindingTarget globalObj)
1447 {
1448 JSClass<JSTimePicker>::Declare("TimePicker");
1449 MethodOptions opt = MethodOptions::NONE;
1450 JSClass<JSTimePicker>::StaticMethod("create", &JSTimePicker::Create, opt);
1451 JSClass<JSTimePicker>::StaticMethod("onChange", &JSTimePicker::OnChange);
1452 JSClass<JSTimePicker>::StaticMethod("backgroundColor", &JSTimePicker::PickerBackgroundColor);
1453 JSClass<JSTimePicker>::StaticMethod("loop", &JSTimePicker::Loop);
1454 JSClass<JSTimePicker>::StaticMethod("useMilitaryTime", &JSTimePicker::UseMilitaryTime);
1455 JSClass<JSTimePicker>::StaticMethod("enableHapticFeedback", &JSTimePicker::EnableHapticFeedback);
1456 JSClass<JSTimePicker>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
1457 JSClass<JSTimePicker>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
1458 JSClass<JSTimePicker>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
1459 JSClass<JSTimePicker>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
1460 JSClass<JSTimePicker>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
1461 JSClass<JSTimePicker>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
1462 JSClass<JSTimePicker>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
1463 JSClass<JSTimePicker>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
1464 JSClass<JSTimePicker>::StaticMethod("disappearTextStyle", &JSTimePicker::SetDisappearTextStyle);
1465 JSClass<JSTimePicker>::StaticMethod("textStyle", &JSTimePicker::SetTextStyle);
1466 JSClass<JSTimePicker>::StaticMethod("selectedTextStyle", &JSTimePicker::SetSelectedTextStyle);
1467 JSClass<JSTimePicker>::StaticMethod("dateTimeOptions", &JSTimePicker::DateTimeOptions);
1468 JSClass<JSTimePicker>::StaticMethod("opacity", &JSTimePicker::JsOpacity);
1469 JSClass<JSTimePicker>::StaticMethod("enableCascade", &JSTimePicker::EnableCascade);
1470 JSClass<JSTimePicker>::StaticMethod("onEnterSelectedArea", &JSTimePicker::OnEnterSelectedArea);
1471 JSClass<JSTimePicker>::StaticMethod("digitalCrownSensitivity", &JSTimePicker::SetDigitalCrownSensitivity);
1472 JSClass<JSTimePicker>::InheritAndBind<JSViewAbstract>(globalObj);
1473 }
1474
SetDigitalCrownSensitivity(const JSCallbackInfo & info)1475 void JSTimePicker::SetDigitalCrownSensitivity(const JSCallbackInfo& info)
1476 {
1477 int32_t value = OHOS::Ace::NG::DEFAULT_CROWNSENSITIVITY;
1478 if (info[0]->IsNumber()) {
1479 value = info[0]->ToNumber<int32_t>();
1480 }
1481 TimePickerModel::GetInstance()->SetDigitalCrownSensitivity(value);
1482 }
1483
Create(const JSCallbackInfo & info)1484 void JSTimePicker::Create(const JSCallbackInfo& info)
1485 {
1486 JSRef<JSObject> paramObject = JSRef<JSObject>::New();
1487 if (info.Length() >= 1 && info[0]->IsObject()) {
1488 paramObject = JSRef<JSObject>::Cast(info[0]);
1489 }
1490 CreateTimePicker(info, paramObject);
1491 }
1492
JsOpacity(const JSCallbackInfo & info)1493 void JSTimePicker::JsOpacity(const JSCallbackInfo& info)
1494 {
1495 JSViewAbstract::JsOpacity(info);
1496 TimePickerModel::GetInstance()->HasUserDefinedOpacity();
1497 }
1498
Loop(const JSCallbackInfo & info)1499 void JSTimePicker::Loop(const JSCallbackInfo& info)
1500 {
1501 bool isLoop = true;
1502 if (info[0]->IsBoolean()) {
1503 isLoop = info[0]->ToBoolean();
1504 }
1505 TimePickerModel::GetInstance()->SetWheelModeEnabled(isLoop);
1506 }
1507
EnableHapticFeedback(const JSCallbackInfo & info)1508 void JSTimePicker::EnableHapticFeedback(const JSCallbackInfo& info)
1509 {
1510 bool isEnableHapticFeedback = true;
1511 if (info[0]->IsBoolean()) {
1512 isEnableHapticFeedback = info[0]->ToBoolean();
1513 }
1514 TimePickerModel::GetInstance()->SetIsEnableHapticFeedback(isEnableHapticFeedback);
1515 }
1516
UseMilitaryTime(bool isUseMilitaryTime)1517 void JSTimePicker::UseMilitaryTime(bool isUseMilitaryTime)
1518 {
1519 TimePickerModel::GetInstance()->SetHour24(isUseMilitaryTime);
1520 }
1521
EnableCascade(const JSCallbackInfo & info)1522 void JSTimePicker::EnableCascade(const JSCallbackInfo& info)
1523 {
1524 bool isEnableCascade = false;
1525 if (info[0]->IsBoolean()) {
1526 isEnableCascade = info[0]->ToBoolean();
1527 }
1528 TimePickerModel::GetInstance()->SetEnableCascade(isEnableCascade);
1529 }
1530
DateTimeOptions(const JSCallbackInfo & info)1531 void JSTimePicker::DateTimeOptions(const JSCallbackInfo& info)
1532 {
1533 JSRef<JSObject> paramObject;
1534 ZeroPrefixType hourType = ZeroPrefixType::AUTO;
1535 ZeroPrefixType minuteType = ZeroPrefixType::AUTO;
1536 ZeroPrefixType secondType = ZeroPrefixType::AUTO;
1537 if (info.Length() >= 1 && info[0]->IsObject()) {
1538 paramObject = JSRef<JSObject>::Cast(info[0]);
1539 auto hourValue = paramObject->GetProperty(TIMEPICKER_OPTIONS_HOUR);
1540 if (hourValue->IsString()) {
1541 std::string hour = hourValue->ToString();
1542 if (hour == TIMEPICKER_OPTIONS_TWO_DIGIT_VAL) {
1543 hourType = ZeroPrefixType::SHOW;
1544 } else if (hour == TIMEPICKER_OPTIONS_NUMERIC_VAL) {
1545 hourType = ZeroPrefixType::HIDE;
1546 }
1547 }
1548 auto minuteValue = paramObject->GetProperty(TIMEPICKER_OPTIONS_MINUTE);
1549 if (minuteValue->IsString()) {
1550 minuteType = ZeroPrefixType::SHOW;
1551 std::string minute = minuteValue->ToString();
1552 if (minute == TIMEPICKER_OPTIONS_NUMERIC_VAL) {
1553 minuteType = ZeroPrefixType::HIDE;
1554 }
1555 }
1556 auto secondValue = paramObject->GetProperty(TIMEPICKER_OPTIONS_SECOND);
1557 if (secondValue->IsString()) {
1558 secondType = ZeroPrefixType::SHOW;
1559 std::string second = secondValue->ToString();
1560 if (second == TIMEPICKER_OPTIONS_NUMERIC_VAL) {
1561 secondType = ZeroPrefixType::HIDE;
1562 }
1563 }
1564 }
1565 TimePickerModel::GetInstance()->SetDateTimeOptions(hourType, minuteType, secondType);
1566 }
1567
PickerBackgroundColor(const JSCallbackInfo & info)1568 void JSTimePicker::PickerBackgroundColor(const JSCallbackInfo& info)
1569 {
1570 JSViewAbstract::JsBackgroundColor(info);
1571
1572 if (info.Length() < 1) {
1573 return;
1574 }
1575 Color backgroundColor;
1576 if (!ParseJsColor(info[0], backgroundColor)) {
1577 return;
1578 }
1579 TimePickerModel::GetInstance()->SetBackgroundColor(backgroundColor);
1580 }
1581
SetDisappearTextStyle(const JSCallbackInfo & info)1582 void JSTimePicker::SetDisappearTextStyle(const JSCallbackInfo& info)
1583 {
1584 auto theme = GetTheme<PickerTheme>();
1585 CHECK_NULL_VOID(theme);
1586 NG::PickerTextStyle textStyle;
1587 if (info[0]->IsObject()) {
1588 JSDatePicker::ParseTextStyle(info[0], textStyle, "disappearTextStyleTime");
1589 }
1590 TimePickerModel::GetInstance()->SetDisappearTextStyle(theme, textStyle);
1591 }
1592
SetTextStyle(const JSCallbackInfo & info)1593 void JSTimePicker::SetTextStyle(const JSCallbackInfo& info)
1594 {
1595 auto theme = GetTheme<PickerTheme>();
1596 CHECK_NULL_VOID(theme);
1597 NG::PickerTextStyle textStyle;
1598 if (info[0]->IsObject()) {
1599 JSDatePicker::ParseTextStyle(info[0], textStyle, "textStyleTime");
1600 }
1601 TimePickerModel::GetInstance()->SetNormalTextStyle(theme, textStyle);
1602 }
1603
SetSelectedTextStyle(const JSCallbackInfo & info)1604 void JSTimePicker::SetSelectedTextStyle(const JSCallbackInfo& info)
1605 {
1606 auto theme = GetTheme<PickerTheme>();
1607 CHECK_NULL_VOID(theme);
1608 NG::PickerTextStyle textStyle;
1609 if (info[0]->IsObject()) {
1610 JSDatePicker::ParseTextStyle(info[0], textStyle, "selectedTextStyleTime");
1611 }
1612 TimePickerModel::GetInstance()->SetSelectedTextStyle(theme, textStyle);
1613 if (textStyle.textColor.has_value() && theme->IsCircleDial()) {
1614 TimePickerModel::GetInstance()->UpdateUserSetSelectColor();
1615 }
1616 }
1617
CreateTimePicker(const JSCallbackInfo & info,const JSRef<JSObject> & paramObj)1618 void JSTimePicker::CreateTimePicker(const JSCallbackInfo& info, const JSRef<JSObject>& paramObj)
1619 {
1620 auto startTime = paramObj->GetProperty("start");
1621 auto endTime = paramObj->GetProperty("end");
1622 auto selectedTime = paramObj->GetProperty("selected");
1623 auto theme = GetTheme<PickerTheme>();
1624 CHECK_NULL_VOID(theme);
1625 auto parseStartTime = ParseTime(startTime, theme->GetDefaultStartTime(), true);
1626 auto parseEndTime = ParseTime(endTime, theme->GetDefaultEndTime(), true);
1627 if (parseStartTime.ToMinutes() > parseEndTime.ToMinutes()) {
1628 parseStartTime = theme->GetDefaultStartTime();
1629 parseEndTime = theme->GetDefaultEndTime();
1630 }
1631 auto formatValue = paramObj->GetProperty("format");
1632 bool showSecond = false;
1633 if (formatValue->IsNumber()) {
1634 auto displayedFormat = static_cast<TimePickerFormat>(formatValue->ToNumber<int32_t>());
1635 if (displayedFormat == TimePickerFormat::HOUR_MINUTE_SECOND) {
1636 showSecond = true;
1637 }
1638 }
1639 TimePickerModel::GetInstance()->CreateTimePicker(theme, showSecond);
1640 TimePickerModel::GetInstance()->SetStartTime(parseStartTime);
1641 TimePickerModel::GetInstance()->SetEndTime(parseEndTime);
1642 if (selectedTime->IsObject()) {
1643 JSRef<JSObject> selectedTimeObj = JSRef<JSObject>::Cast(selectedTime);
1644 JSRef<JSVal> changeEventVal = selectedTimeObj->GetProperty("changeEvent");
1645 if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
1646 ParseSelectedDateTimeObject(info, selectedTimeObj, false);
1647 auto parseSelectedTime = ParseTime(selectedTimeObj->GetProperty("value"));
1648 TimePickerModel::GetInstance()->SetSelectedTime(parseSelectedTime);
1649 } else {
1650 TimePickerModel::GetInstance()->SetSelectedTime(ParseTime(selectedTime));
1651 }
1652 }
1653 SetDefaultAttributes();
1654 }
1655
SetDefaultAttributes()1656 void JSTimePicker::SetDefaultAttributes()
1657 {
1658 auto theme = GetTheme<PickerTheme>();
1659 CHECK_NULL_VOID(theme);
1660 NG::PickerTextStyle textStyle;
1661 auto selectedStyle = theme->GetOptionStyle(true, false);
1662 textStyle.fontSize = selectedStyle.GetFontSize();
1663 textStyle.fontWeight = selectedStyle.GetFontWeight();
1664 TimePickerModel::GetInstance()->SetSelectedTextStyle(theme, textStyle);
1665
1666 auto disappearStyle = theme->GetDisappearOptionStyle();
1667 textStyle.fontSize = disappearStyle.GetFontSize();
1668 textStyle.fontWeight = disappearStyle.GetFontWeight();
1669 TimePickerModel::GetInstance()->SetDisappearTextStyle(theme, textStyle);
1670
1671 auto normalStyle = theme->GetOptionStyle(false, false);
1672 textStyle.fontSize = normalStyle.GetFontSize();
1673 textStyle.fontWeight = normalStyle.GetFontWeight();
1674 TimePickerModel::GetInstance()->SetNormalTextStyle(theme, textStyle);
1675 }
1676
ParseTime(const JSRef<JSVal> & timeVal,PickerTime defaultTime,bool startEndCheckValue)1677 PickerTime JSTimePicker::ParseTime(const JSRef<JSVal>& timeVal, PickerTime defaultTime, bool startEndCheckValue)
1678 {
1679 auto pickerTime = startEndCheckValue ? defaultTime : PickerTime::Current();
1680 if (!timeVal->IsObject()) {
1681 return pickerTime;
1682 }
1683 auto timeObj = JSRef<JSObject>::Cast(timeVal);
1684 auto yearFuncJsVal = timeObj->GetProperty("getFullYear");
1685 if (yearFuncJsVal->IsFunction()) {
1686 auto yearFunc = JSRef<JSFunc>::Cast(yearFuncJsVal);
1687 JSRef<JSVal> year = yearFunc->Call(timeObj);
1688 if (year->IsNumber() && LessOrEqual(year->ToNumber<int32_t>(), 0)) {
1689 return pickerTime;
1690 }
1691 }
1692
1693 auto hourFuncJsVal = timeObj->GetProperty("getHours");
1694 auto minuteFuncJsVal = timeObj->GetProperty("getMinutes");
1695 auto secondFuncJsVal = timeObj->GetProperty("getSeconds");
1696 if (!(hourFuncJsVal->IsFunction() && minuteFuncJsVal->IsFunction() && secondFuncJsVal->IsFunction())) {
1697 return pickerTime;
1698 }
1699 auto hourFunc = JSRef<JSFunc>::Cast(hourFuncJsVal);
1700 auto minuteFunc = JSRef<JSFunc>::Cast(minuteFuncJsVal);
1701 auto secondFunc = JSRef<JSFunc>::Cast(secondFuncJsVal);
1702 JSRef<JSVal> hour = hourFunc->Call(timeObj);
1703 JSRef<JSVal> minute = minuteFunc->Call(timeObj);
1704 JSRef<JSVal> second = secondFunc->Call(timeObj);
1705
1706 if (hour->IsNumber() && minute->IsNumber() && second->IsNumber()) {
1707 pickerTime.SetHour(hour->ToNumber<int32_t>());
1708 pickerTime.SetMinute(minute->ToNumber<int32_t>());
1709 pickerTime.SetSecond(second->ToNumber<int32_t>());
1710 }
1711 return pickerTime;
1712 }
1713
JSBind(BindingTarget globalObj)1714 void JSTimePickerDialog::JSBind(BindingTarget globalObj)
1715 {
1716 JSClass<JSTimePickerDialog>::Declare("TimePickerDialog");
1717 JSClass<JSTimePickerDialog>::StaticMethod("show", &JSTimePickerDialog::Show);
1718
1719 JSClass<JSTimePickerDialog>::Bind<>(globalObj);
1720 }
1721
TimePickerDialogAppearEvent(const JSCallbackInfo & info,TimePickerDialogEvent & timePickerDialogEvent)1722 void TimePickerDialogAppearEvent(const JSCallbackInfo& info, TimePickerDialogEvent& timePickerDialogEvent)
1723 {
1724 std::function<void()> didAppearEvent;
1725 std::function<void()> willAppearEvent;
1726 if (info.Length() == 0 || !info[0]->IsObject()) {
1727 return;
1728 }
1729 auto paramObject = JSRef<JSObject>::Cast(info[0]);
1730 WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1731 auto onDidAppear = paramObject->GetProperty("onDidAppear");
1732 if (!onDidAppear->IsUndefined() && onDidAppear->IsFunction()) {
1733 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onDidAppear));
1734 didAppearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]() {
1735 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1736 ACE_SCORING_EVENT("DatePickerDialog.onDidAppear");
1737 PipelineContext::SetCallBackNode(node);
1738 func->Execute();
1739 };
1740 }
1741 auto onWillAppear = paramObject->GetProperty("onWillAppear");
1742 if (!onWillAppear->IsUndefined() && onWillAppear->IsFunction()) {
1743 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onWillAppear));
1744 willAppearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]() {
1745 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1746 ACE_SCORING_EVENT("DatePickerDialog.onWillAppear");
1747 PipelineContext::SetCallBackNode(node);
1748 func->Execute();
1749 };
1750 }
1751 timePickerDialogEvent.onDidAppear = std::move(didAppearEvent);
1752 timePickerDialogEvent.onWillAppear = std::move(willAppearEvent);
1753 }
1754
TimePickerDialogDisappearEvent(const JSCallbackInfo & info,TimePickerDialogEvent & timePickerDialogEvent)1755 void TimePickerDialogDisappearEvent(const JSCallbackInfo& info, TimePickerDialogEvent& timePickerDialogEvent)
1756 {
1757 std::function<void()> didDisappearEvent;
1758 std::function<void()> willDisappearEvent;
1759 if (info.Length() == 0 || !info[0]->IsObject()) {
1760 return;
1761 }
1762 auto paramObject = JSRef<JSObject>::Cast(info[0]);
1763 WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1764 auto onDidDisappear = paramObject->GetProperty("onDidDisappear");
1765 if (!onDidDisappear->IsUndefined() && onDidDisappear->IsFunction()) {
1766 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onDidDisappear));
1767 didDisappearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]() {
1768 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1769 ACE_SCORING_EVENT("DatePickerDialog.onDidDisappear");
1770 PipelineContext::SetCallBackNode(node);
1771 func->Execute();
1772 };
1773 }
1774 auto onWillDisappear = paramObject->GetProperty("onWillDisappear");
1775 if (!onWillDisappear->IsUndefined() && onWillDisappear->IsFunction()) {
1776 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onWillDisappear));
1777 willDisappearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]() {
1778 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1779 ACE_SCORING_EVENT("DatePickerDialog.onWillDisappear");
1780 PipelineContext::SetCallBackNode(node);
1781 func->Execute();
1782 };
1783 }
1784 timePickerDialogEvent.onDidDisappear = std::move(didDisappearEvent);
1785 timePickerDialogEvent.onWillDisappear = std::move(willDisappearEvent);
1786 }
1787
Show(const JSCallbackInfo & info)1788 void JSTimePickerDialog::Show(const JSCallbackInfo& info)
1789 {
1790 auto scopedDelegate = EngineHelper::GetCurrentDelegateSafely();
1791 CHECK_NULL_VOID(scopedDelegate);
1792 if ((Container::LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN) && !info[0]->IsObject()) ||
1793 (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN) && !info[0]->IsObject()
1794 && !info[0]->IsEmpty())) {
1795 return;
1796 }
1797 auto paramObject = info[0]->IsEmpty() ? (JSRef<JSObject>::New()) : JSRef<JSObject>::Cast(info[0]);
1798 std::function<void()> cancelEvent;
1799 std::function<void(const std::string&)> acceptEvent;
1800 std::function<void(const std::string&)> changeEvent;
1801 std::function<void(const std::string&)> enterEvent;
1802 WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1803 auto onChange = paramObject->GetProperty("onChange");
1804 if (!onChange->IsUndefined() && onChange->IsFunction()) {
1805 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onChange));
1806 changeEvent = [execCtx = info.GetExecutionContext(), type = DatePickerType::TIME, func = std::move(jsFunc),
1807 node = targetNode](const std::string& info) {
1808 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1809 std::vector<std::string> keys;
1810 keys = { "year", "month", "day", "hour", "minute", "second" };
1811 ACE_SCORING_EVENT("DatePickerDialog.onChange");
1812 PipelineContext::SetCallBackNode(node);
1813 func->Execute(keys, info);
1814 };
1815 }
1816 auto onEnterSelectedArea = paramObject->GetProperty("onEnterSelectedArea");
1817 if (!onEnterSelectedArea->IsUndefined() && onEnterSelectedArea->IsFunction()) {
1818 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onEnterSelectedArea));
1819 enterEvent = [execCtx = info.GetExecutionContext(), type = DatePickerType::TIME, func = std::move(jsFunc),
1820 node = targetNode](const std::string& info) {
1821 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1822 std::vector<std::string> keys;
1823 keys = { "year", "month", "day", "hour", "minute", "second" };
1824 ACE_SCORING_EVENT("DatePickerDialog.onEnterSelectedArea");
1825 PipelineContext::SetCallBackNode(node);
1826 func->Execute(keys, info);
1827 };
1828 }
1829 auto onAccept = paramObject->GetProperty("onAccept");
1830 if (!onAccept->IsUndefined() && onAccept->IsFunction()) {
1831 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onAccept));
1832 acceptEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
1833 const std::string& info) {
1834 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1835 std::vector<std::string> keys = { "year", "month", "day", "hour", "minute", "second" };
1836 ACE_SCORING_EVENT("DatePickerDialog.onAccept");
1837 PipelineContext::SetCallBackNode(node);
1838 func->Execute(keys, info);
1839 };
1840 }
1841 auto onCancel = paramObject->GetProperty("onCancel");
1842 if (!onCancel->IsUndefined() && onCancel->IsFunction()) {
1843 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onCancel));
1844 cancelEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]() {
1845 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1846 ACE_SCORING_EVENT("DatePickerDialog.onCancel");
1847 PipelineContext::SetCallBackNode(node);
1848 func->Execute();
1849 };
1850 }
1851 auto startTime = paramObject->GetProperty("start");
1852 auto endTime = paramObject->GetProperty("end");
1853 auto selectedTime = paramObject->GetProperty("selected");
1854 auto useMilitaryTime = paramObject->GetProperty("useMilitaryTime");
1855 auto enableCascade = paramObject->GetProperty("enableCascade");
1856 NG::TimePickerSettingData settingData;
1857 PickerDialogInfo pickerDialog;
1858 settingData.isUseMilitaryTime = useMilitaryTime->ToBoolean();
1859 settingData.isEnableCascade = enableCascade->ToBoolean();
1860 pickerDialog.isUseMilitaryTime = useMilitaryTime->ToBoolean();
1861 pickerDialog.isEnableCascade = enableCascade->ToBoolean();
1862 auto theme = GetTheme<PickerTheme>();
1863 CHECK_NULL_VOID(theme);
1864 auto parseStartTime = ParseTime(startTime, theme->GetDefaultStartTime(), true);
1865 auto parseEndTime = ParseTime(endTime, theme->GetDefaultEndTime(), true);
1866 if (parseStartTime.ToMinutes() > parseEndTime.ToMinutes()) {
1867 parseStartTime = theme->GetDefaultStartTime();
1868 parseEndTime = theme->GetDefaultEndTime();
1869 }
1870 pickerDialog.parseStartTime = parseStartTime;
1871 pickerDialog.parseEndTime = parseEndTime;
1872
1873 if (selectedTime->IsObject()) {
1874 PickerDate dialogTitleDate = ParseDate(selectedTime);
1875 if (dialogTitleDate.GetYear() != 0) {
1876 settingData.dialogTitleDate = dialogTitleDate;
1877 pickerDialog.isSelectedTime = true;
1878 pickerDialog.pickerTime = ParseTime(selectedTime);
1879 }
1880 }
1881 JSDatePicker::ParseTextProperties(paramObject, settingData.properties);
1882 auto dateTimeOptionsValue = paramObject->GetProperty("dateTimeOptions");
1883 if (dateTimeOptionsValue->IsObject()) {
1884 auto dateTimeOptionsObj = JSRef<JSObject>::Cast(dateTimeOptionsValue);
1885 JSDatePickerDialog::ParseDateTimeOptions(dateTimeOptionsObj, settingData.dateTimeOptions);
1886 }
1887
1888 // Parse alignment
1889 auto alignmentValue = paramObject->GetProperty("alignment");
1890 if (alignmentValue->IsNumber()) {
1891 auto alignment = alignmentValue->ToNumber<int32_t>();
1892 if (alignment >= 0 && alignment < static_cast<int32_t>(DIALOG_ALIGNMENT.size())) {
1893 pickerDialog.alignment = DIALOG_ALIGNMENT[alignment];
1894 }
1895 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1896 if (alignment == static_cast<int32_t>(DialogAlignment::TOP) ||
1897 alignment == static_cast<int32_t>(DialogAlignment::TOP_START) ||
1898 alignment == static_cast<int32_t>(DialogAlignment::TOP_END)) {
1899 pickerDialog.offset = DATEPICKER_OFFSET_DEFAULT_TOP;
1900 }
1901 }
1902 }
1903
1904 // Parse offset
1905 auto offsetValue = paramObject->GetProperty("offset");
1906 if (offsetValue->IsObject()) {
1907 auto offsetObj = JSRef<JSObject>::Cast(offsetValue);
1908 CalcDimension dx;
1909 auto dxValue = offsetObj->GetProperty("dx");
1910 JSAlertDialog::ParseJsDimensionVp(dxValue, dx);
1911 CalcDimension dy;
1912 auto dyValue = offsetObj->GetProperty("dy");
1913 JSAlertDialog::ParseJsDimensionVp(dyValue, dy);
1914 pickerDialog.offset = DimensionOffset(dx, dy);
1915 }
1916
1917 // Parse maskRect.
1918 auto maskRectValue = paramObject->GetProperty("maskRect");
1919 DimensionRect maskRect;
1920 if (JSViewAbstract::ParseJsDimensionRect(maskRectValue, maskRect)) {
1921 pickerDialog.maskRect = maskRect;
1922 }
1923
1924 auto backgroundColorValue = paramObject->GetProperty("backgroundColor");
1925 Color backgroundColor;
1926 if (JSViewAbstract::ParseJsColor(backgroundColorValue, backgroundColor)) {
1927 pickerDialog.backgroundColor = backgroundColor;
1928 }
1929
1930 auto backgroundBlurStyle = paramObject->GetProperty("backgroundBlurStyle");
1931 if (backgroundBlurStyle->IsNumber()) {
1932 auto blurStyle = backgroundBlurStyle->ToNumber<int32_t>();
1933 if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
1934 blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
1935 pickerDialog.backgroundBlurStyle = blurStyle;
1936 }
1937 }
1938
1939 ParseDatePickerHoverMode(pickerDialog, paramObject);
1940 ParseDatePickerBlurStyleOption(pickerDialog, paramObject);
1941 ParseDatePickerEffectOption(pickerDialog, paramObject);
1942
1943 auto buttonInfos = ParseButtonStyles(paramObject);
1944
1945 auto shadowValue = paramObject->GetProperty("shadow");
1946 Shadow shadow;
1947 if ((shadowValue->IsObject() || shadowValue->IsNumber()) && JSViewAbstract::ParseShadowProps(shadowValue, shadow)) {
1948 pickerDialog.shadow = shadow;
1949 }
1950 auto formatValue = paramObject->GetProperty("format");
1951 bool showSecond = false;
1952 if (formatValue->IsNumber()) {
1953 auto displayedFormat = static_cast<TimePickerFormat>(formatValue->ToNumber<int32_t>());
1954 if (displayedFormat == TimePickerFormat::HOUR_MINUTE_SECOND) {
1955 showSecond = true;
1956 }
1957 }
1958 settingData.showSecond = showSecond;
1959 auto enableHapticFeedbackValue = paramObject->GetProperty("enableHapticFeedback");
1960 bool isEnableHapticFeedback = true;
1961 if (enableHapticFeedbackValue->IsBoolean()) {
1962 isEnableHapticFeedback = enableHapticFeedbackValue->ToBoolean();
1963 }
1964 settingData.isEnableHapticFeedback = isEnableHapticFeedback;
1965 TimePickerDialogEvent timePickerDialogEvent { nullptr, nullptr, nullptr, nullptr };
1966 TimePickerDialogAppearEvent(info, timePickerDialogEvent);
1967 TimePickerDialogDisappearEvent(info, timePickerDialogEvent);
1968 TimePickerDialogModel::GetInstance()->SetTimePickerDialogShow(pickerDialog, settingData, std::move(cancelEvent),
1969 std::move(acceptEvent), std::move(changeEvent), std::move(enterEvent), timePickerDialogEvent, buttonInfos);
1970 }
1971
TimePickerDialogShow(const JSRef<JSObject> & paramObj,const std::map<std::string,NG::DialogEvent> & dialogEvent,const std::map<std::string,NG::DialogGestureEvent> & dialogCancelEvent)1972 void JSTimePickerDialog::TimePickerDialogShow(const JSRef<JSObject>& paramObj,
1973 const std::map<std::string, NG::DialogEvent>& dialogEvent,
1974 const std::map<std::string, NG::DialogGestureEvent>& dialogCancelEvent)
1975 {
1976 auto container = Container::CurrentSafely();
1977 CHECK_NULL_VOID(container);
1978
1979 auto pipelineContext = AccessibilityManager::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
1980 CHECK_NULL_VOID(pipelineContext);
1981
1982 auto executor = pipelineContext->GetTaskExecutor();
1983 CHECK_NULL_VOID(executor);
1984
1985 auto theme = JSAlertDialog::GetTheme<DialogTheme>();
1986 CHECK_NULL_VOID(theme);
1987
1988 auto selectedTime = paramObj->GetProperty("selected");
1989 auto useMilitaryTime = paramObj->GetProperty("useMilitaryTime");
1990 auto enableCascade = paramObj->GetProperty("enableCascade");
1991 NG::TimePickerSettingData settingData;
1992 settingData.isUseMilitaryTime = useMilitaryTime->ToBoolean();
1993 settingData.isEnableCascade = enableCascade->ToBoolean();
1994
1995 DialogProperties properties;
1996 properties.alignment = theme->GetAlignment();
1997 if (properties.alignment == DialogAlignment::BOTTOM &&
1998 Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1999 properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx()));
2000 }
2001
2002 auto enableHapticFeedbackValue = paramObj->GetProperty("enableHapticFeedback");
2003 bool isEnableHapticFeedback = true;
2004 if (enableHapticFeedbackValue->IsBoolean()) {
2005 isEnableHapticFeedback = enableHapticFeedbackValue->ToBoolean();
2006 }
2007 settingData.isEnableHapticFeedback = isEnableHapticFeedback;
2008
2009 properties.customStyle = false;
2010 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
2011 properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx()));
2012 }
2013
2014 std::map<std::string, PickerTime> timePickerProperty;
2015 if (selectedTime->IsObject()) {
2016 settingData.dialogTitleDate = ParseDate(selectedTime);
2017 timePickerProperty["selected"] = ParseTime(selectedTime);
2018 }
2019 JSDatePicker::ParseTextProperties(paramObj, settingData.properties);
2020
2021 auto context = AccessibilityManager::DynamicCast<NG::PipelineContext>(pipelineContext);
2022 auto overlayManager = context ? context->GetOverlayManager() : nullptr;
2023 executor->PostTask(
2024 [properties, settingData, timePickerProperty, dialogEvent, dialogCancelEvent,
2025 weak = WeakPtr<NG::OverlayManager>(overlayManager)] {
2026 auto overlayManager = weak.Upgrade();
2027 CHECK_NULL_VOID(overlayManager);
2028 overlayManager->ShowTimeDialog(properties, settingData, timePickerProperty, dialogEvent, dialogCancelEvent);
2029 },
2030 TaskExecutor::TaskType::UI, "ArkUIDialogShowTimePicker",
2031 TaskExecutor::GetPriorityTypeWithCheck(PriorityType::VIP));
2032 }
2033
CreateTimePicker(RefPtr<Component> & component,const JSRef<JSObject> & paramObj)2034 void JSTimePickerDialog::CreateTimePicker(RefPtr<Component>& component, const JSRef<JSObject>& paramObj)
2035 {
2036 auto timePicker = AceType::MakeRefPtr<PickerTimeComponent>();
2037 auto selectedTime = paramObj->GetProperty("selected");
2038 auto useMilitaryTime = paramObj->GetProperty("useMilitaryTime");
2039 auto enableCascade = paramObj->GetProperty("enableCascade");
2040 bool isUseMilitaryTime = useMilitaryTime->ToBoolean();
2041 bool isEnableCascade = enableCascade->ToBoolean();
2042 if (selectedTime->IsObject()) {
2043 timePicker->SetSelectedTime(ParseTime(selectedTime));
2044 }
2045 timePicker->SetIsDialog(true);
2046 timePicker->SetIsCreateDialogComponent(true);
2047 timePicker->SetHour24(isUseMilitaryTime);
2048 timePicker->SetEnableCascade(isEnableCascade);
2049 component = timePicker;
2050 }
2051
ParseTime(const JSRef<JSVal> & timeVal,PickerTime defaultTime,bool startEndCheckValue)2052 PickerTime JSTimePickerDialog::ParseTime(const JSRef<JSVal>& timeVal, PickerTime defaultTime, bool startEndCheckValue)
2053 {
2054 auto pickerTime = startEndCheckValue ? defaultTime : PickerTime();
2055 if (!timeVal->IsObject()) {
2056 return pickerTime;
2057 }
2058 auto timeObj = JSRef<JSObject>::Cast(timeVal);
2059 auto yearFuncJsVal = timeObj->GetProperty("getFullYear");
2060 if (yearFuncJsVal->IsFunction()) {
2061 auto yearFunc = JSRef<JSFunc>::Cast(yearFuncJsVal);
2062 JSRef<JSVal> year = yearFunc->Call(timeObj);
2063 if (year->IsNumber() && LessOrEqual(year->ToNumber<int32_t>(), 0)) {
2064 return pickerTime;
2065 }
2066 }
2067 auto hourFuncJsVal = timeObj->GetProperty("getHours");
2068 auto minuteFuncJsVal = timeObj->GetProperty("getMinutes");
2069 auto secondFuncJsVal = timeObj->GetProperty("getSeconds");
2070 if (!(hourFuncJsVal->IsFunction() && minuteFuncJsVal->IsFunction() && secondFuncJsVal->IsFunction())) {
2071 return pickerTime;
2072 }
2073 auto hourFunc = JSRef<JSFunc>::Cast(hourFuncJsVal);
2074 auto minuteFunc = JSRef<JSFunc>::Cast(minuteFuncJsVal);
2075 auto secondFunc = JSRef<JSFunc>::Cast(secondFuncJsVal);
2076 JSRef<JSVal> hour = hourFunc->Call(timeObj);
2077 JSRef<JSVal> minute = minuteFunc->Call(timeObj);
2078 JSRef<JSVal> second = secondFunc->Call(timeObj);
2079
2080 if (hour->IsNumber() && minute->IsNumber() && second->IsNumber()) {
2081 pickerTime.SetHour(hour->ToNumber<int32_t>());
2082 pickerTime.SetMinute(minute->ToNumber<int32_t>());
2083 pickerTime.SetSecond(second->ToNumber<int32_t>());
2084 }
2085 return pickerTime;
2086 }
2087
ParseDate(const JSRef<JSVal> & dateVal)2088 PickerDate JSTimePickerDialog::ParseDate(const JSRef<JSVal>& dateVal)
2089 {
2090 auto pickerDate = PickerDate();
2091 if (!dateVal->IsObject()) {
2092 return pickerDate;
2093 }
2094 auto dateObj = JSRef<JSObject>::Cast(dateVal);
2095 auto yearFuncJsVal = dateObj->GetProperty("getFullYear");
2096 auto monthFuncJsVal = dateObj->GetProperty("getMonth");
2097 auto dateFuncJsVal = dateObj->GetProperty("getDate");
2098 if (!(yearFuncJsVal->IsFunction() && monthFuncJsVal->IsFunction() && dateFuncJsVal->IsFunction())) {
2099 return pickerDate;
2100 }
2101 auto yearFunc = JSRef<JSFunc>::Cast(yearFuncJsVal);
2102 auto monthFunc = JSRef<JSFunc>::Cast(monthFuncJsVal);
2103 auto dateFunc = JSRef<JSFunc>::Cast(dateFuncJsVal);
2104 JSRef<JSVal> year = yearFunc->Call(dateObj);
2105 JSRef<JSVal> month = monthFunc->Call(dateObj);
2106 JSRef<JSVal> date = dateFunc->Call(dateObj);
2107
2108 if (year->IsNumber() && month->IsNumber() && date->IsNumber()) {
2109 pickerDate.SetYear(year->ToNumber<int32_t>());
2110 pickerDate.SetMonth(month->ToNumber<int32_t>() + 1); // 0-11 means 1 to 12 months
2111 pickerDate.SetDay(date->ToNumber<int32_t>());
2112 }
2113 return pickerDate;
2114 }
2115 } // namespace OHOS::Ace::Framework
2116