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