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 "frameworks/bridge/declarative_frontend/jsview/js_swiper.h"
17 
18 #include <algorithm>
19 #include <cstdint>
20 #include <iterator>
21 
22 #include "base/log/ace_scoring_log.h"
23 #include "base/utils/utils.h"
24 #include "bridge/common/utils/utils.h"
25 #include "bridge/declarative_frontend/engine/functions/js_click_function.h"
26 #include "bridge/declarative_frontend/engine/functions/js_swiper_function.h"
27 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
28 #include "bridge/declarative_frontend/jsview/models/swiper_model_impl.h"
29 #include "bridge/declarative_frontend/ark_theme/theme_apply/js_theme_utils.h"
30 #include "bridge/declarative_frontend/ark_theme/theme_apply/js_swiper_theme.h"
31 #include "bridge/declarative_frontend/view_stack_processor.h"
32 #include "bridge/js_frontend/engine/jsi/js_value.h"
33 #include "core/animation/curve.h"
34 #include "core/components/common/layout/constants.h"
35 #include "core/components/common/properties/scroll_bar.h"
36 #include "core/components/swiper/swiper_component.h"
37 #include "core/components/swiper/swiper_indicator_theme.h"
38 #include "core/components_ng/base/view_stack_processor.h"
39 #include "core/components_ng/pattern/scrollable/scrollable_properties.h"
40 #include "core/components_ng/pattern/swiper/swiper_content_transition_proxy.h"
41 #include "core/components_ng/pattern/swiper/swiper_model.h"
42 #include "core/components_ng/pattern/swiper/swiper_model_ng.h"
43 #include "bridge/declarative_frontend/engine/jsi/js_ui_index.h"
44 #include "bridge/declarative_frontend/jsview/js_indicator.h"
45 
46 namespace OHOS::Ace {
47 namespace {
48 constexpr float ARROW_SIZE_COEFFICIENT = 0.75f;
49 constexpr int32_t DEFAULT_CUSTOM_ANIMATION_TIMEOUT = 0;
50 const auto DEFAULT_CURVE = AceType::MakeRefPtr<InterpolatingSpring>(-1, 1, 328, 34);
51 } // namespace
52 std::unique_ptr<SwiperModel> SwiperModel::instance_ = nullptr;
53 std::mutex SwiperModel::mutex_;
54 
GetInstance()55 SwiperModel* SwiperModel::GetInstance()
56 {
57     if (!instance_) {
58         std::lock_guard<std::mutex> lock(mutex_);
59         if (!instance_) {
60 #ifdef NG_BUILD
61             instance_.reset(new NG::SwiperModelNG());
62 #else
63             if (Container::IsCurrentUseNewPipeline()) {
64                 instance_.reset(new NG::SwiperModelNG());
65             } else {
66                 instance_.reset(new Framework::SwiperModelImpl());
67             }
68 #endif
69         }
70     }
71     return instance_.get();
72 }
73 
74 } // namespace OHOS::Ace
75 namespace OHOS::Ace::Framework {
76 namespace {
77 
78 const std::vector<EdgeEffect> EDGE_EFFECT = { EdgeEffect::SPRING, EdgeEffect::FADE, EdgeEffect::NONE };
79 const std::vector<SwiperDisplayMode> DISPLAY_MODE = { SwiperDisplayMode::STRETCH, SwiperDisplayMode::AUTO_LINEAR };
80 const std::vector<SwiperIndicatorType> INDICATOR_TYPE = { SwiperIndicatorType::DOT, SwiperIndicatorType::DIGIT };
81 const static int32_t DEFAULT_INTERVAL = 3000;
82 const static int32_t DEFAULT_DURATION = 400;
83 const static int32_t DEFAULT_DISPLAY_COUNT = 1;
84 const static int32_t DEFAULT_CACHED_COUNT = 1;
85 
SwiperChangeEventToJSValue(const SwiperChangeEvent& eventInfo)86 JSRef<JSVal> SwiperChangeEventToJSValue(const SwiperChangeEvent& eventInfo)
87 {
88     return JSRef<JSVal>::Make(ToJSValue(eventInfo.GetIndex()));
89 }
90 
91 } // namespace
92 
Create(const JSCallbackInfo& info)93 void JSSwiper::Create(const JSCallbackInfo& info)
94 {
95     auto controller = SwiperModel::GetInstance()->Create();
96 
97     if (info.Length() > 0 && info[0]->IsObject()) {
98         auto* jsController = JSRef<JSObject>::Cast(info[0])->Unwrap<JSSwiperController>();
99         if (jsController) {
100             jsController->SetInstanceId(Container::CurrentId());
101             jsController->SetController(controller);
102         }
103     }
104 
105     JSSwiperTheme::ApplyThemeInConstructor();
106 }
107 
JsRemoteMessage(const JSCallbackInfo& info)108 void JSSwiper::JsRemoteMessage(const JSCallbackInfo& info)
109 {
110     RemoteCallback remoteCallback;
111     JSInteractableView::JsRemoteMessage(info, remoteCallback);
112 
113     SwiperModel::GetInstance()->SetRemoteMessageEventId(std::move(remoteCallback));
114 }
115 
JSBind(BindingTarget globalObj)116 void JSSwiper::JSBind(BindingTarget globalObj)
117 {
118     JsSwiperContentTransitionProxy::JSBind(globalObj);
119     JSClass<JSSwiper>::Declare("Swiper");
120     MethodOptions opt = MethodOptions::NONE;
121     JSClass<JSSwiper>::StaticMethod("create", &JSSwiper::Create, opt);
122     JSClass<JSSwiper>::StaticMethod("indicatorInteractive", &JSSwiper::SetIndicatorInteractive, opt);
123     JSClass<JSSwiper>::StaticMethod("autoPlay", &JSSwiper::SetAutoPlay, opt);
124     JSClass<JSSwiper>::StaticMethod("duration", &JSSwiper::SetDuration, opt);
125     JSClass<JSSwiper>::StaticMethod("index", &JSSwiper::SetIndex, opt);
126     JSClass<JSSwiper>::StaticMethod("interval", &JSSwiper::SetInterval, opt);
127     JSClass<JSSwiper>::StaticMethod("loop", &JSSwiper::SetLoop, opt);
128     JSClass<JSSwiper>::StaticMethod("vertical", &JSSwiper::SetVertical, opt);
129     JSClass<JSSwiper>::StaticMethod("indicator", &JSSwiper::SetIndicator, opt);
130     JSClass<JSSwiper>::StaticMethod("displayMode", &JSSwiper::SetDisplayMode);
131     JSClass<JSSwiper>::StaticMethod("effectMode", &JSSwiper::SetEffectMode);
132     JSClass<JSSwiper>::StaticMethod("displayCount", &JSSwiper::SetDisplayCount);
133     JSClass<JSSwiper>::StaticMethod("itemSpace", &JSSwiper::SetItemSpace);
134     JSClass<JSSwiper>::StaticMethod("prevMargin", &JSSwiper::SetPreviousMargin);
135     JSClass<JSSwiper>::StaticMethod("nextMargin", &JSSwiper::SetNextMargin);
136     JSClass<JSSwiper>::StaticMethod("cachedCount", &JSSwiper::SetCachedCount);
137     JSClass<JSSwiper>::StaticMethod("curve", &JSSwiper::SetCurve);
138     JSClass<JSSwiper>::StaticMethod("onChange", &JSSwiper::SetOnChange);
139     JSClass<JSSwiper>::StaticMethod("onAnimationStart", &JSSwiper::SetOnAnimationStart);
140     JSClass<JSSwiper>::StaticMethod("onAnimationEnd", &JSSwiper::SetOnAnimationEnd);
141     JSClass<JSSwiper>::StaticMethod("onGestureSwipe", &JSSwiper::SetOnGestureSwipe);
142     JSClass<JSSwiper>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
143     JSClass<JSSwiper>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
144     JSClass<JSSwiper>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
145     JSClass<JSSwiper>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
146     JSClass<JSSwiper>::StaticMethod("remoteMessage", &JSSwiper::JsRemoteMessage);
147     JSClass<JSSwiper>::StaticMethod("onClick", &JSSwiper::SetOnClick);
148     JSClass<JSSwiper>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
149     JSClass<JSSwiper>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
150     JSClass<JSSwiper>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
151     JSClass<JSSwiper>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
152     JSClass<JSSwiper>::StaticMethod("indicatorStyle", &JSSwiper::SetIndicatorStyle);
153     JSClass<JSSwiper>::StaticMethod("enabled", &JSSwiper::SetEnabled);
154     JSClass<JSSwiper>::StaticMethod("disableSwipe", &JSSwiper::SetDisableSwipe);
155     JSClass<JSSwiper>::StaticMethod("height", &JSSwiper::SetHeight);
156     JSClass<JSSwiper>::StaticMethod("width", &JSSwiper::SetWidth);
157     JSClass<JSSwiper>::StaticMethod("size", &JSSwiper::SetSize);
158     JSClass<JSSwiper>::StaticMethod("displayArrow", &JSSwiper::SetDisplayArrow);
159     JSClass<JSSwiper>::StaticMethod("nestedScroll", &JSSwiper::SetNestedScroll);
160     JSClass<JSSwiper>::StaticMethod("customContentTransition", &JSSwiper::SetCustomContentTransition);
161     JSClass<JSSwiper>::StaticMethod("onContentDidScroll", &JSSwiper::SetOnContentDidScroll);
162     JSClass<JSSwiper>::InheritAndBind<JSContainerBase>(globalObj);
163 }
164 
SetIndicatorInteractive(const JSCallbackInfo& info)165 void JSSwiper::SetIndicatorInteractive(const JSCallbackInfo& info)
166 {
167     if (info.Length() < 1) {
168         return;
169     }
170 
171     if (info[0]->IsBoolean()) {
172         SwiperModel::GetInstance()->SetIndicatorInteractive(info[0]->ToBoolean());
173     } else {
174         SwiperModel::GetInstance()->SetIndicatorInteractive(true);
175     }
176 }
177 
SetAutoPlay(bool autoPlay)178 void JSSwiper::SetAutoPlay(bool autoPlay)
179 {
180     SwiperModel::GetInstance()->SetAutoPlay(autoPlay);
181 }
182 
SetEnabled(const JSCallbackInfo& info)183 void JSSwiper::SetEnabled(const JSCallbackInfo& info)
184 {
185     JSViewAbstract::JsEnabled(info);
186     if (info.Length() < 1) {
187         return;
188     }
189 
190     if (!info[0]->IsBoolean()) {
191         return;
192     }
193 
194     SwiperModel::GetInstance()->SetEnabled(info[0]->ToBoolean());
195 }
196 
SetDisableSwipe(bool disableSwipe)197 void JSSwiper::SetDisableSwipe(bool disableSwipe)
198 {
199     SwiperModel::GetInstance()->SetDisableSwipe(disableSwipe);
200 }
201 
SetEffectMode(const JSCallbackInfo& info)202 void JSSwiper::SetEffectMode(const JSCallbackInfo& info)
203 {
204     if (info.Length() < 1) {
205         return;
206     }
207 
208     if (!info[0]->IsNumber()) {
209         return;
210     }
211 
212     auto edgeEffect = info[0]->ToNumber<int32_t>();
213     if (edgeEffect < 0 || edgeEffect >= static_cast<int32_t>(EDGE_EFFECT.size())) {
214         return;
215     }
216 
217     SwiperModel::GetInstance()->SetEdgeEffect(EDGE_EFFECT[edgeEffect]);
218 }
219 
SetDisplayCount(const JSCallbackInfo& info)220 void JSSwiper::SetDisplayCount(const JSCallbackInfo& info)
221 {
222     if (info.Length() < 1) {
223         return;
224     }
225 
226     if (info.Length() == 2) {
227         if (info[1]->IsBoolean()) {
228             SwiperModel::GetInstance()->SetSwipeByGroup(info[1]->ToBoolean());
229         } else {
230             SwiperModel::GetInstance()->SetSwipeByGroup(false);
231         }
232     }
233 
234     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
235         if (info[0]->IsString() && info[0]->ToString() == "auto") {
236             SwiperModel::GetInstance()->SetDisplayMode(SwiperDisplayMode::AUTO_LINEAR);
237             SwiperModel::GetInstance()->ResetDisplayCount();
238         } else if (info[0]->IsNumber() && info[0]->ToNumber<int32_t>() > 0) {
239             SwiperModel::GetInstance()->SetDisplayCount(info[0]->ToNumber<int32_t>());
240         } else if (info[0]->IsObject()) {
241             JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
242             auto minSizeParam = jsObj->GetProperty("minSize");
243             if (minSizeParam->IsNull()) {
244                 return;
245             }
246             CalcDimension minSizeValue;
247             if (!ParseJsDimensionVp(minSizeParam, minSizeValue)) {
248                 SwiperModel::GetInstance()->SetMinSize(0.0_vp);
249                 return;
250             }
251             SwiperModel::GetInstance()->SetMinSize(minSizeValue);
252         } else {
253             SwiperModel::GetInstance()->SetDisplayCount(DEFAULT_DISPLAY_COUNT);
254         }
255 
256         return;
257     }
258 
259     if (info[0]->IsString() && info[0]->ToString() == "auto") {
260         SwiperModel::GetInstance()->SetDisplayMode(SwiperDisplayMode::AUTO_LINEAR);
261         SwiperModel::GetInstance()->ResetDisplayCount();
262     } else if (info[0]->IsNumber()) {
263         SwiperModel::GetInstance()->SetDisplayCount(info[0]->ToNumber<int32_t>());
264     }
265 }
266 
SetDuration(const JSCallbackInfo& info)267 void JSSwiper::SetDuration(const JSCallbackInfo& info)
268 {
269     int32_t duration = DEFAULT_DURATION;
270 
271     if (info.Length() < 1) { // user do not set any value
272         return;
273     }
274 
275     // undefined value turn to default 400
276     if (!info[0]->IsUndefined() && info[0]->IsNumber()) {
277         duration = info[0]->ToNumber<int32_t>();
278         if (duration < 0) {
279             duration = DEFAULT_DURATION;
280         }
281     }
282 
283     SwiperModel::GetInstance()->SetDuration(duration);
284 }
285 
ParseSwiperIndexObject(const JSCallbackInfo& args, const JSRef<JSVal>& changeEventVal)286 void ParseSwiperIndexObject(const JSCallbackInfo& args, const JSRef<JSVal>& changeEventVal)
287 {
288     CHECK_NULL_VOID(changeEventVal->IsFunction());
289 
290     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(changeEventVal));
291     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
292     auto onIndex = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
293                        const BaseEventInfo* info) {
294         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
295         ACE_SCORING_EVENT("Swiper.onChangeEvent");
296         PipelineContext::SetCallBackNode(node);
297         const auto* swiperInfo = TypeInfoHelper::DynamicCast<SwiperChangeEvent>(info);
298         if (!swiperInfo) {
299             return;
300         }
301         auto newJSVal = JSRef<JSVal>::Make(ToJSValue(swiperInfo->GetIndex()));
302         func->ExecuteJS(1, &newJSVal);
303     };
304     SwiperModel::GetInstance()->SetOnChangeEvent(std::move(onIndex));
305 }
306 
SetIndex(const JSCallbackInfo& info)307 void JSSwiper::SetIndex(const JSCallbackInfo& info)
308 {
309     auto length = info.Length();
310     if (length < 1 || length > 2) {
311         return;
312     }
313 
314     int32_t index = 0;
315     auto jsIndex = info[0];
316     if (length > 0 && jsIndex->IsNumber()) {
317         index = jsIndex->ToNumber<int32_t>();
318     }
319 
320     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
321         index = index < 0 ? 0 : index;
322     }
323 
324     if (index < 0) {
325         return;
326     }
327     SwiperModel::GetInstance()->SetIndex(index);
328 
329     if (length > 1 && info[1]->IsFunction()) {
330         ParseSwiperIndexObject(info, info[1]);
331     }
332 }
333 
334 void JSSwiper::SetInterval(const JSCallbackInfo& info)
335 {
336     int32_t interval = DEFAULT_INTERVAL;
337 
338     if (info.Length() < 1) { // user do not set any value
339         return;
340     }
341 
342     // undefined value turn to default 3000
343     if (!info[0]->IsUndefined() && info[0]->IsNumber()) {
344         interval = info[0]->ToNumber<int32_t>();
345         if (interval < 0) {
346             interval = DEFAULT_INTERVAL;
347         }
348     }
349 
350     SwiperModel::GetInstance()->SetAutoPlayInterval(interval);
351 }
352 
353 void JSSwiper::SetLoop(const JSCallbackInfo& info)
354 {
355     if (info.Length() < 1) {
356         return;
357     }
358 
359     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
360         SwiperModel::GetInstance()->SetLoop(info[0]->ToBoolean());
361         return;
362     }
363 
364     if (info[0]->IsBoolean()) {
365         SwiperModel::GetInstance()->SetLoop(info[0]->ToBoolean());
366     } else {
367         SwiperModel::GetInstance()->SetLoop(true);
368     }
369 }
370 
371 void JSSwiper::SetVertical(bool isVertical)
372 {
373     SwiperModel::GetInstance()->SetDirection(isVertical ? Axis::VERTICAL : Axis::HORIZONTAL);
374 }
375 
376 void JSSwiper::GetFontContent(const JSRef<JSVal>& font, bool isSelected, SwiperDigitalParameters& digitalParameters)
377 {
378     JSRef<JSObject> obj = JSRef<JSObject>::Cast(font);
379     JSRef<JSVal> size = obj->GetProperty("size");
380     auto pipelineContext = PipelineBase::GetCurrentContext();
381     CHECK_NULL_VOID(pipelineContext);
382     auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
383     CHECK_NULL_VOID(swiperIndicatorTheme);
384     // set font size, unit FP
385     CalcDimension fontSize;
386     if (!size->IsUndefined() && !size->IsNull() && ParseJsDimensionFp(size, fontSize)) {
387         if (LessOrEqual(fontSize.Value(), 0.0) || LessOrEqual(size->ToNumber<double>(), 0.0) ||
388             fontSize.Unit() == DimensionUnit::PERCENT) {
389             fontSize = swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontSize();
390         }
391     } else {
392         fontSize = swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontSize();
393     }
394     if (isSelected) {
395         digitalParameters.selectedFontSize = fontSize;
396     } else {
397         digitalParameters.fontSize = fontSize;
398     }
399     JSRef<JSVal> weight = obj->GetProperty("weight");
400     if (!weight->IsNull()) {
401         std::string weightValue;
402         if (weight->IsNumber()) {
403             weightValue = std::to_string(weight->ToNumber<int32_t>());
404         } else {
405             ParseJsString(weight, weightValue);
406         }
407         if (isSelected) {
408             digitalParameters.selectedFontWeight = ConvertStrToFontWeight(weightValue);
409         } else {
410             digitalParameters.fontWeight = ConvertStrToFontWeight(weightValue);
411         }
412     } else {
413         if (isSelected) {
414             digitalParameters.selectedFontWeight = swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontWeight();
415         } else {
416             digitalParameters.fontWeight = swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontWeight();
417         }
418     }
419 }
420 
421 void JSSwiper::SetIsIndicatorCustomSize(const Dimension& dimPosition, bool parseOk)
422 {
423     if (parseOk && dimPosition > 0.0_vp) {
424         SwiperModel::GetInstance()->SetIsIndicatorCustomSize(true);
425     } else {
426         SwiperModel::GetInstance()->SetIsIndicatorCustomSize(false);
427     }
428 }
429 
430 std::optional<Dimension> JSSwiper::ParseIndicatorDimension(const JSRef<JSVal>& value)
431 {
432     std::optional<Dimension> indicatorDimension;
433     if (value->IsUndefined()) {
434         return indicatorDimension;
435     }
436     CalcDimension dimPosition;
437     auto parseOk = ParseJsDimensionVp(value, dimPosition);
438     indicatorDimension = parseOk && dimPosition.ConvertToPx() >= 0.0f ? dimPosition : 0.0_vp;
439     return indicatorDimension;
440 }
441 
442 SwiperParameters JSSwiper::GetDotIndicatorInfo(const JSRef<JSObject>& obj)
443 {
444     JSRef<JSVal> leftValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::LEFT_VALUE));
445     JSRef<JSVal> topValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::TOP_VALUE));
446     JSRef<JSVal> rightValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::RIGHT_VALUE));
447     JSRef<JSVal> bottomValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::BOTTOM_VALUE));
448     JSRef<JSVal> startValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::START_VALUE));
449     JSRef<JSVal> endValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::END_VALUE));
450     JSRef<JSVal> itemWidthValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::ITEM_WIDTH_VALUE));
451     JSRef<JSVal> itemHeightValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::ITEM_HEIGHT_VALUE));
452     JSRef<JSVal> selectedItemWidthValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::SELECTED_ITEM_WIDTH_VALUE));
453     JSRef<JSVal> selectedItemHeightValue =
454         obj->GetProperty(static_cast<int32_t>(ArkUIIndex::SELECTED_ITEM_HEIGHT_VALUE));
455     auto pipelineContext = PipelineBase::GetCurrentContext();
456     CHECK_NULL_RETURN(pipelineContext, SwiperParameters());
457     auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
458     CHECK_NULL_RETURN(swiperIndicatorTheme, SwiperParameters());
459     SwiperParameters swiperParameters;
460     swiperParameters.dimLeft = ParseIndicatorDimension(leftValue);
461     swiperParameters.dimTop = ParseIndicatorDimension(topValue);
462     swiperParameters.dimRight = ParseIndicatorDimension(rightValue);
463     swiperParameters.dimBottom = ParseIndicatorDimension(bottomValue);
464     CalcDimension dimStart;
465     CalcDimension dimEnd;
466     std::optional<Dimension> indicatorDimension;
467     swiperParameters.dimStart =  ParseLengthMetricsToDimension(startValue, dimStart) ? dimStart : indicatorDimension;
468     swiperParameters.dimEnd =  ParseLengthMetricsToDimension(endValue, dimEnd) ? dimEnd : indicatorDimension;
469 
470     CalcDimension dimPosition;
471     bool parseItemWOk =
472         ParseJsDimensionVp(itemWidthValue, dimPosition) && (dimPosition.Unit() != DimensionUnit::PERCENT);
473     auto defaultSize = swiperIndicatorTheme->GetSize();
474     swiperParameters.itemWidth = parseItemWOk && dimPosition > 0.0_vp ? dimPosition : defaultSize;
475     bool parseItemHOk =
476         ParseJsDimensionVp(itemHeightValue, dimPosition) && (dimPosition.Unit() != DimensionUnit::PERCENT);
477     swiperParameters.itemHeight = parseItemHOk && dimPosition > 0.0_vp ? dimPosition : defaultSize;
478     bool parseSelectedItemWOk =
479         ParseJsDimensionVp(selectedItemWidthValue, dimPosition) && (dimPosition.Unit() != DimensionUnit::PERCENT);
480     swiperParameters.selectedItemWidth = parseSelectedItemWOk && dimPosition > 0.0_vp ? dimPosition : defaultSize;
481     bool parseSelectedItemHOk =
482         ParseJsDimensionVp(selectedItemHeightValue, dimPosition) && (dimPosition.Unit() != DimensionUnit::PERCENT);
483     swiperParameters.selectedItemHeight = parseSelectedItemHOk && dimPosition > 0.0_vp ? dimPosition : defaultSize;
484     SwiperModel::GetInstance()->SetIsIndicatorCustomSize(
485         parseSelectedItemWOk || parseSelectedItemHOk || parseItemWOk || parseItemHOk);
486     SetDotIndicatorInfo(obj, swiperParameters, swiperIndicatorTheme);
487     return swiperParameters;
488 }
489 void JSSwiper::SetDotIndicatorInfo(const JSRef<JSObject>& obj, SwiperParameters& swiperParameters,
490     const RefPtr<SwiperIndicatorTheme>& swiperIndicatorTheme)
491 {
492     JSRef<JSVal> maskValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::MASK_VALUE));
493     JSRef<JSVal> colorValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::COLOR_VALUE));
494     JSRef<JSVal> selectedColorValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::SELECTED_COLOR_VALUE));
495     JSRef<JSVal> maxDisplayCountVal = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::MAX_DISPLAY_COUNT_VALUE));
496     if (maskValue->IsBoolean()) {
497         auto mask = maskValue->ToBoolean();
498         swiperParameters.maskValue = mask;
499     }
500     Color colorVal;
501     auto parseOk = ParseJsColor(colorValue, colorVal);
502     swiperParameters.colorVal = parseOk ? colorVal : swiperIndicatorTheme->GetColor();
503     parseOk = ParseJsColor(selectedColorValue, colorVal);
504     swiperParameters.selectedColorVal = parseOk ? colorVal : swiperIndicatorTheme->GetSelectedColor();
505     if (maxDisplayCountVal->IsUndefined()) {
506         return;
507     }
508     uint32_t result = 0;
509     auto setMaxDisplayCountVal = ParseJsInteger(maxDisplayCountVal, result);
510     swiperParameters.maxDisplayCountVal = setMaxDisplayCountVal && result > 0 ? result : 0;
511 }
512 bool JSSwiper::ParseLengthMetricsToDimension(const JSRef<JSVal>& jsValue, CalcDimension& result)
513 {
514     if (jsValue->IsNumber()) {
515         result = CalcDimension(jsValue->ToNumber<double>(), DimensionUnit::VP);
516         return true;
517     }
518     if (jsValue->IsString()) {
519         auto value = jsValue->ToString();
520         StringUtils::StringToCalcDimensionNG(value, result, false, DimensionUnit::VP);
521         return true;
522     }
523     if (jsValue->IsObject()) {
524         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
525         double value = jsObj->GetProperty("value")->ToNumber<double>();
526         auto unit = static_cast<DimensionUnit>(jsObj->GetProperty("unit")->ToNumber<int32_t>());
527         result = CalcDimension(value, unit);
528         return true;
529     }
530     if (jsValue->IsNull()) {
531         result = CalcDimension(0.0f, DimensionUnit::VP);
532         return true;
533     }
534 
535     return false;
536 }
537 
538 SwiperDigitalParameters JSSwiper::GetDigitIndicatorInfo(const JSRef<JSObject>& obj)
539 {
540     JSRef<JSVal> dotLeftValue = obj->GetProperty("leftValue");
541     JSRef<JSVal> dotTopValue = obj->GetProperty("topValue");
542     JSRef<JSVal> dotRightValue = obj->GetProperty("rightValue");
543     JSRef<JSVal> dotBottomValue = obj->GetProperty("bottomValue");
544     JSRef<JSVal> startValue = obj->GetProperty("startValue");
545     JSRef<JSVal> endValue = obj->GetProperty("endValue");
546     JSRef<JSVal> fontColorValue = obj->GetProperty("fontColorValue");
547     JSRef<JSVal> selectedFontColorValue = obj->GetProperty("selectedFontColorValue");
548     JSRef<JSVal> digitFontValue = obj->GetProperty("digitFontValue");
549     JSRef<JSVal> selectedDigitFontValue = obj->GetProperty("selectedDigitFontValue");
550     auto pipelineContext = PipelineBase::GetCurrentContext();
551     CHECK_NULL_RETURN(pipelineContext, SwiperDigitalParameters());
552     auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
553     CHECK_NULL_RETURN(swiperIndicatorTheme, SwiperDigitalParameters());
554     SwiperDigitalParameters digitalParameters;
555     digitalParameters.dimLeft = ParseIndicatorDimension(dotLeftValue);
556     digitalParameters.dimTop = ParseIndicatorDimension(dotTopValue);
557     digitalParameters.dimRight = ParseIndicatorDimension(dotRightValue);
558     digitalParameters.dimBottom = ParseIndicatorDimension(dotBottomValue);
559     std::optional<Dimension> indicatorDimension;
560     CalcDimension dimStart;
561     CalcDimension dimEnd;
562     digitalParameters.dimStart =  ParseLengthMetricsToDimension(startValue, dimStart) ? dimStart : indicatorDimension;
563     digitalParameters.dimEnd =  ParseLengthMetricsToDimension(endValue, dimEnd) ? dimEnd : indicatorDimension;
564 
565     Color fontColor;
566     auto parseOk = JSViewAbstract::ParseJsColor(fontColorValue, fontColor);
567     digitalParameters.fontColor =
568         parseOk ? fontColor : swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetTextColor();
569     parseOk = JSViewAbstract::ParseJsColor(selectedFontColorValue, fontColor);
570     digitalParameters.selectedFontColor =
571         parseOk ? fontColor : swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetTextColor();
572     if (!digitFontValue->IsNull() && digitFontValue->IsObject()) {
573         GetFontContent(digitFontValue, false, digitalParameters);
574     }
575     if (!selectedDigitFontValue->IsNull() && selectedDigitFontValue->IsObject()) {
576         GetFontContent(selectedDigitFontValue, true, digitalParameters);
577     }
578     return digitalParameters;
579 }
580 
581 bool JSSwiper::GetArrowInfo(const JSRef<JSObject>& obj, SwiperArrowParameters& swiperArrowParameters)
582 {
583     auto isShowBackgroundValue = obj->GetProperty("showBackground");
584     auto isSidebarMiddleValue = obj->GetProperty("isSidebarMiddle");
585     auto backgroundSizeValue = obj->GetProperty("backgroundSize");
586     auto backgroundColorValue = obj->GetProperty("backgroundColor");
587     auto arrowSizeValue = obj->GetProperty("arrowSize");
588     auto arrowColorValue = obj->GetProperty("arrowColor");
589     auto pipelineContext = PipelineBase::GetCurrentContext();
590     CHECK_NULL_RETURN(pipelineContext, false);
591     auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
592     CHECK_NULL_RETURN(swiperIndicatorTheme, false);
593     swiperArrowParameters.isShowBackground = isShowBackgroundValue->IsBoolean()
594                                                  ? isShowBackgroundValue->ToBoolean()
595                                                  : swiperIndicatorTheme->GetIsShowArrowBackground();
596     swiperArrowParameters.isSidebarMiddle = isSidebarMiddleValue->IsBoolean()
597                                                 ? isSidebarMiddleValue->ToBoolean()
598                                                 : swiperIndicatorTheme->GetIsSidebarMiddle();
599     bool parseOk = false;
600     CalcDimension dimension;
601     Color color;
602     if (swiperArrowParameters.isSidebarMiddle.value()) {
603         parseOk = ParseJsDimensionVp(backgroundSizeValue, dimension);
604         swiperArrowParameters.backgroundSize =
605             parseOk && GreatNotEqual(dimension.ConvertToVp(), 0.0) && !(dimension.Unit() == DimensionUnit::PERCENT)
606                 ? dimension
607                 : swiperIndicatorTheme->GetBigArrowBackgroundSize();
608         parseOk = ParseJsColor(backgroundColorValue, color);
609         swiperArrowParameters.backgroundColor = parseOk ? color : swiperIndicatorTheme->GetBigArrowBackgroundColor();
610         if (swiperArrowParameters.isShowBackground.value()) {
611             swiperArrowParameters.arrowSize = swiperArrowParameters.backgroundSize.value() * ARROW_SIZE_COEFFICIENT;
612         } else {
613             parseOk = ParseJsDimensionVpNG(arrowSizeValue, dimension);
614             swiperArrowParameters.arrowSize =
615                 parseOk && GreatNotEqual(dimension.ConvertToVp(), 0.0) && !(dimension.Unit() == DimensionUnit::PERCENT)
616                     ? dimension
617                     : swiperIndicatorTheme->GetBigArrowSize();
618             swiperArrowParameters.backgroundSize = swiperArrowParameters.arrowSize;
619         }
620         parseOk = ParseJsColor(arrowColorValue, color);
621         swiperArrowParameters.arrowColor = parseOk ? color : swiperIndicatorTheme->GetBigArrowColor();
622     } else {
623         parseOk = ParseJsDimensionVp(backgroundSizeValue, dimension);
624         swiperArrowParameters.backgroundSize =
625             parseOk && GreatNotEqual(dimension.ConvertToVp(), 0.0) && !(dimension.Unit() == DimensionUnit::PERCENT)
626                 ? dimension
627                 : swiperIndicatorTheme->GetSmallArrowBackgroundSize();
628         parseOk = ParseJsColor(backgroundColorValue, color);
629         swiperArrowParameters.backgroundColor = parseOk ? color : swiperIndicatorTheme->GetSmallArrowBackgroundColor();
630         if (swiperArrowParameters.isShowBackground.value()) {
631             swiperArrowParameters.arrowSize = swiperArrowParameters.backgroundSize.value() * ARROW_SIZE_COEFFICIENT;
632         } else {
633             parseOk = ParseJsDimensionVpNG(arrowSizeValue, dimension);
634             swiperArrowParameters.arrowSize =
635                 parseOk && GreatNotEqual(dimension.ConvertToVp(), 0.0) && !(dimension.Unit() == DimensionUnit::PERCENT)
636                     ? dimension
637                     : swiperIndicatorTheme->GetSmallArrowSize();
638             swiperArrowParameters.backgroundSize = swiperArrowParameters.arrowSize;
639         }
640         parseOk = ParseJsColor(arrowColorValue, color);
641         swiperArrowParameters.arrowColor = parseOk ? color : swiperIndicatorTheme->GetSmallArrowColor();
642     }
643     return true;
644 }
645 
646 void JSSwiper::SetDisplayArrow(const JSCallbackInfo& info)
647 {
648     if (info[0]->IsEmpty() || info[0]->IsUndefined()) {
649         SwiperModel::GetInstance()->SetDisplayArrow(false);
650         return;
651     }
652     if (info.Length() > 0 && info[0]->IsObject()) {
653         auto obj = JSRef<JSObject>::Cast(info[0]);
654         SwiperArrowParameters swiperArrowParameters;
655         if (!GetArrowInfo(obj, swiperArrowParameters)) {
656             SwiperModel::GetInstance()->SetDisplayArrow(false);
657             return;
658         }
659         JSSwiperTheme::ApplyThemeToDisplayArrow(swiperArrowParameters, obj);
660         SwiperModel::GetInstance()->SetArrowStyle(swiperArrowParameters);
661         SwiperModel::GetInstance()->SetDisplayArrow(true);
662     } else if (info[0]->IsBoolean()) {
663         if (info[0]->ToBoolean()) {
664             auto pipelineContext = PipelineBase::GetCurrentContext();
665             CHECK_NULL_VOID(pipelineContext);
666             auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
667             CHECK_NULL_VOID(swiperIndicatorTheme);
668             SwiperArrowParameters swiperArrowParameters;
669             swiperArrowParameters.isShowBackground = swiperIndicatorTheme->GetIsShowArrowBackground();
670             swiperArrowParameters.isSidebarMiddle = swiperIndicatorTheme->GetIsSidebarMiddle();
671             swiperArrowParameters.backgroundSize = swiperIndicatorTheme->GetSmallArrowBackgroundSize();
672             swiperArrowParameters.backgroundColor = swiperIndicatorTheme->GetSmallArrowBackgroundColor();
673             swiperArrowParameters.arrowSize = swiperIndicatorTheme->GetSmallArrowSize();
674             swiperArrowParameters.arrowColor = swiperIndicatorTheme->GetSmallArrowColor();
675             JSSwiperTheme::ApplyThemeToDisplayArrowForce(swiperArrowParameters);
676             SwiperModel::GetInstance()->SetArrowStyle(swiperArrowParameters);
677             SwiperModel::GetInstance()->SetDisplayArrow(true);
678         } else {
679             SwiperModel::GetInstance()->SetDisplayArrow(false);
680             return;
681         }
682     } else {
683         SwiperModel::GetInstance()->SetDisplayArrow(false);
684         return;
685     }
686     if (info.Length() > 1 && info[1]->IsBoolean()) {
687         SwiperModel::GetInstance()->SetHoverShow(info[1]->ToBoolean());
688     } else {
689         SwiperModel::GetInstance()->SetHoverShow(false);
690     }
691 }
692 
693 void JSSwiper::SetIndicatorController(const JSCallbackInfo& info)
694 {
695     if (info.Length() < 1 || !info[0]->IsObject()) {
696         return;
697     }
698 
699     auto* jsIndicatorController = JSRef<JSObject>::Cast(info[0])->Unwrap<JSIndicatorController>();
700     if (!jsIndicatorController) {
701         return;
702     }
703 
704     WeakPtr<NG::UINode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
705     jsIndicatorController->SetSwiperNode(targetNode);
706     SwiperModel::GetInstance()->SetBindIndicator(true);
707 }
708 
709 void JSSwiper::SetIndicator(const JSCallbackInfo& info)
710 {
711     if (info.Length() < 1) {
712         return;
713     }
714 
715     if (info[0]->IsEmpty()) {
716         SwiperModel::GetInstance()->SetShowIndicator(true);
717         return;
718     }
719     SwiperModel::GetInstance()->SetBindIndicator(false);
720     if (info[0]->IsObject()) {
721         auto obj = JSRef<JSObject>::Cast(info[0]);
722         SwiperModel::GetInstance()->SetIndicatorIsBoolean(false);
723 
724         JSRef<JSVal> typeParam = obj->GetProperty("type");
725         if (typeParam->IsString()) {
726             auto type = typeParam->ToString();
727             if (type == "DigitIndicator") {
728                 SwiperDigitalParameters digitalParameters = GetDigitIndicatorInfo(obj);
729                 JSSwiperTheme::ApplyThemeToDigitIndicator(digitalParameters, obj);
730                 SwiperModel::GetInstance()->SetDigitIndicatorStyle(digitalParameters);
731                 SwiperModel::GetInstance()->SetIndicatorType(SwiperIndicatorType::DIGIT);
732             } else {
733                 SwiperParameters swiperParameters = GetDotIndicatorInfo(obj);
734                 JSSwiperTheme::ApplyThemeToDotIndicator(swiperParameters, obj);
735                 SwiperModel::GetInstance()->SetDotIndicatorStyle(swiperParameters);
736                 SwiperModel::GetInstance()->SetIndicatorType(SwiperIndicatorType::DOT);
737             }
738         } else if (typeParam->IsUndefined()) {
739             SetIndicatorController(info);
740         } else {
741             SwiperParameters swiperParameters = GetDotIndicatorInfo(obj);
742             JSSwiperTheme::ApplyThemeToDotIndicatorForce(swiperParameters);
743             SwiperModel::GetInstance()->SetDotIndicatorStyle(swiperParameters);
744             SwiperModel::GetInstance()->SetIndicatorType(SwiperIndicatorType::DOT);
745         }
746     } else {
747         SwiperParameters swiperParameters = GetDotIndicatorInfo(JSRef<JSObject>::New());
748         JSSwiperTheme::ApplyThemeToDotIndicatorForce(swiperParameters);
749         SwiperModel::GetInstance()->SetDotIndicatorStyle(swiperParameters);
750         SwiperModel::GetInstance()->SetIndicatorType(SwiperIndicatorType::DOT);
751     }
752     if (info[0]->IsBoolean()) {
753         bool showIndicator = false;
754         ParseJsBool(info[0], showIndicator);
755         SwiperModel::GetInstance()->SetShowIndicator(showIndicator);
756     } else {
757         SwiperModel::GetInstance()->SetShowIndicator(true);
758     }
759 }
760 
761 void JSSwiper::SetIndicatorStyle(const JSCallbackInfo& info)
762 {
763     SwiperParameters swiperParameters;
764     if (info[0]->IsObject()) {
765         JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
766         JSRef<JSVal> leftValue = obj->GetProperty("left");
767         JSRef<JSVal> topValue = obj->GetProperty("top");
768         JSRef<JSVal> rightValue = obj->GetProperty("right");
769         JSRef<JSVal> bottomValue = obj->GetProperty("bottom");
770         JSRef<JSVal> sizeValue = obj->GetProperty("size");
771         JSRef<JSVal> maskValue = obj->GetProperty("mask");
772         JSRef<JSVal> colorValue = obj->GetProperty("color");
773         JSRef<JSVal> selectedColorValue = obj->GetProperty("selectedColor");
774         auto pipelineContext = PipelineBase::GetCurrentContext();
775         CHECK_NULL_VOID(pipelineContext);
776         auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
777         CHECK_NULL_VOID(swiperIndicatorTheme);
778         swiperParameters.dimLeft = ParseIndicatorDimension(leftValue);
779         swiperParameters.dimTop = ParseIndicatorDimension(topValue);
780         swiperParameters.dimRight = ParseIndicatorDimension(rightValue);
781         swiperParameters.dimBottom = ParseIndicatorDimension(bottomValue);
782         CalcDimension dimPosition;
783         auto parseOk = ParseJsDimensionVp(sizeValue, dimPosition) && (dimPosition.Unit() != DimensionUnit::PERCENT);
784         SetIsIndicatorCustomSize(dimPosition, parseOk);
785         swiperParameters.itemWidth = parseOk && dimPosition > 0.0_vp ? dimPosition : swiperIndicatorTheme->GetSize();
786         swiperParameters.itemHeight = parseOk && dimPosition > 0.0_vp ? dimPosition : swiperIndicatorTheme->GetSize();
787         swiperParameters.selectedItemWidth =
788             parseOk && dimPosition > 0.0_vp ? dimPosition : swiperIndicatorTheme->GetSize();
789         swiperParameters.selectedItemHeight =
790             parseOk && dimPosition > 0.0_vp ? dimPosition : swiperIndicatorTheme->GetSize();
791         if (maskValue->IsBoolean()) {
792             auto mask = maskValue->ToBoolean();
793             swiperParameters.maskValue = mask;
794         }
795         Color colorVal;
796         parseOk = ParseJsColor(colorValue, colorVal);
797         swiperParameters.colorVal = parseOk ? colorVal : swiperIndicatorTheme->GetColor();
798         parseOk = ParseJsColor(selectedColorValue, colorVal);
799         swiperParameters.selectedColorVal = parseOk ? colorVal : swiperIndicatorTheme->GetSelectedColor();
800     }
801     SwiperModel::GetInstance()->SetDotIndicatorStyle(swiperParameters);
802     info.ReturnSelf();
803 }
804 
805 void JSSwiper::SetItemSpace(const JSCallbackInfo& info)
806 {
807     if (info.Length() < 1) {
808         return;
809     }
810 
811     CalcDimension value;
812     if (!ParseJsDimensionVp(info[0], value) || LessNotEqual(value.Value(), 0.0)) {
813         value.SetValue(0.0);
814     }
815 
816     SwiperModel::GetInstance()->SetItemSpace(value);
817 }
818 
819 void JSSwiper::SetPreviousMargin(const JSCallbackInfo& info)
820 {
821     if (info.Length() < 1) {
822         return;
823     }
824 
825     CalcDimension value;
826     bool ignoreBlank = false;
827     if (!ParseJsDimensionVp(info[0], value) || info[0]->IsNull() || info[0]->IsUndefined() ||
828         LessNotEqual(value.Value(), 0.0)) {
829         value.SetValue(0.0);
830     }
831     if (info.Length() > 1 && info[1]->IsBoolean()) {
832         ignoreBlank = info[1]->ToBoolean();
833     }
834     SwiperModel::GetInstance()->SetPreviousMargin(value, ignoreBlank);
835 }
836 
837 void JSSwiper::SetNextMargin(const JSCallbackInfo& info)
838 {
839     if (info.Length() < 1) {
840         return;
841     }
842 
843     CalcDimension value;
844     bool ignoreBlank = false;
845     if (!ParseJsDimensionVp(info[0], value) || info[0]->IsNull() || info[0]->IsUndefined() ||
846         LessNotEqual(value.Value(), 0.0)) {
847         value.SetValue(0.0);
848     }
849     if (info.Length() > 1 && info[1]->IsBoolean()) {
850         ignoreBlank = info[1]->ToBoolean();
851     }
852     SwiperModel::GetInstance()->SetNextMargin(value, ignoreBlank);
853 }
854 
855 void JSSwiper::SetDisplayMode(int32_t index)
856 {
857     if (index < 0 || index >= static_cast<int32_t>(DISPLAY_MODE.size())) {
858         return;
859     }
860 
861     SwiperModel::GetInstance()->SetDisplayMode(DISPLAY_MODE[index]);
862 }
863 
864 void JSSwiper::SetCachedCount(const JSCallbackInfo& info)
865 {
866     if (info.Length() < 1) {
867         return;
868     }
869 
870     int32_t cachedCount = DEFAULT_CACHED_COUNT;
871     if (!info[0]->IsUndefined() && info[0]->IsNumber()) {
872         cachedCount = info[0]->ToNumber<int32_t>();
873         if (cachedCount < 0) {
874             cachedCount = DEFAULT_CACHED_COUNT;
875         }
876     }
877     SwiperModel::GetInstance()->SetCachedCount(cachedCount);
878 }
879 
880 void JSSwiper::SetCurve(const JSCallbackInfo& info)
881 {
882     RefPtr<Curve> curve = DEFAULT_CURVE;
883     if (info[0]->IsString()) {
884         curve = CreateCurve(info[0]->ToString(), false);
885         if (!curve) {
886             curve = DEFAULT_CURVE;
887         }
888     } else if (info[0]->IsObject()) {
889         auto object = JSRef<JSObject>::Cast(info[0]);
890         std::function<float(float)> customCallBack = nullptr;
891         JSRef<JSVal> onCallBack = object->GetProperty("__curveCustomFunc");
892         if (onCallBack->IsFunction()) {
893             RefPtr<JsFunction> jsFuncCallBack =
894                 AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onCallBack));
895             customCallBack = [func = std::move(jsFuncCallBack), id = Container::CurrentId()](float time) -> float {
896                 ContainerScope scope(id);
897                 JSRef<JSVal> params[1];
898                 params[0] = JSRef<JSVal>::Make(ToJSValue(time));
899                 auto result = func->ExecuteJS(1, params);
900                 auto resultValue = result->IsNumber() ? result->ToNumber<float>() : 1.0f;
901                 return resultValue;
902             };
903         }
904         auto jsCurveString = object->GetProperty("__curveString");
905         if (jsCurveString->IsString()) {
906             auto aniTimFunc = jsCurveString->ToString();
907             if (aniTimFunc == DOM_ANIMATION_TIMING_FUNCTION_CUSTOM && customCallBack) {
908                 curve = CreateCurve(customCallBack);
909             } else if (aniTimFunc != DOM_ANIMATION_TIMING_FUNCTION_CUSTOM) {
910                 curve = CreateCurve(aniTimFunc);
911             }
912         }
913     }
914     SwiperModel::GetInstance()->SetCurve(curve);
915 }
916 
917 void JSSwiper::SetOnChange(const JSCallbackInfo& info)
918 {
919     if (!info[0]->IsFunction()) {
920         return;
921     }
922 
923     auto changeHandler = AceType::MakeRefPtr<JsEventFunction<SwiperChangeEvent, 1>>(
924         JSRef<JSFunc>::Cast(info[0]), SwiperChangeEventToJSValue);
925     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
926     auto onChange = [executionContext = info.GetExecutionContext(), func = std::move(changeHandler), node = targetNode](
927                         const BaseEventInfo* info) {
928         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
929         const auto* swiperInfo = TypeInfoHelper::DynamicCast<SwiperChangeEvent>(info);
930         if (!swiperInfo) {
931             TAG_LOGW(AceLogTag::ACE_SWIPER, "Swiper onChange callback execute failed.");
932             return;
933         }
934         ACE_SCORING_EVENT("Swiper.OnChange");
935         PipelineContext::SetCallBackNode(node);
936         func->Execute(*swiperInfo);
937     };
938 
939     SwiperModel::GetInstance()->SetOnChange(std::move(onChange));
940 }
941 
942 void JSSwiper::SetOnAnimationStart(const JSCallbackInfo& info)
943 {
944     if (!info[0]->IsFunction()) {
945         return;
946     }
947 
948     if (Container::IsCurrentUseNewPipeline()) {
949         auto animationStartHandler = AceType::MakeRefPtr<JsSwiperFunction>(JSRef<JSFunc>::Cast(info[0]));
950         auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
951         auto onAnimationStart = [executionContext = info.GetExecutionContext(), func = std::move(animationStartHandler),
952                                     node = targetNode](
953                                     int32_t index, int32_t targetIndex, const AnimationCallbackInfo& info) {
954             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
955             ACE_SCORING_EVENT("Swiper.onAnimationStart");
956             PipelineContext::SetCallBackNode(node);
957             func->Execute(index, targetIndex, info);
958         };
959 
960         SwiperModel::GetInstance()->SetOnAnimationStart(std::move(onAnimationStart));
961         return;
962     }
963 
964     auto animationStartHandler = AceType::MakeRefPtr<JsEventFunction<SwiperChangeEvent, 1>>(
965         JSRef<JSFunc>::Cast(info[0]), SwiperChangeEventToJSValue);
966     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
967     auto onAnimationStart = [executionContext = info.GetExecutionContext(), func = std::move(animationStartHandler),
968                                 node = targetNode](const BaseEventInfo* info) {
969         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
970         const auto* swiperInfo = TypeInfoHelper::DynamicCast<SwiperChangeEvent>(info);
971         if (!swiperInfo) {
972             TAG_LOGW(AceLogTag::ACE_SWIPER, "Swiper onAnimationStart callback execute failed.");
973             return;
974         }
975         ACE_SCORING_EVENT("Swiper.onAnimationStart");
976         PipelineContext::SetCallBackNode(node);
977         func->Execute(*swiperInfo);
978     };
979 
980     SwiperModel::GetInstance()->SetOnAnimationStart(std::move(onAnimationStart));
981 }
982 
983 void JSSwiper::SetOnAnimationEnd(const JSCallbackInfo& info)
984 {
985     if (!info[0]->IsFunction()) {
986         return;
987     }
988 
989     if (Container::IsCurrentUseNewPipeline()) {
990         auto animationEndHandler = AceType::MakeRefPtr<JsSwiperFunction>(JSRef<JSFunc>::Cast(info[0]));
991         auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
992         auto onAnimationEnd = [executionContext = info.GetExecutionContext(), func = std::move(animationEndHandler),
993                                   node = targetNode](int32_t index, const AnimationCallbackInfo& info) {
994             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
995             ACE_SCORING_EVENT("Swiper.onAnimationEnd");
996             PipelineContext::SetCallBackNode(node);
997             func->Execute(index, info);
998         };
999 
1000         SwiperModel::GetInstance()->SetOnAnimationEnd(std::move(onAnimationEnd));
1001         return;
1002     }
1003 
1004     auto animationEndHandler = AceType::MakeRefPtr<JsEventFunction<SwiperChangeEvent, 1>>(
1005         JSRef<JSFunc>::Cast(info[0]), SwiperChangeEventToJSValue);
1006     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1007     auto onAnimationEnd = [executionContext = info.GetExecutionContext(), func = std::move(animationEndHandler),
1008                               node = targetNode](const BaseEventInfo* info) {
1009         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
1010         const auto* swiperInfo = TypeInfoHelper::DynamicCast<SwiperChangeEvent>(info);
1011         if (!swiperInfo) {
1012             TAG_LOGW(AceLogTag::ACE_SWIPER, "Swiper onAnimationEnd callback execute failed.");
1013             return;
1014         }
1015         ACE_SCORING_EVENT("Swiper.onAnimationEnd");
1016         PipelineContext::SetCallBackNode(node);
1017         func->Execute(*swiperInfo);
1018     };
1019 
1020     SwiperModel::GetInstance()->SetOnAnimationEnd(std::move(onAnimationEnd));
1021 }
1022 
1023 void JSSwiper::SetOnGestureSwipe(const JSCallbackInfo& info)
1024 {
1025     if (!info[0]->IsFunction()) {
1026         return;
1027     }
1028 
1029     auto gestureSwipeHandler = AceType::MakeRefPtr<JsSwiperFunction>(JSRef<JSFunc>::Cast(info[0]));
1030     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1031     auto onGestureSwipe = [executionContext = info.GetExecutionContext(), func = std::move(gestureSwipeHandler),
1032                               node = targetNode](int32_t index, const AnimationCallbackInfo& info) {
1033         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
1034         ACE_SCORING_EVENT("Swiper.onGestureSwipe");
1035         PipelineContext::SetCallBackNode(node);
1036         func->Execute(index, info);
1037     };
1038 
1039     SwiperModel::GetInstance()->SetOnGestureSwipe(std::move(onGestureSwipe));
1040 }
1041 
1042 void JSSwiper::SetOnClick(const JSCallbackInfo& info)
1043 {
1044     if (Container::IsCurrentUseNewPipeline()) {
1045         JSInteractableView::JsOnClick(info);
1046         return;
1047     }
1048 
1049     if (!info[0]->IsFunction()) {
1050         return;
1051     }
1052 
1053     RefPtr<JsClickFunction> jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(info[0]));
1054     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1055     auto onClick = [execCtx = info.GetExecutionContext(), func = std::move(jsOnClickFunc), node = targetNode](
1056                        const BaseEventInfo* info, const RefPtr<V2::InspectorFunctionImpl>& impl) {
1057         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1058         const auto* clickInfo = TypeInfoHelper::DynamicCast<ClickInfo>(info);
1059         if (!clickInfo) {
1060             TAG_LOGW(AceLogTag::ACE_SWIPER, "Swiper onClick callback execute failed.");
1061             return;
1062         }
1063         auto newInfo = *clickInfo;
1064         if (impl) {
1065             impl->UpdateEventInfo(newInfo);
1066         }
1067         ACE_SCORING_EVENT("onClick");
1068         PipelineContext::SetCallBackNode(node);
1069         func->Execute(newInfo);
1070     };
1071 
1072     SwiperModel::GetInstance()->SetOnClick(onClick);
1073 }
1074 
1075 void JSSwiper::SetWidth(const JSCallbackInfo& info)
1076 {
1077     if (info.Length() < 1) {
1078         return;
1079     }
1080 
1081     SetWidth(info[0]);
1082 }
1083 
1084 void JSSwiper::SetWidth(const JSRef<JSVal>& jsValue)
1085 {
1086     if (Container::IsCurrentUseNewPipeline()) {
1087         JSViewAbstract::JsWidth(jsValue);
1088         return;
1089     }
1090 
1091     JSViewAbstract::JsWidth(jsValue);
1092     SwiperModel::GetInstance()->SetMainSwiperSizeWidth();
1093 }
1094 
1095 void JSSwiper::SetHeight(const JSRef<JSVal>& jsValue)
1096 {
1097     if (Container::IsCurrentUseNewPipeline()) {
1098         JSViewAbstract::JsHeight(jsValue);
1099         return;
1100     }
1101 
1102     JSViewAbstract::JsHeight(jsValue);
1103     SwiperModel::GetInstance()->SetMainSwiperSizeHeight();
1104 }
1105 
1106 void JSSwiper::SetHeight(const JSCallbackInfo& info)
1107 {
1108     if (info.Length() < 1) {
1109         return;
1110     }
1111 
1112     SetHeight(info[0]);
1113 }
1114 
1115 void JSSwiper::SetSize(const JSCallbackInfo& info)
1116 {
1117     if (info.Length() < 1) {
1118         return;
1119     }
1120 
1121     if (!info[0]->IsObject()) {
1122         return;
1123     }
1124 
1125     JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(info[0]);
1126     SetWidth(sizeObj->GetProperty("width"));
1127     SetHeight(sizeObj->GetProperty("height"));
1128 }
1129 
1130 void JSSwiperController::JSBind(BindingTarget globalObj)
1131 {
1132     JSClass<JSSwiperController>::Declare("SwiperController");
1133     JSClass<JSSwiperController>::CustomMethod("swipeTo", &JSSwiperController::SwipeTo);
1134     JSClass<JSSwiperController>::CustomMethod("showNext", &JSSwiperController::ShowNext);
1135     JSClass<JSSwiperController>::CustomMethod("showPrevious", &JSSwiperController::ShowPrevious);
1136     JSClass<JSSwiperController>::CustomMethod("changeIndex", &JSSwiperController::ChangeIndex);
1137     JSClass<JSSwiperController>::CustomMethod("finishAnimation", &JSSwiperController::FinishAnimation);
1138     JSClass<JSSwiperController>::CustomMethod("preloadItems", &JSSwiperController::PreloadItems);
1139     JSClass<JSSwiperController>::Bind(globalObj, JSSwiperController::Constructor, JSSwiperController::Destructor);
1140 }
1141 
1142 void JSSwiperController::Constructor(const JSCallbackInfo& args)
1143 {
1144     auto scroller = Referenced::MakeRefPtr<JSSwiperController>();
1145     scroller->IncRefCount();
1146     args.SetReturnValue(Referenced::RawPtr(scroller));
1147 }
1148 
1149 void JSSwiperController::Destructor(JSSwiperController* scroller)
1150 {
1151     if (scroller != nullptr) {
1152         scroller->DecRefCount();
1153     }
1154 }
1155 
1156 void JSSwiperController::ChangeIndex(const JSCallbackInfo& args)
1157 {
1158     if (!controller_) {
1159         return;
1160     }
1161     if (args.Length() < 1 || !args[0]->IsNumber()) {
1162         return;
1163     }
1164     int32_t index = -1;
1165     bool useAnimation = false;
1166     if (args.Length() > 1 && args[1]->IsBoolean()) {
1167         useAnimation = args[1]->ToBoolean();
1168     }
1169     index = args[0]->ToNumber<int32_t>();
1170     controller_->ChangeIndex(index, useAnimation);
1171 }
1172 
1173 void JSSwiperController::FinishAnimation(const JSCallbackInfo& args)
1174 {
1175     ContainerScope scope(instanceId_);
1176     if (!controller_) {
1177         return;
1178     }
1179 
1180     if (args.Length() > 0 && args[0]->IsFunction()) {
1181         RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(args[0]));
1182         auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1183         auto onFinish = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]() {
1184             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1185             ACE_SCORING_EVENT("Swiper.finishAnimation");
1186             PipelineContext::SetCallBackNode(node);
1187             TAG_LOGD(AceLogTag::ACE_SWIPER, "SwiperController finishAnimation callback execute.");
1188             func->Execute();
1189         };
1190 
1191         controller_->SetFinishCallback(onFinish);
1192         controller_->FinishAnimation();
1193         return;
1194     }
1195 
1196     controller_->FinishAnimation();
1197 }
1198 
1199 void JSSwiperController::PreloadItems(const JSCallbackInfo& args)
1200 {
1201     ContainerScope scope(instanceId_);
1202     if (!controller_) {
1203         return;
1204     }
1205 
1206     if (args.Length() != 2 || !args[0]->IsArray() || !args[1]->IsFunction()) {
1207         return;
1208     }
1209 
1210     auto indexArray = JSRef<JSArray>::Cast(args[0]);
1211     size_t size = indexArray->Length();
1212     std::set<int32_t> indexSet;
1213     for (size_t i = 0; i < size; i++) {
1214         int32_t index = -1;
1215         JSViewAbstract::ParseJsInt32(indexArray->GetValueAt(i), index);
1216         indexSet.emplace(index);
1217     }
1218 
1219     RefPtr<JsSwiperFunction> jsFunc = AceType::MakeRefPtr<JsSwiperFunction>(JSRef<JSFunc>::Cast(args[1]));
1220     auto onPreloadFinish =
1221         [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](int32_t errorCode, std::string message) {
1222             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1223             ACE_SCORING_EVENT("Swiper.preloadItems");
1224             TAG_LOGI(AceLogTag::ACE_SWIPER, "SwiperController preloadItems callback execute.");
1225             func->Execute(errorCode);
1226         };
1227 
1228     controller_->SetPreloadFinishCallback(onPreloadFinish);
1229     controller_->PreloadItems(indexSet);
1230 }
1231 
1232 void JSSwiper::SetNestedScroll(const JSCallbackInfo& args)
1233 {
1234     // default value
1235     NestedScrollOptions nestedOpt = {
1236         .forward = NestedScrollMode::SELF_ONLY,
1237         .backward = NestedScrollMode::SELF_ONLY,
1238     };
1239     if (args.Length() < 1 || !args[0]->IsNumber()) {
1240         SwiperModel::GetInstance()->SetNestedScroll(nestedOpt);
1241         return;
1242     }
1243     int32_t value = -1;
1244     JSViewAbstract::ParseJsInt32(args[0], value);
1245     auto mode = static_cast<NestedScrollMode>(value);
1246     if (mode < NestedScrollMode::SELF_ONLY || mode > NestedScrollMode::SELF_FIRST) {
1247         SwiperModel::GetInstance()->SetNestedScroll(nestedOpt);
1248         return;
1249     }
1250     nestedOpt.forward = mode;
1251     nestedOpt.backward = mode;
1252     SwiperModel::GetInstance()->SetNestedScroll(nestedOpt);
1253     args.ReturnSelf();
1254 }
1255 
1256 void JSSwiper::SetCustomContentTransition(const JSCallbackInfo& info)
1257 {
1258     if (info.Length() < 1 || !info[0]->IsObject()) {
1259         return;
1260     }
1261 
1262     SwiperContentAnimatedTransition transitionInfo;
1263     auto transitionObj = JSRef<JSObject>::Cast(info[0]);
1264     JSRef<JSVal> timeoutProperty = transitionObj->GetProperty("timeout");
1265     if (timeoutProperty->IsNumber()) {
1266         auto timeout = timeoutProperty->ToNumber<int32_t>();
1267         transitionInfo.timeout = timeout < 0 ? DEFAULT_CUSTOM_ANIMATION_TIMEOUT : timeout;
1268     } else {
1269         transitionInfo.timeout = DEFAULT_CUSTOM_ANIMATION_TIMEOUT;
1270     }
1271 
1272     JSRef<JSVal> transition = transitionObj->GetProperty("transition");
1273     if (transition->IsFunction()) {
1274         auto jsOnTransition = AceType::MakeRefPtr<JsSwiperFunction>(JSRef<JSFunc>::Cast(transition));
1275         auto onTransition = [execCtx = info.GetExecutionContext(), func = std::move(jsOnTransition)](
1276                                 const RefPtr<SwiperContentTransitionProxy>& proxy) {
1277             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1278             ACE_SCORING_EVENT("Swiper.customContentTransition");
1279             func->Execute(proxy);
1280         };
1281         transitionInfo.transition = std::move(onTransition);
1282     }
1283     SwiperModel::GetInstance()->SetCustomContentTransition(transitionInfo);
1284 }
1285 
1286 void JSSwiper::SetOnContentDidScroll(const JSCallbackInfo& info)
1287 {
1288     if (info.Length() < 1 || !info[0]->IsFunction()) {
1289         return;
1290     }
1291 
1292     auto contentDidScrollHandler = AceType::MakeRefPtr<JsSwiperFunction>(JSRef<JSFunc>::Cast(info[0]));
1293     auto onContentDidScroll = [execCtx = info.GetExecutionContext(),
1294                                 func = std::move(contentDidScrollHandler)](
1295                                 int32_t selectedIndex, int32_t index, float position, float mainAxisLength) {
1296         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1297         ACE_SCORING_EVENT("Swiper.onContentDidScroll");
1298         func->Execute(selectedIndex, index, position, mainAxisLength);
1299     };
1300     SwiperModel::GetInstance()->SetOnContentDidScroll(std::move(onContentDidScroll));
1301 }
1302 } // namespace OHOS::Ace::Framework
1303