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