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