• 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_view_common_def.h"
26 #include "bridge/declarative_frontend/jsview/models/picker_model_impl.h"
27 #include "bridge/declarative_frontend/jsview/models/timepicker_model_impl.h"
28 #include "bridge/declarative_frontend/view_stack_processor.h"
29 #include "core/components/picker/picker_data.h"
30 #include "core/components/picker/picker_date_component.h"
31 #include "core/components/picker/picker_theme.h"
32 #include "core/components/picker/picker_time_component.h"
33 #include "core/components_ng/base/view_stack_processor.h"
34 #include "core/components_ng/pattern/picker/datepicker_model_ng.h"
35 #include "core/components_ng/pattern/time_picker/timepicker_model.h"
36 #include "core/components_ng/pattern/time_picker/timepicker_model_ng.h"
37 #include "core/components_v2/inspector/inspector_constants.h"
38 #include "core/event/ace_event_helper.h"
39 #include "core/pipeline_ng/pipeline_context.h"
40 
41 namespace OHOS::Ace {
42 namespace {
43 const DimensionOffset DATEPICKER_OFFSET_DEFAULT_TOP = DimensionOffset(0.0_vp, 40.0_vp);
44 const std::vector<DialogAlignment> DIALOG_ALIGNMENT = { DialogAlignment::TOP, DialogAlignment::CENTER,
45     DialogAlignment::BOTTOM, DialogAlignment::DEFAULT, DialogAlignment::TOP_START, DialogAlignment::TOP_END,
46     DialogAlignment::CENTER_START, DialogAlignment::CENTER_END, DialogAlignment::BOTTOM_START,
47     DialogAlignment::BOTTOM_END };
48 } // namespace
49 
50 std::unique_ptr<DatePickerModel> DatePickerModel::datePickerInstance_ = nullptr;
51 std::unique_ptr<DatePickerDialogModel> DatePickerDialogModel::datePickerDialogInstance_ = nullptr;
52 std::unique_ptr<TimePickerModel> TimePickerModel::timePickerInstance_ = nullptr;
53 std::unique_ptr<TimePickerDialogModel> TimePickerDialogModel::timePickerDialogInstance_ = nullptr;
54 std::mutex DatePickerModel::mutex_;
55 std::mutex DatePickerDialogModel::mutex_;
56 std::mutex TimePickerModel::mutex_;
57 std::mutex TimePickerDialogModel::mutex_;
58 
GetInstance()59 DatePickerModel* DatePickerModel::GetInstance()
60 {
61     if (!datePickerInstance_) {
62         std::lock_guard<std::mutex> lock(mutex_);
63         if (!datePickerInstance_) {
64 #ifdef NG_BUILD
65             datePickerInstance_.reset(new NG::DatePickerModelNG());
66 #else
67             if (Container::IsCurrentUseNewPipeline()) {
68                 datePickerInstance_.reset(new NG::DatePickerModelNG());
69             } else {
70                 datePickerInstance_.reset(new Framework::DatePickerModelImpl());
71             }
72 #endif
73         }
74     }
75     return datePickerInstance_.get();
76 }
77 
GetInstance()78 DatePickerDialogModel* DatePickerDialogModel::GetInstance()
79 {
80     if (!datePickerDialogInstance_) {
81         std::lock_guard<std::mutex> lock(mutex_);
82         if (!datePickerDialogInstance_) {
83 #ifdef NG_BUILD
84             datePickerDialogInstance_.reset(new NG::DatePickerDialogModelNG());
85 #else
86             if (Container::IsCurrentUseNewPipeline()) {
87                 datePickerDialogInstance_.reset(new NG::DatePickerDialogModelNG());
88             } else {
89                 datePickerDialogInstance_.reset(new Framework::DatePickerDialogModelImpl());
90             }
91 #endif
92         }
93     }
94     return datePickerDialogInstance_.get();
95 }
96 
GetInstance()97 TimePickerModel* TimePickerModel::GetInstance()
98 {
99     if (!timePickerInstance_) {
100         std::lock_guard<std::mutex> lock(mutex_);
101         if (!timePickerInstance_) {
102 #ifdef NG_BUILD
103             timePickerInstance_.reset(new NG::TimePickerModelNG());
104 #else
105             if (Container::IsCurrentUseNewPipeline()) {
106                 timePickerInstance_.reset(new NG::TimePickerModelNG());
107             } else {
108                 timePickerInstance_.reset(new Framework::TimePickerModelImpl());
109             }
110 #endif
111         }
112     }
113     return timePickerInstance_.get();
114 }
115 
GetInstance()116 TimePickerDialogModel* TimePickerDialogModel::GetInstance()
117 {
118     if (!timePickerDialogInstance_) {
119         std::lock_guard<std::mutex> lock(mutex_);
120         if (!timePickerDialogInstance_) {
121 #ifdef NG_BUILD
122             timePickerDialogInstance_.reset(new NG::TimePickerDialogModelNG());
123 #else
124             if (Container::IsCurrentUseNewPipeline()) {
125                 timePickerDialogInstance_.reset(new NG::TimePickerDialogModelNG());
126             } else {
127                 timePickerDialogInstance_.reset(new Framework::TimePickerDialogModelImpl());
128             }
129 #endif
130         }
131     }
132     return timePickerDialogInstance_.get();
133 }
134 } // namespace OHOS::Ace
135 
136 namespace OHOS::Ace::Framework {
137 namespace {
DatePickerChangeEventToJSValue(const DatePickerChangeEvent & eventInfo)138 JSRef<JSVal> DatePickerChangeEventToJSValue(const DatePickerChangeEvent& eventInfo)
139 {
140     JSRef<JSObject> obj = JSRef<JSObject>::New();
141     std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(eventInfo.GetSelectedStr());
142     if (!argsPtr) {
143         return JSRef<JSVal>::Cast(obj);
144     }
145     std::vector<std::string> keys = { "year", "month", "day", "hour", "minute", "second" };
146     for (auto iter = keys.begin(); iter != keys.end(); iter++) {
147         const std::string key = *iter;
148         const auto value = argsPtr->GetValue(key);
149         if (!value || value->ToString().empty()) {
150             continue;
151         }
152         obj->SetProperty<int32_t>(key.c_str(), value->GetInt());
153     }
154     return JSRef<JSVal>::Cast(obj);
155 }
156 
DatePickerDateChangeEventToJSValue(const DatePickerChangeEvent & eventInfo)157 JSRef<JSVal> DatePickerDateChangeEventToJSValue(const DatePickerChangeEvent& eventInfo)
158 {
159     JSRef<JSObject> obj = JSRef<JSObject>::New();
160     std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(eventInfo.GetSelectedStr());
161     if (!argsPtr) {
162         return JSRef<JSVal>::Cast(obj);
163     }
164     std::tm dateTime = { 0 };
165     auto year = argsPtr->GetValue("year");
166     if (year && year->IsNumber()) {
167         dateTime.tm_year = year->GetInt() - 1900; // local date start from 1900
168     }
169     auto month = argsPtr->GetValue("month");
170     if (month && month->IsNumber()) {
171         dateTime.tm_mon = month->GetInt();
172     }
173     auto day = argsPtr->GetValue("day");
174     if (day && day->IsNumber()) {
175         dateTime.tm_mday = day->GetInt();
176     }
177     auto hour = argsPtr->GetValue("hour");
178     if (hour && hour->IsNumber()) {
179         dateTime.tm_hour = hour->GetInt();
180     }
181     auto minute = argsPtr->GetValue("minute");
182     if (minute && minute->IsNumber()) {
183         dateTime.tm_min = minute->GetInt();
184     }
185 
186     auto milliseconds = Date::GetMilliSecondsByDateTime(dateTime);
187     auto dateObj = JSDate::New(milliseconds);
188     return JSRef<JSVal>::Cast(dateObj);
189 }
190 } // namespace
191 
JSBind(BindingTarget globalObj)192 void JSDatePicker::JSBind(BindingTarget globalObj)
193 {
194     JSClass<JSDatePicker>::Declare("DatePicker");
195     MethodOptions opt = MethodOptions::NONE;
196     JSClass<JSDatePicker>::StaticMethod("create", &JSDatePicker::Create, opt);
197     JSClass<JSDatePicker>::StaticMethod("lunar", &JSDatePicker::SetLunar);
198     JSClass<JSDatePicker>::StaticMethod("onChange", &JSDatePicker::OnChange);
199     JSClass<JSDatePicker>::StaticMethod("onDateChange", &JSDatePicker::OnDateChange);
200     JSClass<JSDatePicker>::StaticMethod("backgroundColor", &JSDatePicker::PickerBackgroundColor);
201     // keep compatible, need remove after
202     JSClass<JSDatePicker>::StaticMethod("useMilitaryTime", &JSDatePicker::UseMilitaryTime);
203     JSClass<JSDatePicker>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
204     JSClass<JSDatePicker>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
205     JSClass<JSDatePicker>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
206     JSClass<JSDatePicker>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
207     JSClass<JSDatePicker>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
208     JSClass<JSDatePicker>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
209     JSClass<JSDatePicker>::StaticMethod("disappearTextStyle", &JSDatePicker::SetDisappearTextStyle);
210     JSClass<JSDatePicker>::StaticMethod("textStyle", &JSDatePicker::SetTextStyle);
211     JSClass<JSDatePicker>::StaticMethod("selectedTextStyle", &JSDatePicker::SetSelectedTextStyle);
212     JSClass<JSDatePicker>::InheritAndBind<JSViewAbstract>(globalObj);
213 }
214 
Create(const JSCallbackInfo & info)215 void JSDatePicker::Create(const JSCallbackInfo& info)
216 {
217     DatePickerType pickerType = DatePickerType::DATE;
218     JSRef<JSObject> paramObject;
219     if (info.Length() >= 1 && info[0]->IsObject()) {
220         paramObject = JSRef<JSObject>::Cast(info[0]);
221         auto type = paramObject->GetProperty("type");
222         if (type->IsNumber()) {
223             pickerType = static_cast<DatePickerType>(type->ToNumber<int32_t>());
224         }
225     }
226     switch (pickerType) {
227         case DatePickerType::TIME: {
228             CreateTimePicker(info, paramObject);
229             break;
230         }
231         case DatePickerType::DATE: {
232             CreateDatePicker(info, paramObject);
233             break;
234         }
235         default: {
236             break;
237         }
238     }
239 }
240 
SetLunar(bool isLunar)241 void JSDatePicker::SetLunar(bool isLunar)
242 {
243     DatePickerModel::GetInstance()->SetShowLunar(isLunar);
244 }
245 
UseMilitaryTime(bool isUseMilitaryTime)246 void JSDatePicker::UseMilitaryTime(bool isUseMilitaryTime)
247 {
248     DatePickerModel::GetInstance()->SetHour24(isUseMilitaryTime);
249 }
250 
ParseTextProperties(const JSRef<JSObject> & paramObj,NG::PickerTextProperties & result)251 void JSDatePicker::ParseTextProperties(const JSRef<JSObject>& paramObj, NG::PickerTextProperties& result)
252 {
253     auto disappearProperty = paramObj->GetProperty("disappearTextStyle");
254     auto normalProperty = paramObj->GetProperty("textStyle");
255     auto selectedProperty = paramObj->GetProperty("selectedTextStyle");
256 
257     if (!disappearProperty->IsNull() && disappearProperty->IsObject()) {
258         JSRef<JSObject> disappearObj = JSRef<JSObject>::Cast(disappearProperty);
259         JSDatePicker::ParseTextStyle(disappearObj, result.disappearTextStyle_);
260     }
261 
262     if (!normalProperty->IsNull() && normalProperty->IsObject()) {
263         JSRef<JSObject> noramlObj = JSRef<JSObject>::Cast(normalProperty);
264         JSDatePicker::ParseTextStyle(noramlObj, result.normalTextStyle_);
265     }
266 
267     if (!selectedProperty->IsNull() && selectedProperty->IsObject()) {
268         JSRef<JSObject> selectedObj = JSRef<JSObject>::Cast(selectedProperty);
269         JSDatePicker::ParseTextStyle(selectedObj, result.selectedTextStyle_);
270     }
271 }
272 
ParseTextStyle(const JSRef<JSObject> & paramObj,NG::PickerTextStyle & textStyle)273 void JSDatePicker::ParseTextStyle(const JSRef<JSObject>& paramObj, NG::PickerTextStyle& textStyle)
274 {
275     auto fontColor = paramObj->GetProperty("color");
276     auto fontOptions = paramObj->GetProperty("font");
277 
278     Color textColor;
279     if (JSViewAbstract::ParseJsColor(fontColor, textColor)) {
280         textStyle.textColor = textColor;
281     }
282 
283     if (!fontOptions->IsObject()) {
284         return;
285     }
286     JSRef<JSObject> fontObj = JSRef<JSObject>::Cast(fontOptions);
287     auto fontSize = fontObj->GetProperty("size");
288     auto fontWeight = fontObj->GetProperty("weight");
289     auto fontFamily = fontObj->GetProperty("family");
290     auto fontStyle = fontObj->GetProperty("style");
291     if (fontSize->IsNull() || fontSize->IsUndefined()) {
292         textStyle.fontSize = Dimension(-1);
293     } else {
294         CalcDimension size;
295         if (!ParseJsDimensionFp(fontSize, size) || size.Unit() == DimensionUnit::PERCENT) {
296             textStyle.fontSize = Dimension(-1);
297         } else {
298             textStyle.fontSize = size;
299         }
300     }
301 
302     if (!fontWeight->IsNull() && !fontWeight->IsUndefined()) {
303         std::string weight;
304         if (fontWeight->IsNumber()) {
305             weight = std::to_string(fontWeight->ToNumber<int32_t>());
306         } else {
307             ParseJsString(fontWeight, weight);
308         }
309         textStyle.fontWeight = ConvertStrToFontWeight(weight);
310     }
311 
312     if (!fontFamily->IsNull() && !fontFamily->IsUndefined()) {
313         std::vector<std::string> families;
314         if (ParseJsFontFamilies(fontFamily, families)) {
315             textStyle.fontFamily = families;
316         }
317     }
318 
319     if (fontStyle->IsNumber()) {
320         auto style = fontStyle->ToNumber<int32_t>();
321         if (style < 0 || style > 1) {
322             return;
323         }
324         textStyle.fontStyle = static_cast<FontStyle>(style);
325     }
326 }
327 
SetDisappearTextStyle(const JSCallbackInfo & info)328 void JSDatePicker::SetDisappearTextStyle(const JSCallbackInfo& info)
329 {
330     auto theme = GetTheme<PickerTheme>();
331     CHECK_NULL_VOID(theme);
332     NG::PickerTextStyle textStyle;
333     if (info[0]->IsObject()) {
334         JSDatePicker::ParseTextStyle(info[0], textStyle);
335     }
336     DatePickerModel::GetInstance()->SetDisappearTextStyle(theme, textStyle);
337 }
338 
SetTextStyle(const JSCallbackInfo & info)339 void JSDatePicker::SetTextStyle(const JSCallbackInfo& info)
340 {
341     auto theme = GetTheme<PickerTheme>();
342     CHECK_NULL_VOID(theme);
343     NG::PickerTextStyle textStyle;
344     if (info[0]->IsObject()) {
345         JSDatePicker::ParseTextStyle(info[0], textStyle);
346     }
347     DatePickerModel::GetInstance()->SetNormalTextStyle(theme, textStyle);
348 }
349 
SetSelectedTextStyle(const JSCallbackInfo & info)350 void JSDatePicker::SetSelectedTextStyle(const JSCallbackInfo& info)
351 {
352     auto theme = GetTheme<PickerTheme>();
353     CHECK_NULL_VOID(theme);
354     NG::PickerTextStyle textStyle;
355     if (info[0]->IsObject()) {
356         JSDatePicker::ParseTextStyle(info[0], textStyle);
357     }
358     DatePickerModel::GetInstance()->SetSelectedTextStyle(theme, textStyle);
359 }
360 
OnChange(const JSCallbackInfo & info)361 void JSDatePicker::OnChange(const JSCallbackInfo& info)
362 {
363     if (!info[0]->IsFunction()) {
364         return;
365     }
366 
367     auto jsFunc = AceType::MakeRefPtr<JsEventFunction<DatePickerChangeEvent, 1>>(
368         JSRef<JSFunc>::Cast(info[0]), DatePickerChangeEventToJSValue);
369     WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
370     auto onChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
371                         const BaseEventInfo* info) {
372         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
373         ACE_SCORING_EVENT("datePicker.onChange");
374         PipelineContext::SetCallBackNode(node);
375         const auto* eventInfo = TypeInfoHelper::DynamicCast<DatePickerChangeEvent>(info);
376         func->Execute(*eventInfo);
377     };
378     DatePickerModel::GetInstance()->SetOnChange(std::move(onChange));
379 }
380 
OnDateChange(const JSCallbackInfo & info)381 void JSDatePicker::OnDateChange(const JSCallbackInfo& info)
382 {
383     if (!info[0]->IsFunction()) {
384         return;
385     }
386     auto jsFunc = AceType::MakeRefPtr<JsEventFunction<DatePickerChangeEvent, 1>>(
387         JSRef<JSFunc>::Cast(info[0]), DatePickerDateChangeEventToJSValue);
388     WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
389     auto onDateChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
390                             const BaseEventInfo* info) {
391         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
392         ACE_SCORING_EVENT("datePicker.onDateChange");
393         PipelineContext::SetCallBackNode(node);
394         const auto* eventInfo = TypeInfoHelper::DynamicCast<DatePickerChangeEvent>(info);
395         func->Execute(*eventInfo);
396     };
397     DatePickerModel::GetInstance()->SetOnDateChange(std::move(onDateChange));
398 }
399 
OnChange(const JSCallbackInfo & info)400 void JSTimePicker::OnChange(const JSCallbackInfo& info)
401 {
402     if (!info[0]->IsFunction()) {
403         return;
404     }
405 
406     auto jsFunc = AceType::MakeRefPtr<JsEventFunction<DatePickerChangeEvent, 1>>(
407         JSRef<JSFunc>::Cast(info[0]), DatePickerChangeEventToJSValue);
408     WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
409     auto onChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
410                         const BaseEventInfo* index) {
411         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
412         ACE_SCORING_EVENT("datePicker.onChange");
413         PipelineContext::SetCallBackNode(node);
414         const auto* eventInfo = TypeInfoHelper::DynamicCast<DatePickerChangeEvent>(index);
415         func->Execute(*eventInfo);
416     };
417     TimePickerModel::GetInstance()->SetOnChange(std::move(onChange));
418 }
419 
PickerBackgroundColor(const JSCallbackInfo & info)420 void JSDatePicker::PickerBackgroundColor(const JSCallbackInfo& info)
421 {
422     JSViewAbstract::JsBackgroundColor(info);
423 
424     if (info.Length() < 1) {
425         return;
426     }
427     Color backgroundColor;
428     if (!ParseJsColor(info[0], backgroundColor)) {
429         return;
430     }
431     DatePickerModel::GetInstance()->SetBackgroundColor(backgroundColor);
432 }
433 
ParseDate(const JSRef<JSVal> & dateVal)434 PickerDate JSDatePicker::ParseDate(const JSRef<JSVal>& dateVal)
435 {
436     auto pickerDate = PickerDate();
437     if (!dateVal->IsObject()) {
438         return pickerDate;
439     }
440     auto dateObj = JSRef<JSObject>::Cast(dateVal);
441     auto yearFuncJsVal = dateObj->GetProperty("getFullYear");
442     auto monthFuncJsVal = dateObj->GetProperty("getMonth");
443     auto dateFuncJsVal = dateObj->GetProperty("getDate");
444     if (!(yearFuncJsVal->IsFunction() && monthFuncJsVal->IsFunction() && dateFuncJsVal->IsFunction())) {
445         return pickerDate;
446     }
447     auto yearFunc = JSRef<JSFunc>::Cast(yearFuncJsVal);
448     auto monthFunc = JSRef<JSFunc>::Cast(monthFuncJsVal);
449     auto dateFunc = JSRef<JSFunc>::Cast(dateFuncJsVal);
450     JSRef<JSVal> year = yearFunc->Call(dateObj);
451     JSRef<JSVal> month = monthFunc->Call(dateObj);
452     JSRef<JSVal> date = dateFunc->Call(dateObj);
453 
454     if (year->IsNumber() && month->IsNumber() && date->IsNumber()) {
455         pickerDate.SetYear(year->ToNumber<int32_t>());
456         pickerDate.SetMonth(month->ToNumber<int32_t>() + 1); // 0-11 means 1 to 12 months
457         pickerDate.SetDay(date->ToNumber<int32_t>());
458     }
459     return pickerDate;
460 }
461 
ParseTime(const JSRef<JSVal> & timeVal)462 PickerTime JSDatePicker::ParseTime(const JSRef<JSVal>& timeVal)
463 {
464     auto pickerTime = PickerTime();
465     if (!timeVal->IsObject()) {
466         return pickerTime;
467     }
468     auto timeObj = JSRef<JSObject>::Cast(timeVal);
469     auto hourFuncJsVal = timeObj->GetProperty("getHours");
470     auto minuteFuncJsVal = timeObj->GetProperty("getMinutes");
471     auto secondFuncJsVal = timeObj->GetProperty("getSeconds");
472     if (!(hourFuncJsVal->IsFunction() && minuteFuncJsVal->IsFunction() && secondFuncJsVal->IsFunction())) {
473         return pickerTime;
474     }
475     auto hourFunc = JSRef<JSFunc>::Cast(hourFuncJsVal);
476     auto minuteFunc = JSRef<JSFunc>::Cast(minuteFuncJsVal);
477     auto secondFunc = JSRef<JSFunc>::Cast(secondFuncJsVal);
478     JSRef<JSVal> hour = hourFunc->Call(timeObj);
479     JSRef<JSVal> minute = minuteFunc->Call(timeObj);
480     JSRef<JSVal> second = secondFunc->Call(timeObj);
481 
482     if (hour->IsNumber() && minute->IsNumber() && second->IsNumber()) {
483         pickerTime.SetHour(hour->ToNumber<int32_t>());
484         pickerTime.SetMinute(minute->ToNumber<int32_t>());
485         pickerTime.SetSecond(second->ToNumber<int32_t>());
486     }
487     return pickerTime;
488 }
489 
ParseSelectedDateTimeObject(const JSCallbackInfo & info,const JSRef<JSObject> & selectedObject,bool isDatePicker)490 void ParseSelectedDateTimeObject(const JSCallbackInfo& info, const JSRef<JSObject>& selectedObject, bool isDatePicker)
491 {
492     JSRef<JSVal> changeEventVal = selectedObject->GetProperty("changeEvent");
493     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(changeEventVal));
494     WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
495     auto changeEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
496                            const BaseEventInfo* info) {
497         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
498         ACE_SCORING_EVENT("DatePicker.SelectedDateTimeChangeEvent");
499         const auto* eventInfo = TypeInfoHelper::DynamicCast<DatePickerChangeEvent>(info);
500         CHECK_NULL_VOID(eventInfo);
501         auto selectedStr = eventInfo->GetSelectedStr();
502         auto sourceJson = JsonUtil::ParseJsonString(selectedStr);
503         if (!sourceJson || sourceJson->IsNull()) {
504             return;
505         }
506 
507         std::tm dateTime = { 0 };
508         auto year = sourceJson->GetValue("year");
509         if (year && year->IsNumber()) {
510             dateTime.tm_year = year->GetInt() - 1900; // local date start from 1900
511         }
512         auto month = sourceJson->GetValue("month");
513         if (month && month->IsNumber()) {
514             dateTime.tm_mon = month->GetInt();
515         }
516         auto day = sourceJson->GetValue("day");
517         if (day && day->IsNumber()) {
518             dateTime.tm_mday = day->GetInt();
519         }
520         auto hour = sourceJson->GetValue("hour");
521         if (hour && hour->IsNumber()) {
522             dateTime.tm_hour = hour->GetInt();
523         }
524         auto minute = sourceJson->GetValue("minute");
525         if (minute && minute->IsNumber()) {
526             dateTime.tm_min = minute->GetInt();
527         }
528         PipelineContext::SetCallBackNode(node);
529         auto milliseconds = Date::GetMilliSecondsByDateTime(dateTime);
530         auto dateObj = JSDate::New(milliseconds);
531         func->ExecuteJS(1, &dateObj);
532     };
533     if (isDatePicker) {
534         DatePickerModel::GetInstance()->SetChangeEvent(std::move(changeEvent));
535     } else {
536         TimePickerModel::GetInstance()->SetChangeEvent(std::move(changeEvent));
537     }
538 }
539 
CreateDatePicker(const JSCallbackInfo & info,const JSRef<JSObject> & paramObj)540 void JSDatePicker::CreateDatePicker(const JSCallbackInfo& info, const JSRef<JSObject>& paramObj)
541 {
542     auto theme = GetTheme<PickerTheme>();
543     CHECK_NULL_VOID(theme);
544     JSRef<JSVal> startDate;
545     JSRef<JSVal> endDate;
546     JSRef<JSVal> selectedDate;
547     if (!paramObj->IsUndefined()) {
548         startDate = paramObj->GetProperty("start");
549         endDate = paramObj->GetProperty("end");
550         selectedDate = paramObj->GetProperty("selected");
551     }
552     auto parseStartDate = ParseDate(startDate);
553     auto parseEndDate = ParseDate(endDate);
554     if (parseStartDate.GetYear() <= 0) {
555         parseStartDate = theme->GetDefaultStartDate();
556     }
557     if (parseEndDate.GetYear() <= 0) {
558         parseEndDate = theme->GetDefaultEndDate();
559     }
560     auto startDays = parseStartDate.ToDays();
561     auto endDays = parseEndDate.ToDays();
562     if (startDays > endDays) {
563         parseStartDate = theme->GetDefaultStartDate();
564         parseEndDate = theme->GetDefaultEndDate();
565     }
566     DatePickerModel::GetInstance()->CreateDatePicker(theme);
567     if (startDate->IsObject()) {
568         DatePickerModel::GetInstance()->SetStartDate(parseStartDate);
569     }
570     if (endDate->IsObject()) {
571         DatePickerModel::GetInstance()->SetEndDate(parseEndDate);
572     }
573     if (selectedDate->IsObject()) {
574         JSRef<JSObject> selectedDateObj = JSRef<JSObject>::Cast(selectedDate);
575         JSRef<JSVal> changeEventVal = selectedDateObj->GetProperty("changeEvent");
576         PickerDate parseSelectedDate;
577         if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
578             ParseSelectedDateTimeObject(info, selectedDateObj, true);
579             parseSelectedDate = ParseDate(selectedDateObj->GetProperty("value"));
580         } else {
581             parseSelectedDate = ParseDate(selectedDate);
582         }
583         DatePickerModel::GetInstance()->SetSelectedDate(parseSelectedDate);
584     }
585     SetDefaultAttributes();
586 }
587 
SetDefaultAttributes()588 void JSDatePicker::SetDefaultAttributes()
589 {
590     auto theme = GetTheme<PickerTheme>();
591     CHECK_NULL_VOID(theme);
592     NG::PickerTextStyle textStyle;
593     auto selectedStyle = theme->GetOptionStyle(true, false);
594     textStyle.textColor = selectedStyle.GetTextColor();
595     textStyle.fontSize = selectedStyle.GetFontSize();
596     textStyle.fontWeight = selectedStyle.GetFontWeight();
597     DatePickerModel::GetInstance()->SetSelectedTextStyle(theme, textStyle);
598 
599     auto disappearStyle = theme->GetDisappearOptionStyle();
600     textStyle.textColor = disappearStyle.GetTextColor();
601     textStyle.fontSize = disappearStyle.GetFontSize();
602     textStyle.fontWeight = disappearStyle.GetFontWeight();
603     DatePickerModel::GetInstance()->SetDisappearTextStyle(theme, textStyle);
604 
605     auto normalStyle = theme->GetOptionStyle(false, false);
606     textStyle.textColor = normalStyle.GetTextColor();
607     textStyle.fontSize = normalStyle.GetFontSize();
608     textStyle.fontWeight = normalStyle.GetFontWeight();
609     DatePickerModel::GetInstance()->SetNormalTextStyle(theme, textStyle);
610 }
611 
CreateTimePicker(const JSCallbackInfo & info,const JSRef<JSObject> & paramObj)612 void JSDatePicker::CreateTimePicker(const JSCallbackInfo& info, const JSRef<JSObject>& paramObj)
613 {
614     auto theme = GetTheme<PickerTheme>();
615     CHECK_NULL_VOID(theme);
616     DatePickerModel::GetInstance()->CreateTimePicker(theme);
617     auto selectedTime = paramObj->GetProperty("selected");
618     if (selectedTime->IsObject()) {
619         JSRef<JSObject> selectedTimeObj = JSRef<JSObject>::Cast(selectedTime);
620         JSRef<JSVal> changeEventVal = selectedTimeObj->GetProperty("changeEvent");
621         if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
622             ParseSelectedDateTimeObject(info, selectedTimeObj, true);
623             auto parseSelectedTime = ParseTime(selectedTimeObj->GetProperty("value"));
624             DatePickerModel::GetInstance()->SetSelectedTime(parseSelectedTime);
625         } else {
626             DatePickerModel::GetInstance()->SetSelectedTime(ParseTime(selectedTime));
627         }
628     }
629 }
630 
JSBind(BindingTarget globalObj)631 void JSDatePickerDialog::JSBind(BindingTarget globalObj)
632 {
633     JSClass<JSDatePickerDialog>::Declare("DatePickerDialog");
634     JSClass<JSDatePickerDialog>::StaticMethod("show", &JSDatePickerDialog::Show);
635 
636     JSClass<JSDatePickerDialog>::Bind<>(globalObj);
637 }
638 
Show(const JSCallbackInfo & info)639 void JSDatePickerDialog::Show(const JSCallbackInfo& info)
640 {
641     auto scopedDelegate = EngineHelper::GetCurrentDelegateSafely();
642     CHECK_NULL_VOID(scopedDelegate);
643     if (!info[0]->IsObject()) {
644         return;
645     }
646     auto theme = GetTheme<PickerTheme>();
647     CHECK_NULL_VOID(theme);
648 
649     auto paramObject = JSRef<JSObject>::Cast(info[0]);
650     DatePickerType pickerType = DatePickerType::DATE;
651     auto type = paramObject->GetProperty("type");
652     if (type->IsNumber()) {
653         pickerType = static_cast<DatePickerType>(type->ToNumber<int32_t>());
654     }
655     std::function<void()> cancelEvent;
656     std::function<void(const std::string&)> acceptEvent;
657     std::function<void(const std::string&)> changeEvent;
658     std::function<void(const std::string&)> dateChangeEvent;
659     std::function<void(const std::string&)> dateAcceptEvent;
660     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
661     auto onChange = paramObject->GetProperty("onChange");
662     if (!onChange->IsUndefined() && onChange->IsFunction()) {
663         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onChange));
664         changeEvent = [execCtx = info.GetExecutionContext(), type = pickerType, func = std::move(jsFunc),
665                           node = frameNode](const std::string& info) {
666             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
667             std::vector<std::string> keys;
668             keys = { "year", "month", "day" };
669             ACE_SCORING_EVENT("DatePickerDialog.onChange");
670             PipelineContext::SetCallBackNode(node);
671             func->Execute(keys, info);
672         };
673     }
674     auto onAccept = paramObject->GetProperty("onAccept");
675     if (!onAccept->IsUndefined() && onAccept->IsFunction()) {
676         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onAccept));
677         acceptEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode](
678                           const std::string& info) {
679             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
680             std::vector<std::string> keys = { "year", "month", "day", "hour", "minute", "second" };
681             ACE_SCORING_EVENT("DatePickerDialog.onAccept");
682             PipelineContext::SetCallBackNode(node);
683             func->Execute(keys, info);
684         };
685     }
686     auto onCancel = paramObject->GetProperty("onCancel");
687     if (!onCancel->IsUndefined() && onCancel->IsFunction()) {
688         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onCancel));
689         cancelEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode]() {
690             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
691             ACE_SCORING_EVENT("DatePickerDialog.onCancel");
692             PipelineContext::SetCallBackNode(node);
693             func->Execute();
694         };
695     }
696     auto onDateChange = paramObject->GetProperty("onDateChange");
697     if (!onDateChange->IsUndefined() && onDateChange->IsFunction()) {
698         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onDateChange));
699         dateChangeEvent = [execCtx = info.GetExecutionContext(), type = pickerType, func = std::move(jsFunc),
700                               node = frameNode](const std::string& info) {
701             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
702             ACE_SCORING_EVENT("DatePickerDialog.onDateChange");
703             auto selectedJson = JsonUtil::ParseJsonString(info);
704             if (!selectedJson || selectedJson->IsNull()) {
705                 return;
706             }
707             std::tm dateTime = { 0 };
708             auto year = selectedJson->GetValue("year");
709             if (year && year->IsNumber()) {
710                 dateTime.tm_year = year->GetInt() - 1900; // local date start from 1900
711             }
712             auto month = selectedJson->GetValue("month");
713             if (month && month->IsNumber()) {
714                 dateTime.tm_mon = month->GetInt();
715             }
716             auto day = selectedJson->GetValue("day");
717             if (day && day->IsNumber()) {
718                 dateTime.tm_mday = day->GetInt();
719             }
720             auto hour = selectedJson->GetValue("hour");
721             if (hour && hour->IsNumber()) {
722                 dateTime.tm_hour = hour->GetInt();
723             }
724             auto minute = selectedJson->GetValue("minute");
725             if (minute && minute->IsNumber()) {
726                 dateTime.tm_min = minute->GetInt();
727             }
728             auto milliseconds = Date::GetMilliSecondsByDateTime(dateTime);
729             auto dateObj = JSDate::New(milliseconds);
730             PipelineContext::SetCallBackNode(node);
731             func->ExecuteJS(1, &dateObj);
732         };
733     }
734     auto onDateAccept = paramObject->GetProperty("onDateAccept");
735     if (!onDateAccept->IsUndefined() && onDateAccept->IsFunction()) {
736         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onDateAccept));
737         dateAcceptEvent = [execCtx = info.GetExecutionContext(), type = pickerType, func = std::move(jsFunc),
738                               node = frameNode](const std::string& info) {
739             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
740             ACE_SCORING_EVENT("DatePickerDialog.onDateAccept");
741             auto selectedJson = JsonUtil::ParseJsonString(info);
742             if (!selectedJson || selectedJson->IsNull()) {
743                 return;
744             }
745             std::tm dateTime = { 0 };
746             auto year = selectedJson->GetValue("year");
747             if (year && year->IsNumber()) {
748                 dateTime.tm_year = year->GetInt() - 1900; // local date start from 1900
749             }
750             auto month = selectedJson->GetValue("month");
751             if (month && month->IsNumber()) {
752                 dateTime.tm_mon = month->GetInt();
753             }
754             auto day = selectedJson->GetValue("day");
755             if (day && day->IsNumber()) {
756                 dateTime.tm_mday = day->GetInt();
757             }
758             auto hour = selectedJson->GetValue("hour");
759             if (hour && hour->IsNumber()) {
760                 dateTime.tm_hour = hour->GetInt();
761             }
762             auto minute = selectedJson->GetValue("minute");
763             if (minute && minute->IsNumber()) {
764                 dateTime.tm_min = minute->GetInt();
765             }
766             auto milliseconds = Date::GetMilliSecondsByDateTime(dateTime);
767             auto dateObj = JSDate::New(milliseconds);
768             PipelineContext::SetCallBackNode(node);
769             func->ExecuteJS(1, &dateObj);
770         };
771     }
772     NG::DatePickerSettingData settingData;
773     PickerDialogInfo pickerDialog;
774     auto startDate = paramObject->GetProperty("start");
775     if (startDate->IsObject()) {
776         pickerDialog.isStartDate = true;
777     }
778     auto endDate = paramObject->GetProperty("end");
779     if (endDate->IsObject()) {
780         pickerDialog.isEndDate = true;
781     }
782     auto selectedDate = paramObject->GetProperty("selected");
783     if (selectedDate->IsObject()) {
784         pickerDialog.isSelectedDate = true;
785     }
786     auto lunar = paramObject->GetProperty("lunar");
787     auto lunarSwitch = paramObject->GetProperty("lunarSwitch");
788     auto sTime = paramObject->GetProperty("showTime");
789     auto useMilitary = paramObject->GetProperty("useMilitaryTime");
790     settingData.isLunar = lunar->ToBoolean();
791     settingData.lunarswitch = lunarSwitch->ToBoolean();
792     settingData.showTime = sTime->ToBoolean();
793     settingData.useMilitary = useMilitary->ToBoolean();
794     auto parseStartDate = ParseDate(startDate);
795     auto parseEndDate = ParseDate(endDate);
796     if (parseStartDate.GetYear() <= 0) {
797         parseStartDate = theme->GetDefaultStartDate();
798     }
799     if (parseEndDate.GetYear() <= 0) {
800         parseEndDate = theme->GetDefaultEndDate();
801     }
802     auto startDays = parseStartDate.ToDays();
803     auto endDays = parseEndDate.ToDays();
804     if (startDays > endDays) {
805         parseStartDate = theme->GetDefaultStartDate();
806         parseEndDate = theme->GetDefaultEndDate();
807     }
808     pickerDialog.parseStartDate = parseStartDate;
809     pickerDialog.parseEndDate = parseEndDate;
810     pickerDialog.parseSelectedDate = ParseDate(selectedDate);
811     pickerDialog.pickerTime = ParseTime(selectedDate);
812     JSDatePicker::ParseTextProperties(paramObject, settingData.properties);
813 
814     // Parse alignment
815     auto alignmentValue = paramObject->GetProperty("alignment");
816     if (alignmentValue->IsNumber()) {
817         auto alignment = alignmentValue->ToNumber<int32_t>();
818         if (alignment >= 0 && alignment <= static_cast<int32_t>(DIALOG_ALIGNMENT.size())) {
819             pickerDialog.alignment = DIALOG_ALIGNMENT[alignment];
820         }
821         if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
822             if (alignment == static_cast<int32_t>(DialogAlignment::TOP) ||
823                 alignment == static_cast<int32_t>(DialogAlignment::TOP_START) ||
824                 alignment == static_cast<int32_t>(DialogAlignment::TOP_END)) {
825                 pickerDialog.offset = DATEPICKER_OFFSET_DEFAULT_TOP;
826             }
827         }
828     }
829 
830     // Parse offset
831     auto offsetValue = paramObject->GetProperty("offset");
832     if (offsetValue->IsObject()) {
833         auto offsetObj = JSRef<JSObject>::Cast(offsetValue);
834         CalcDimension dx;
835         auto dxValue = offsetObj->GetProperty("dx");
836         ParseJsDimensionVp(dxValue, dx);
837         CalcDimension dy;
838         auto dyValue = offsetObj->GetProperty("dy");
839         ParseJsDimensionVp(dyValue, dy);
840         pickerDialog.offset = DimensionOffset(dx, dy);
841     }
842 
843     // Parse maskRect.
844     auto maskRectValue = paramObject->GetProperty("maskRect");
845     DimensionRect maskRect;
846     if (JSViewAbstract::ParseJsDimensionRect(maskRectValue, maskRect)) {
847         pickerDialog.maskRect = maskRect;
848     }
849 
850     auto backgroundColorValue = paramObject->GetProperty("backgroundColor");
851     Color backgroundColor;
852     if (JSViewAbstract::ParseJsColor(backgroundColorValue, backgroundColor)) {
853         pickerDialog.backgroundColor = backgroundColor;
854     }
855 
856     auto backgroundBlurStyle = paramObject->GetProperty("backgroundBlurStyle");
857     BlurStyleOption styleOption;
858     if (backgroundBlurStyle->IsNumber()) {
859         auto blurStyle = backgroundBlurStyle->ToNumber<int32_t>();
860         if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
861             blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
862             pickerDialog.backgroundBlurStyle = blurStyle;
863         }
864     }
865 
866     DatePickerDialogModel::GetInstance()->SetDatePickerDialogShow(pickerDialog, settingData, std::move(cancelEvent),
867         std::move(acceptEvent), std::move(changeEvent), std::move(dateAcceptEvent), std::move(dateChangeEvent),
868         pickerType);
869 }
870 
DatePickerDialogShow(const JSRef<JSObject> & paramObj,const std::map<std::string,NG::DialogEvent> & dialogEvent,const std::map<std::string,NG::DialogGestureEvent> & dialogCancelEvent)871 void JSDatePickerDialog::DatePickerDialogShow(const JSRef<JSObject>& paramObj,
872     const std::map<std::string, NG::DialogEvent>& dialogEvent,
873     const std::map<std::string, NG::DialogGestureEvent>& dialogCancelEvent)
874 {
875     auto container = Container::CurrentSafely();
876     if (!container) {
877         return;
878     }
879     auto pipelineContext = AccessibilityManager::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
880     if (!pipelineContext) {
881         return;
882     }
883 
884     auto executor = pipelineContext->GetTaskExecutor();
885     if (!executor) {
886         return;
887     }
888 
889     NG::DatePickerSettingData settingData;
890     auto startDate = paramObj->GetProperty("start");
891     auto endDate = paramObj->GetProperty("end");
892     auto selectedDate = paramObj->GetProperty("selected");
893     auto lunar = paramObj->GetProperty("lunar");
894     auto sTime = paramObj->GetProperty("showTime");
895     auto useMilitary = paramObj->GetProperty("useMilitaryTime");
896     settingData.isLunar = lunar->ToBoolean();
897     settingData.showTime = sTime->ToBoolean();
898     settingData.useMilitary = useMilitary->ToBoolean();
899     auto parseStartDate = ParseDate(startDate);
900     auto parseEndDate = ParseDate(endDate);
901     auto parseSelectedDate = ParseDate(selectedDate);
902 
903     auto theme = GetTheme<DialogTheme>();
904     CHECK_NULL_VOID(theme);
905 
906     ButtonInfo buttonInfo;
907     DialogProperties properties;
908     if (SystemProperties::GetDeviceType() == DeviceType::PHONE) {
909         properties.alignment = DialogAlignment::BOTTOM;
910         if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
911             properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx()));
912         }
913     } else {
914         properties.alignment = DialogAlignment::CENTER;
915     }
916     properties.customStyle = false;
917     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
918         properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx()));
919     }
920 
921     std::map<std::string, PickerDate> datePickerProperty;
922     std::map<std::string, PickerTime> timePickerProperty;
923     if (startDate->IsObject()) {
924         settingData.datePickerProperty["start"] = parseStartDate;
925     }
926     if (endDate->IsObject()) {
927         settingData.datePickerProperty["end"] = parseEndDate;
928     }
929     if (selectedDate->IsObject()) {
930         settingData.datePickerProperty["selected"] = parseSelectedDate;
931         settingData.timePickerProperty["selected"] = ParseTime(selectedDate);
932     }
933 
934     JSDatePicker::ParseTextProperties(paramObj, settingData.properties);
935     auto context = AccessibilityManager::DynamicCast<NG::PipelineContext>(pipelineContext);
936     auto overlayManager = context ? context->GetOverlayManager() : nullptr;
937     executor->PostTask(
938         [properties, settingData, dialogEvent, dialogCancelEvent, weak = WeakPtr<NG::OverlayManager>(overlayManager)] {
939             auto overlayManager = weak.Upgrade();
940             CHECK_NULL_VOID(overlayManager);
941             overlayManager->ShowDateDialog(properties, settingData, dialogEvent, dialogCancelEvent);
942         },
943         TaskExecutor::TaskType::UI);
944 }
945 
CreateDatePicker(RefPtr<Component> & component,const JSRef<JSObject> & paramObj)946 void JSDatePickerDialog::CreateDatePicker(RefPtr<Component>& component, const JSRef<JSObject>& paramObj)
947 {
948     auto datePicker = AceType::MakeRefPtr<PickerDateComponent>();
949     auto startDate = paramObj->GetProperty("start");
950     auto endDate = paramObj->GetProperty("end");
951     auto selectedDate = paramObj->GetProperty("selected");
952     auto lunar = paramObj->GetProperty("lunar");
953     bool isLunar = lunar->ToBoolean();
954     auto parseStartDate = ParseDate(startDate);
955     auto parseEndDate = ParseDate(endDate);
956     auto parseSelectedDate = ParseDate(selectedDate);
957     auto startDays = parseStartDate.ToDays();
958     auto endDays = parseEndDate.ToDays();
959     if (startDays > endDays) {
960         parseStartDate.SetYear(0);
961         parseEndDate.SetYear(0);
962     }
963     if (startDate->IsObject()) {
964         datePicker->SetStartDate(parseStartDate);
965     }
966     if (endDate->IsObject()) {
967         datePicker->SetEndDate(parseEndDate);
968     }
969     if (selectedDate->IsObject()) {
970         datePicker->SetSelectedDate(parseSelectedDate);
971     }
972     datePicker->SetIsDialog(true);
973     datePicker->SetIsCreateDialogComponent(true);
974     datePicker->SetShowLunar(isLunar);
975 
976     component = datePicker;
977 }
978 
CreateTimePicker(RefPtr<Component> & component,const JSRef<JSObject> & paramObj)979 void JSDatePickerDialog::CreateTimePicker(RefPtr<Component>& component, const JSRef<JSObject>& paramObj)
980 {
981     auto timePicker = AceType::MakeRefPtr<PickerTimeComponent>();
982     auto selectedTime = paramObj->GetProperty("selected");
983     auto useMilitaryTime = paramObj->GetProperty("useMilitaryTime");
984     bool isUseMilitaryTime = useMilitaryTime->ToBoolean();
985     if (selectedTime->IsObject()) {
986         timePicker->SetSelectedTime(ParseTime(selectedTime));
987     }
988     timePicker->SetIsDialog(true);
989     timePicker->SetIsCreateDialogComponent(true);
990     timePicker->SetHour24(isUseMilitaryTime);
991     component = timePicker;
992 }
993 
ParseDate(const JSRef<JSVal> & dateVal)994 PickerDate JSDatePickerDialog::ParseDate(const JSRef<JSVal>& dateVal)
995 {
996     auto pickerDate = PickerDate();
997     if (!dateVal->IsObject()) {
998         return pickerDate;
999     }
1000     auto dateObj = JSRef<JSObject>::Cast(dateVal);
1001     auto yearFunc = JSRef<JSFunc>::Cast(dateObj->GetProperty("getFullYear"));
1002     auto monthFunc = JSRef<JSFunc>::Cast(dateObj->GetProperty("getMonth"));
1003     auto dateFunc = JSRef<JSFunc>::Cast(dateObj->GetProperty("getDate"));
1004     JSRef<JSVal> year = yearFunc->Call(dateObj);
1005     JSRef<JSVal> month = monthFunc->Call(dateObj);
1006     JSRef<JSVal> date = dateFunc->Call(dateObj);
1007 
1008     if (year->IsNumber() && month->IsNumber() && date->IsNumber()) {
1009         pickerDate.SetYear(year->ToNumber<int32_t>());
1010         pickerDate.SetMonth(month->ToNumber<int32_t>() + 1); // 0-11 means 1 to 12 months
1011         pickerDate.SetDay(date->ToNumber<int32_t>());
1012     }
1013     return pickerDate;
1014 }
1015 
ParseTime(const JSRef<JSVal> & timeVal)1016 PickerTime JSDatePickerDialog::ParseTime(const JSRef<JSVal>& timeVal)
1017 {
1018     auto pickerTime = PickerTime();
1019     if (!timeVal->IsObject()) {
1020         return pickerTime;
1021     }
1022     auto timeObj = JSRef<JSObject>::Cast(timeVal);
1023     auto hourFunc = JSRef<JSFunc>::Cast(timeObj->GetProperty("getHours"));
1024     auto minuteFunc = JSRef<JSFunc>::Cast(timeObj->GetProperty("getMinutes"));
1025     auto secondFunc = JSRef<JSFunc>::Cast(timeObj->GetProperty("getSeconds"));
1026     JSRef<JSVal> hour = hourFunc->Call(timeObj);
1027     JSRef<JSVal> minute = minuteFunc->Call(timeObj);
1028     JSRef<JSVal> second = secondFunc->Call(timeObj);
1029 
1030     if (hour->IsNumber() && minute->IsNumber() && second->IsNumber()) {
1031         pickerTime.SetHour(hour->ToNumber<int32_t>());
1032         pickerTime.SetMinute(minute->ToNumber<int32_t>());
1033         pickerTime.SetSecond(second->ToNumber<int32_t>());
1034     }
1035     return pickerTime;
1036 }
1037 
JSBind(BindingTarget globalObj)1038 void JSTimePicker::JSBind(BindingTarget globalObj)
1039 {
1040     JSClass<JSTimePicker>::Declare("TimePicker");
1041     MethodOptions opt = MethodOptions::NONE;
1042     JSClass<JSTimePicker>::StaticMethod("create", &JSTimePicker::Create, opt);
1043     JSClass<JSTimePicker>::StaticMethod("onChange", &JSTimePicker::OnChange);
1044     JSClass<JSTimePicker>::StaticMethod("backgroundColor", &JSTimePicker::PickerBackgroundColor);
1045     JSClass<JSTimePicker>::StaticMethod("loop", &JSTimePicker::Loop);
1046     JSClass<JSTimePicker>::StaticMethod("useMilitaryTime", &JSTimePicker::UseMilitaryTime);
1047     JSClass<JSTimePicker>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
1048     JSClass<JSTimePicker>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
1049     JSClass<JSTimePicker>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
1050     JSClass<JSTimePicker>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
1051     JSClass<JSTimePicker>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
1052     JSClass<JSTimePicker>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
1053     JSClass<JSTimePicker>::StaticMethod("disappearTextStyle", &JSTimePicker::SetDisappearTextStyle);
1054     JSClass<JSTimePicker>::StaticMethod("textStyle", &JSTimePicker::SetTextStyle);
1055     JSClass<JSTimePicker>::StaticMethod("selectedTextStyle", &JSTimePicker::SetSelectedTextStyle);
1056     JSClass<JSTimePicker>::InheritAndBind<JSViewAbstract>(globalObj);
1057 }
1058 
Create(const JSCallbackInfo & info)1059 void JSTimePicker::Create(const JSCallbackInfo& info)
1060 {
1061     JSRef<JSObject> paramObject = JSRef<JSObject>::New();
1062     if (info.Length() >= 1 && info[0]->IsObject()) {
1063         paramObject = JSRef<JSObject>::Cast(info[0]);
1064     }
1065     CreateTimePicker(info, paramObject);
1066 }
1067 
Loop(bool isLoop)1068 void JSTimePicker::Loop(bool isLoop)
1069 {
1070     TimePickerModel::GetInstance()->SetWheelModeEnabled(isLoop);
1071 }
1072 
UseMilitaryTime(bool isUseMilitaryTime)1073 void JSTimePicker::UseMilitaryTime(bool isUseMilitaryTime)
1074 {
1075     TimePickerModel::GetInstance()->SetHour24(isUseMilitaryTime);
1076 }
1077 
PickerBackgroundColor(const JSCallbackInfo & info)1078 void JSTimePicker::PickerBackgroundColor(const JSCallbackInfo& info)
1079 {
1080     JSViewAbstract::JsBackgroundColor(info);
1081 
1082     if (info.Length() < 1) {
1083         return;
1084     }
1085     Color backgroundColor;
1086     if (!ParseJsColor(info[0], backgroundColor)) {
1087         return;
1088     }
1089     TimePickerModel::GetInstance()->SetBackgroundColor(backgroundColor);
1090 }
1091 
SetDisappearTextStyle(const JSCallbackInfo & info)1092 void JSTimePicker::SetDisappearTextStyle(const JSCallbackInfo& info)
1093 {
1094     auto theme = GetTheme<PickerTheme>();
1095     CHECK_NULL_VOID(theme);
1096     NG::PickerTextStyle textStyle;
1097     if (info[0]->IsObject()) {
1098         JSDatePicker::ParseTextStyle(info[0], textStyle);
1099     }
1100     TimePickerModel::GetInstance()->SetDisappearTextStyle(theme, textStyle);
1101 }
1102 
SetTextStyle(const JSCallbackInfo & info)1103 void JSTimePicker::SetTextStyle(const JSCallbackInfo& info)
1104 {
1105     auto theme = GetTheme<PickerTheme>();
1106     CHECK_NULL_VOID(theme);
1107     NG::PickerTextStyle textStyle;
1108     if (info[0]->IsObject()) {
1109         JSDatePicker::ParseTextStyle(info[0], textStyle);
1110     }
1111     TimePickerModel::GetInstance()->SetNormalTextStyle(theme, textStyle);
1112 }
1113 
SetSelectedTextStyle(const JSCallbackInfo & info)1114 void JSTimePicker::SetSelectedTextStyle(const JSCallbackInfo& info)
1115 {
1116     auto theme = GetTheme<PickerTheme>();
1117     CHECK_NULL_VOID(theme);
1118     NG::PickerTextStyle textStyle;
1119     if (info[0]->IsObject()) {
1120         JSDatePicker::ParseTextStyle(info[0], textStyle);
1121     }
1122     TimePickerModel::GetInstance()->SetSelectedTextStyle(theme, textStyle);
1123 }
1124 
CreateTimePicker(const JSCallbackInfo & info,const JSRef<JSObject> & paramObj)1125 void JSTimePicker::CreateTimePicker(const JSCallbackInfo& info, const JSRef<JSObject>& paramObj)
1126 {
1127     auto selectedTime = paramObj->GetProperty("selected");
1128     auto theme = GetTheme<PickerTheme>();
1129     CHECK_NULL_VOID(theme);
1130     auto formatValue = paramObj->GetProperty("format");
1131     bool showSecond = false;
1132     if (formatValue->IsNumber()) {
1133         auto displayedFormat = static_cast<TimePickerFormat>(formatValue->ToNumber<int32_t>());
1134         if (displayedFormat == TimePickerFormat::HOUR_MINUTE_SECOND) {
1135             showSecond = true;
1136         }
1137     }
1138     TimePickerModel::GetInstance()->CreateTimePicker(theme, showSecond);
1139     if (selectedTime->IsObject()) {
1140         JSRef<JSObject> selectedTimeObj = JSRef<JSObject>::Cast(selectedTime);
1141         JSRef<JSVal> changeEventVal = selectedTimeObj->GetProperty("changeEvent");
1142         if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
1143             ParseSelectedDateTimeObject(info, selectedTimeObj, false);
1144             auto parseSelectedTime = ParseTime(selectedTimeObj->GetProperty("value"));
1145             TimePickerModel::GetInstance()->SetSelectedTime(parseSelectedTime);
1146         } else {
1147             TimePickerModel::GetInstance()->SetSelectedTime(ParseTime(selectedTime));
1148         }
1149     }
1150     SetDefaultAttributes();
1151 }
1152 
SetDefaultAttributes()1153 void JSTimePicker::SetDefaultAttributes()
1154 {
1155     auto theme = GetTheme<PickerTheme>();
1156     CHECK_NULL_VOID(theme);
1157     NG::PickerTextStyle textStyle;
1158     auto selectedStyle = theme->GetOptionStyle(true, false);
1159     textStyle.textColor = selectedStyle.GetTextColor();
1160     textStyle.fontSize = selectedStyle.GetFontSize();
1161     textStyle.fontWeight = selectedStyle.GetFontWeight();
1162     TimePickerModel::GetInstance()->SetSelectedTextStyle(theme, textStyle);
1163 
1164     auto disappearStyle = theme->GetDisappearOptionStyle();
1165     textStyle.textColor = disappearStyle.GetTextColor();
1166     textStyle.fontSize = disappearStyle.GetFontSize();
1167     textStyle.fontWeight = disappearStyle.GetFontWeight();
1168     TimePickerModel::GetInstance()->SetDisappearTextStyle(theme, textStyle);
1169 
1170     auto normalStyle = theme->GetOptionStyle(false, false);
1171     textStyle.textColor = normalStyle.GetTextColor();
1172     textStyle.fontSize = normalStyle.GetFontSize();
1173     textStyle.fontWeight = normalStyle.GetFontWeight();
1174     TimePickerModel::GetInstance()->SetNormalTextStyle(theme, textStyle);
1175 }
1176 
ParseTime(const JSRef<JSVal> & timeVal)1177 PickerTime JSTimePicker::ParseTime(const JSRef<JSVal>& timeVal)
1178 {
1179     auto pickerTime = PickerTime::Current();
1180     if (!timeVal->IsObject()) {
1181         return pickerTime;
1182     }
1183     auto timeObj = JSRef<JSObject>::Cast(timeVal);
1184     auto yearFuncJsVal = timeObj->GetProperty("getFullYear");
1185     if (yearFuncJsVal->IsFunction()) {
1186         auto yearFunc = JSRef<JSFunc>::Cast(yearFuncJsVal);
1187         JSRef<JSVal> year = yearFunc->Call(timeObj);
1188         if (year->IsNumber() && LessOrEqual(year->ToNumber<int32_t>(), 0)) {
1189             return pickerTime;
1190         }
1191     }
1192 
1193     auto hourFuncJsVal = timeObj->GetProperty("getHours");
1194     auto minuteFuncJsVal = timeObj->GetProperty("getMinutes");
1195     auto secondFuncJsVal = timeObj->GetProperty("getSeconds");
1196     if (!(hourFuncJsVal->IsFunction() && minuteFuncJsVal->IsFunction() && secondFuncJsVal->IsFunction())) {
1197         return pickerTime;
1198     }
1199     auto hourFunc = JSRef<JSFunc>::Cast(hourFuncJsVal);
1200     auto minuteFunc = JSRef<JSFunc>::Cast(minuteFuncJsVal);
1201     auto secondFunc = JSRef<JSFunc>::Cast(secondFuncJsVal);
1202     JSRef<JSVal> hour = hourFunc->Call(timeObj);
1203     JSRef<JSVal> minute = minuteFunc->Call(timeObj);
1204     JSRef<JSVal> second = secondFunc->Call(timeObj);
1205 
1206     if (hour->IsNumber() && minute->IsNumber() && second->IsNumber()) {
1207         pickerTime.SetHour(hour->ToNumber<int32_t>());
1208         pickerTime.SetMinute(minute->ToNumber<int32_t>());
1209         pickerTime.SetSecond(second->ToNumber<int32_t>());
1210     }
1211     return pickerTime;
1212 }
1213 
JSBind(BindingTarget globalObj)1214 void JSTimePickerDialog::JSBind(BindingTarget globalObj)
1215 {
1216     JSClass<JSTimePickerDialog>::Declare("TimePickerDialog");
1217     JSClass<JSTimePickerDialog>::StaticMethod("show", &JSTimePickerDialog::Show);
1218 
1219     JSClass<JSTimePickerDialog>::Bind<>(globalObj);
1220 }
1221 
Show(const JSCallbackInfo & info)1222 void JSTimePickerDialog::Show(const JSCallbackInfo& info)
1223 {
1224     auto scopedDelegate = EngineHelper::GetCurrentDelegateSafely();
1225     CHECK_NULL_VOID(scopedDelegate);
1226     if (!info[0]->IsObject()) {
1227         return;
1228     }
1229     auto paramObject = JSRef<JSObject>::Cast(info[0]);
1230     std::function<void()> cancelEvent;
1231     std::function<void(const std::string&)> acceptEvent;
1232     std::function<void(const std::string&)> changeEvent;
1233     WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
1234     auto onChange = paramObject->GetProperty("onChange");
1235     if (!onChange->IsUndefined() && onChange->IsFunction()) {
1236         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onChange));
1237         changeEvent = [execCtx = info.GetExecutionContext(), type = DatePickerType::TIME, func = std::move(jsFunc),
1238                           node = targetNode](const std::string& info) {
1239             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1240             std::vector<std::string> keys;
1241             keys = { "hour", "minute" };
1242             ACE_SCORING_EVENT("DatePickerDialog.onChange");
1243             PipelineContext::SetCallBackNode(node);
1244             func->Execute(keys, info);
1245         };
1246     }
1247     auto onAccept = paramObject->GetProperty("onAccept");
1248     if (!onAccept->IsUndefined() && onAccept->IsFunction()) {
1249         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onAccept));
1250         acceptEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
1251                           const std::string& info) {
1252             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1253             std::vector<std::string> keys = { "year", "month", "day", "hour", "minute", "second" };
1254             ACE_SCORING_EVENT("DatePickerDialog.onAccept");
1255             PipelineContext::SetCallBackNode(node);
1256             func->Execute(keys, info);
1257         };
1258     }
1259     auto onCancel = paramObject->GetProperty("onCancel");
1260     if (!onCancel->IsUndefined() && onCancel->IsFunction()) {
1261         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onCancel));
1262         cancelEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]() {
1263             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1264             ACE_SCORING_EVENT("DatePickerDialog.onCancel");
1265             PipelineContext::SetCallBackNode(node);
1266             func->Execute();
1267         };
1268     }
1269     auto selectedTime = paramObject->GetProperty("selected");
1270     auto useMilitaryTime = paramObject->GetProperty("useMilitaryTime");
1271     NG::TimePickerSettingData settingData;
1272     PickerDialogInfo pickerDialog;
1273     settingData.isUseMilitaryTime = useMilitaryTime->ToBoolean();
1274     pickerDialog.isUseMilitaryTime = useMilitaryTime->ToBoolean();
1275     if (selectedTime->IsObject()) {
1276         PickerDate dialogTitleDate = ParseDate(selectedTime);
1277         if (dialogTitleDate.GetYear() != 0) {
1278             settingData.dialogTitleDate = dialogTitleDate;
1279             pickerDialog.isSelectedTime = true;
1280             pickerDialog.pickerTime = ParseTime(selectedTime);
1281         }
1282     }
1283     JSDatePicker::ParseTextProperties(paramObject, settingData.properties);
1284 
1285     // Parse alignment
1286     auto alignmentValue = paramObject->GetProperty("alignment");
1287     if (alignmentValue->IsNumber()) {
1288         auto alignment = alignmentValue->ToNumber<int32_t>();
1289         if (alignment >= 0 && alignment <= static_cast<int32_t>(DIALOG_ALIGNMENT.size())) {
1290             pickerDialog.alignment = DIALOG_ALIGNMENT[alignment];
1291         }
1292         if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1293             if (alignment == static_cast<int32_t>(DialogAlignment::TOP) ||
1294                 alignment == static_cast<int32_t>(DialogAlignment::TOP_START) ||
1295                 alignment == static_cast<int32_t>(DialogAlignment::TOP_END)) {
1296                 pickerDialog.offset = DATEPICKER_OFFSET_DEFAULT_TOP;
1297             }
1298         }
1299     }
1300 
1301     // Parse offset
1302     auto offsetValue = paramObject->GetProperty("offset");
1303     if (offsetValue->IsObject()) {
1304         auto offsetObj = JSRef<JSObject>::Cast(offsetValue);
1305         CalcDimension dx;
1306         auto dxValue = offsetObj->GetProperty("dx");
1307         JSAlertDialog::ParseJsDimensionVp(dxValue, dx);
1308         CalcDimension dy;
1309         auto dyValue = offsetObj->GetProperty("dy");
1310         JSAlertDialog::ParseJsDimensionVp(dyValue, dy);
1311         pickerDialog.offset = DimensionOffset(dx, dy);
1312     }
1313 
1314     // Parse maskRect.
1315     auto maskRectValue = paramObject->GetProperty("maskRect");
1316     DimensionRect maskRect;
1317     if (JSViewAbstract::ParseJsDimensionRect(maskRectValue, maskRect)) {
1318         pickerDialog.maskRect = maskRect;
1319     }
1320 
1321     auto backgroundColorValue = paramObject->GetProperty("backgroundColor");
1322     Color backgroundColor;
1323     if (JSViewAbstract::ParseJsColor(backgroundColorValue, backgroundColor)) {
1324         pickerDialog.backgroundColor = backgroundColor;
1325     }
1326 
1327     auto backgroundBlurStyle = paramObject->GetProperty("backgroundBlurStyle");
1328     BlurStyleOption styleOption;
1329     if (backgroundBlurStyle->IsNumber()) {
1330         auto blurStyle = backgroundBlurStyle->ToNumber<int32_t>();
1331         if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
1332             blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
1333             pickerDialog.backgroundBlurStyle = blurStyle;
1334         }
1335     }
1336 
1337     TimePickerDialogModel::GetInstance()->SetTimePickerDialogShow(
1338         pickerDialog, settingData, std::move(cancelEvent), std::move(acceptEvent), std::move(changeEvent));
1339 }
1340 
TimePickerDialogShow(const JSRef<JSObject> & paramObj,const std::map<std::string,NG::DialogEvent> & dialogEvent,const std::map<std::string,NG::DialogGestureEvent> & dialogCancelEvent)1341 void JSTimePickerDialog::TimePickerDialogShow(const JSRef<JSObject>& paramObj,
1342     const std::map<std::string, NG::DialogEvent>& dialogEvent,
1343     const std::map<std::string, NG::DialogGestureEvent>& dialogCancelEvent)
1344 {
1345     auto container = Container::CurrentSafely();
1346     if (!container) {
1347         return;
1348     }
1349     auto pipelineContext = AccessibilityManager::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
1350     if (!pipelineContext) {
1351         return;
1352     }
1353 
1354     auto executor = pipelineContext->GetTaskExecutor();
1355     if (!executor) {
1356         return;
1357     }
1358 
1359     auto theme = JSAlertDialog::GetTheme<DialogTheme>();
1360     CHECK_NULL_VOID(theme);
1361 
1362     auto selectedTime = paramObj->GetProperty("selected");
1363     auto useMilitaryTime = paramObj->GetProperty("useMilitaryTime");
1364     NG::TimePickerSettingData settingData;
1365     settingData.isUseMilitaryTime = useMilitaryTime->ToBoolean();
1366 
1367     ButtonInfo buttonInfo;
1368     DialogProperties properties;
1369     if (SystemProperties::GetDeviceType() == DeviceType::PHONE) {
1370         properties.alignment = DialogAlignment::BOTTOM;
1371         if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1372             properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx()));
1373         }
1374     } else {
1375         properties.alignment = DialogAlignment::CENTER;
1376     }
1377     properties.customStyle = false;
1378     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1379         properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx()));
1380     }
1381 
1382     std::map<std::string, PickerTime> timePickerProperty;
1383     if (selectedTime->IsObject()) {
1384         settingData.dialogTitleDate = ParseDate(selectedTime);
1385         timePickerProperty["selected"] = ParseTime(selectedTime);
1386     }
1387     JSDatePicker::ParseTextProperties(paramObj, settingData.properties);
1388 
1389     auto context = AccessibilityManager::DynamicCast<NG::PipelineContext>(pipelineContext);
1390     auto overlayManager = context ? context->GetOverlayManager() : nullptr;
1391     executor->PostTask(
1392         [properties, settingData, timePickerProperty, dialogEvent, dialogCancelEvent,
1393             weak = WeakPtr<NG::OverlayManager>(overlayManager)] {
1394             auto overlayManager = weak.Upgrade();
1395             CHECK_NULL_VOID(overlayManager);
1396             overlayManager->ShowTimeDialog(properties, settingData, timePickerProperty, dialogEvent, dialogCancelEvent);
1397         },
1398         TaskExecutor::TaskType::UI);
1399 }
1400 
CreateTimePicker(RefPtr<Component> & component,const JSRef<JSObject> & paramObj)1401 void JSTimePickerDialog::CreateTimePicker(RefPtr<Component>& component, const JSRef<JSObject>& paramObj)
1402 {
1403     auto timePicker = AceType::MakeRefPtr<PickerTimeComponent>();
1404     auto selectedTime = paramObj->GetProperty("selected");
1405     auto useMilitaryTime = paramObj->GetProperty("useMilitaryTime");
1406     bool isUseMilitaryTime = useMilitaryTime->ToBoolean();
1407     if (selectedTime->IsObject()) {
1408         timePicker->SetSelectedTime(ParseTime(selectedTime));
1409     }
1410     timePicker->SetIsDialog(true);
1411     timePicker->SetIsCreateDialogComponent(true);
1412     timePicker->SetHour24(isUseMilitaryTime);
1413     component = timePicker;
1414 }
1415 
ParseTime(const JSRef<JSVal> & timeVal)1416 PickerTime JSTimePickerDialog::ParseTime(const JSRef<JSVal>& timeVal)
1417 {
1418     auto pickerTime = PickerTime();
1419     if (!timeVal->IsObject()) {
1420         return pickerTime;
1421     }
1422     auto timeObj = JSRef<JSObject>::Cast(timeVal);
1423     auto hourFuncJsVal = timeObj->GetProperty("getHours");
1424     auto minuteFuncJsVal = timeObj->GetProperty("getMinutes");
1425     auto secondFuncJsVal = timeObj->GetProperty("getSeconds");
1426     if (!(hourFuncJsVal->IsFunction() && minuteFuncJsVal->IsFunction() && secondFuncJsVal->IsFunction())) {
1427         return pickerTime;
1428     }
1429     auto hourFunc = JSRef<JSFunc>::Cast(hourFuncJsVal);
1430     auto minuteFunc = JSRef<JSFunc>::Cast(minuteFuncJsVal);
1431     auto secondFunc = JSRef<JSFunc>::Cast(secondFuncJsVal);
1432     JSRef<JSVal> hour = hourFunc->Call(timeObj);
1433     JSRef<JSVal> minute = minuteFunc->Call(timeObj);
1434     JSRef<JSVal> second = secondFunc->Call(timeObj);
1435 
1436     if (hour->IsNumber() && minute->IsNumber() && second->IsNumber()) {
1437         pickerTime.SetHour(hour->ToNumber<int32_t>());
1438         pickerTime.SetMinute(minute->ToNumber<int32_t>());
1439         pickerTime.SetSecond(second->ToNumber<int32_t>());
1440     }
1441     return pickerTime;
1442 }
1443 
ParseDate(const JSRef<JSVal> & dateVal)1444 PickerDate JSTimePickerDialog::ParseDate(const JSRef<JSVal>& dateVal)
1445 {
1446     auto pickerDate = PickerDate();
1447     if (!dateVal->IsObject()) {
1448         return pickerDate;
1449     }
1450     auto dateObj = JSRef<JSObject>::Cast(dateVal);
1451     auto yearFuncJsVal = dateObj->GetProperty("getFullYear");
1452     auto monthFuncJsVal = dateObj->GetProperty("getMonth");
1453     auto dateFuncJsVal = dateObj->GetProperty("getDate");
1454     if (!(yearFuncJsVal->IsFunction() && monthFuncJsVal->IsFunction() && dateFuncJsVal->IsFunction())) {
1455         return pickerDate;
1456     }
1457     auto yearFunc = JSRef<JSFunc>::Cast(yearFuncJsVal);
1458     auto monthFunc = JSRef<JSFunc>::Cast(monthFuncJsVal);
1459     auto dateFunc = JSRef<JSFunc>::Cast(dateFuncJsVal);
1460     JSRef<JSVal> year = yearFunc->Call(dateObj);
1461     JSRef<JSVal> month = monthFunc->Call(dateObj);
1462     JSRef<JSVal> date = dateFunc->Call(dateObj);
1463 
1464     if (year->IsNumber() && month->IsNumber() && date->IsNumber()) {
1465         pickerDate.SetYear(year->ToNumber<int32_t>());
1466         pickerDate.SetMonth(month->ToNumber<int32_t>() + 1); // 0-11 means 1 to 12 months
1467         pickerDate.SetDay(date->ToNumber<int32_t>());
1468     }
1469     return pickerDate;
1470 }
1471 } // namespace OHOS::Ace::Framework
1472