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