• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "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/log/event_report.h"
24 #include "base/utils/utils.h"
25 #include "bridge/common/utils/engine_helper.h"
26 #include "bridge/common/utils/utils.h"
27 #include "bridge/declarative_frontend/ark_theme/theme_apply/js_swiper_theme.h"
28 #include "bridge/declarative_frontend/ark_theme/theme_apply/js_theme_utils.h"
29 #include "bridge/declarative_frontend/engine/functions/js_click_function.h"
30 #include "bridge/declarative_frontend/engine/functions/js_swiper_function.h"
31 #include "bridge/declarative_frontend/engine/js_converter.h"
32 #include "bridge/declarative_frontend/jsview/js_utils.h"
33 #include "bridge/declarative_frontend/engine/jsi/js_ui_index.h"
34 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
35 #include "bridge/declarative_frontend/jsview/models/swiper_model_impl.h"
36 #include "bridge/declarative_frontend/view_stack_processor.h"
37 #include "bridge/js_frontend/engine/jsi/js_value.h"
38 #include "core/animation/curve.h"
39 #include "core/components/common/layout/constants.h"
40 #include "core/components/common/properties/scroll_bar.h"
41 #include "core/components/swiper/swiper_component.h"
42 #include "core/components/swiper/swiper_indicator_theme.h"
43 #include "core/components_ng/base/view_stack_processor.h"
44 #include "core/components_ng/pattern/scrollable/scrollable_properties.h"
45 #include "core/components_ng/pattern/swiper/swiper_content_transition_proxy.h"
46 #include "core/components_ng/pattern/swiper/swiper_model.h"
47 #include "core/components_ng/pattern/swiper/swiper_model_ng.h"
48 
49 namespace OHOS::Ace {
50 namespace {
51 constexpr float ARROW_SIZE_COEFFICIENT = 0.75f;
52 constexpr int32_t DEFAULT_CUSTOM_ANIMATION_TIMEOUT = 0;
53 const auto DEFAULT_CURVE = AceType::MakeRefPtr<InterpolatingSpring>(-1, 1, 328, 34);
54 constexpr int32_t LENGTH_TWO = 2;
55 } // namespace
56 std::unique_ptr<SwiperModel> SwiperModel::instance_ = nullptr;
57 std::mutex SwiperModel::mutex_;
58 
GetInstance()59 SwiperModel* SwiperModel::GetInstance()
60 {
61     if (!instance_) {
62         std::lock_guard<std::mutex> lock(mutex_);
63         if (!instance_) {
64 #ifdef NG_BUILD
65             instance_.reset(new NG::SwiperModelNG());
66 #else
67             if (Container::IsCurrentUseNewPipeline()) {
68                 instance_.reset(new NG::SwiperModelNG());
69             } else {
70                 instance_.reset(new Framework::SwiperModelImpl());
71             }
72 #endif
73         }
74     }
75     return instance_.get();
76 }
77 
78 } // namespace OHOS::Ace
79 namespace OHOS::Ace::Framework {
80 WeakPtr<JSIndicatorController> JSSwiper::jSIndicatorController_;
81 namespace {
82 
83 const std::vector<EdgeEffect> EDGE_EFFECT = { EdgeEffect::SPRING, EdgeEffect::FADE, EdgeEffect::NONE };
84 const std::vector<SwiperDisplayMode> DISPLAY_MODE = { SwiperDisplayMode::STRETCH, SwiperDisplayMode::AUTO_LINEAR };
85 const std::vector<SwiperIndicatorType> INDICATOR_TYPE = { SwiperIndicatorType::DOT, SwiperIndicatorType::DIGIT };
86 const std::vector<SwiperAnimationMode> SWIPER_ANIMATION_MODE = { SwiperAnimationMode::NO_ANIMATION,
87     SwiperAnimationMode::DEFAULT_ANIMATION, SwiperAnimationMode::FAST_ANIMATION };
88 const static int32_t DEFAULT_INTERVAL = 3000;
89 const static int32_t DEFAULT_DURATION = 400;
90 const static int32_t DEFAULT_DISPLAY_COUNT = 1;
91 const static int32_t DEFAULT_CACHED_COUNT = 1;
92 
SwiperChangeEventToJSValue(const SwiperChangeEvent & eventInfo)93 JSRef<JSVal> SwiperChangeEventToJSValue(const SwiperChangeEvent& eventInfo)
94 {
95     return JSRef<JSVal>::Make(ToJSValue(eventInfo.GetIndex()));
96 }
97 
98 struct SwiperControllerAsyncContext {
99     napi_env env = nullptr;
100     napi_deferred deferred = nullptr;
101 };
102 
CreateErrorValue(napi_env env,int32_t errCode,const std::string & errMsg="")103 napi_value CreateErrorValue(napi_env env, int32_t errCode, const std::string& errMsg = "")
104 {
105     napi_value code = nullptr;
106     std::string codeStr = std::to_string(errCode);
107     napi_create_string_utf8(env, codeStr.c_str(), codeStr.length(), &code);
108     napi_value msg = nullptr;
109     napi_create_string_utf8(env, errMsg.c_str(), errMsg.length(), &msg);
110     napi_value error = nullptr;
111     napi_create_error(env, code, msg, &error);
112     return error;
113 }
114 
HandleDeferred(const shared_ptr<SwiperControllerAsyncContext> & asyncContext,int32_t errorCode,std::string message)115 void HandleDeferred(
116     const shared_ptr<SwiperControllerAsyncContext>& asyncContext, int32_t errorCode, std::string message)
117 {
118     auto env = asyncContext->env;
119     CHECK_NULL_VOID(env);
120     auto deferred = asyncContext->deferred;
121     CHECK_NULL_VOID(deferred);
122 
123     napi_handle_scope scope = nullptr;
124     auto status = napi_open_handle_scope(env, &scope);
125     if (status != napi_ok) {
126         return;
127     }
128 
129     napi_value result = nullptr;
130     if (errorCode == ERROR_CODE_NO_ERROR) {
131         napi_get_null(env, &result);
132         napi_resolve_deferred(env, deferred, result);
133     } else {
134         result = CreateErrorValue(env, errorCode, message);
135         napi_reject_deferred(env, deferred, result);
136     }
137     napi_close_handle_scope(env, scope);
138 }
139 
ReturnPromise(const JSCallbackInfo & info,napi_value result)140 void ReturnPromise(const JSCallbackInfo& info, napi_value result)
141 {
142     CHECK_NULL_VOID(result);
143     auto jsPromise = JsConverter::ConvertNapiValueToJsVal(result);
144     if (!jsPromise->IsObject()) {
145         return;
146     }
147     info.SetReturnValue(JSRef<JSObject>::Cast(jsPromise));
148 }
149 } // namespace
150 
Create(const JSCallbackInfo & info)151 void JSSwiper::Create(const JSCallbackInfo& info)
152 {
153     auto controller = SwiperModel::GetInstance()->Create();
154 
155     if (info.Length() > 0 && info[0]->IsObject()) {
156         auto* jsController = JSRef<JSObject>::Cast(info[0])->Unwrap<JSSwiperController>();
157         if (jsController) {
158             jsController->SetInstanceId(Container::CurrentId());
159             jsController->SetController(controller);
160         }
161     }
162 
163     JSSwiperTheme::ApplyThemeInConstructor();
164 }
165 
JsRemoteMessage(const JSCallbackInfo & info)166 void JSSwiper::JsRemoteMessage(const JSCallbackInfo& info)
167 {
168     RemoteCallback remoteCallback;
169     JSInteractableView::JsRemoteMessage(info, remoteCallback);
170 
171     SwiperModel::GetInstance()->SetRemoteMessageEventId(std::move(remoteCallback));
172 }
173 
JSBind(BindingTarget globalObj)174 void JSSwiper::JSBind(BindingTarget globalObj)
175 {
176     JsSwiperContentTransitionProxy::JSBind(globalObj);
177     JSClass<JSSwiper>::Declare("Swiper");
178     MethodOptions opt = MethodOptions::NONE;
179     JSClass<JSSwiper>::StaticMethod("create", &JSSwiper::Create, opt);
180     JSClass<JSSwiper>::StaticMethod("indicatorInteractive", &JSSwiper::SetIndicatorInteractive, opt);
181     JSClass<JSSwiper>::StaticMethod("autoPlay", &JSSwiper::SetAutoPlay, opt);
182     JSClass<JSSwiper>::StaticMethod("duration", &JSSwiper::SetDuration, opt);
183     JSClass<JSSwiper>::StaticMethod("index", &JSSwiper::SetIndex, opt);
184     JSClass<JSSwiper>::StaticMethod("interval", &JSSwiper::SetInterval, opt);
185     JSClass<JSSwiper>::StaticMethod("loop", &JSSwiper::SetLoop, opt);
186     JSClass<JSSwiper>::StaticMethod("vertical", &JSSwiper::SetVertical, opt);
187     JSClass<JSSwiper>::StaticMethod("indicator", &JSSwiper::SetIndicator, opt);
188     JSClass<JSSwiper>::StaticMethod("displayMode", &JSSwiper::SetDisplayMode);
189     JSClass<JSSwiper>::StaticMethod("effectMode", &JSSwiper::SetEffectMode);
190     JSClass<JSSwiper>::StaticMethod("displayCount", &JSSwiper::SetDisplayCount);
191     JSClass<JSSwiper>::StaticMethod("itemSpace", &JSSwiper::SetItemSpace);
192     JSClass<JSSwiper>::StaticMethod("prevMargin", &JSSwiper::SetPreviousMargin);
193     JSClass<JSSwiper>::StaticMethod("nextMargin", &JSSwiper::SetNextMargin);
194     JSClass<JSSwiper>::StaticMethod("cachedCount", &JSSwiper::SetCachedCount);
195     JSClass<JSSwiper>::StaticMethod("curve", &JSSwiper::SetCurve);
196     JSClass<JSSwiper>::StaticMethod("onChange", &JSSwiper::SetOnChange);
197     JSClass<JSSwiper>::StaticMethod("onUnselected", &JSSwiper::SetOnUnselected);
198     JSClass<JSSwiper>::StaticMethod("onAnimationStart", &JSSwiper::SetOnAnimationStart);
199     JSClass<JSSwiper>::StaticMethod("onAnimationEnd", &JSSwiper::SetOnAnimationEnd);
200     JSClass<JSSwiper>::StaticMethod("onGestureSwipe", &JSSwiper::SetOnGestureSwipe);
201     JSClass<JSSwiper>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
202     JSClass<JSSwiper>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
203     JSClass<JSSwiper>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
204     JSClass<JSSwiper>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
205     JSClass<JSSwiper>::StaticMethod("remoteMessage", &JSSwiper::JsRemoteMessage);
206     JSClass<JSSwiper>::StaticMethod("onClick", &JSSwiper::SetOnClick);
207     JSClass<JSSwiper>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
208     JSClass<JSSwiper>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
209     JSClass<JSSwiper>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
210     JSClass<JSSwiper>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
211     JSClass<JSSwiper>::StaticMethod("indicatorStyle", &JSSwiper::SetIndicatorStyle);
212     JSClass<JSSwiper>::StaticMethod("enabled", &JSSwiper::SetEnabled);
213     JSClass<JSSwiper>::StaticMethod("disableSwipe", &JSSwiper::SetDisableSwipe);
214     JSClass<JSSwiper>::StaticMethod("height", &JSSwiper::SetHeight);
215     JSClass<JSSwiper>::StaticMethod("width", &JSSwiper::SetWidth);
216     JSClass<JSSwiper>::StaticMethod("size", &JSSwiper::SetSize);
217     JSClass<JSSwiper>::StaticMethod("displayArrow", &JSSwiper::SetDisplayArrow);
218     JSClass<JSSwiper>::StaticMethod("nestedScroll", &JSSwiper::SetNestedScroll);
219     JSClass<JSSwiper>::StaticMethod("customContentTransition", &JSSwiper::SetCustomContentTransition);
220     JSClass<JSSwiper>::StaticMethod("onContentDidScroll", &JSSwiper::SetOnContentDidScroll);
221     JSClass<JSSwiper>::StaticMethod("pageFlipMode", &JSSwiper::SetPageFlipMode);
222     JSClass<JSSwiper>::StaticMethod("onContentWillScroll", &JSSwiper::SetOnContentWillScroll);
223     JSClass<JSSwiper>::StaticMethod("onSelected", &JSSwiper::SetOnSelected);
224     JSClass<JSSwiper>::InheritAndBind<JSContainerBase>(globalObj);
225 }
226 
SetIndicatorInteractive(const JSCallbackInfo & info)227 void JSSwiper::SetIndicatorInteractive(const JSCallbackInfo& info)
228 {
229     if (info.Length() < 1) {
230         return;
231     }
232 
233     if (info[0]->IsBoolean()) {
234         SwiperModel::GetInstance()->SetIndicatorInteractive(info[0]->ToBoolean());
235     } else {
236         SwiperModel::GetInstance()->SetIndicatorInteractive(true);
237     }
238 }
239 
SetAutoPlay(const JSCallbackInfo & info)240 void JSSwiper::SetAutoPlay(const JSCallbackInfo& info)
241 {
242     if (info.Length() < 1) {
243         return;
244     }
245     bool autoPlay = false;
246     if (info[0]->IsBoolean()) {
247         autoPlay = info[0]->ToBoolean();
248     }
249     SwiperModel::GetInstance()->SetAutoPlay(autoPlay);
250     SwiperAutoPlayOptions swiperAutoPlayOptions;
251     if (info.Length() > 1 && info[1]->IsObject()) {
252         auto obj = JSRef<JSObject>::Cast(info[1]);
253         GetAutoPlayOptionsInfo(obj, swiperAutoPlayOptions);
254     }
255 
256     SwiperModel::GetInstance()->SetAutoPlayOptions(swiperAutoPlayOptions);
257 }
258 
SetEnabled(const JSCallbackInfo & info)259 void JSSwiper::SetEnabled(const JSCallbackInfo& info)
260 {
261     JSViewAbstract::JsEnabled(info);
262     if (info.Length() < 1) {
263         return;
264     }
265 
266     if (!info[0]->IsBoolean()) {
267         return;
268     }
269 
270     SwiperModel::GetInstance()->SetEnabled(info[0]->ToBoolean());
271 }
272 
SetDisableSwipe(bool disableSwipe)273 void JSSwiper::SetDisableSwipe(bool disableSwipe)
274 {
275     SwiperModel::GetInstance()->SetDisableSwipe(disableSwipe);
276 }
277 
SetEffectMode(const JSCallbackInfo & info)278 void JSSwiper::SetEffectMode(const JSCallbackInfo& info)
279 {
280     if (info.Length() < 1) {
281         return;
282     }
283 
284     if (!info[0]->IsNumber()) {
285         return;
286     }
287 
288     auto edgeEffect = info[0]->ToNumber<int32_t>();
289     if (edgeEffect < 0 || edgeEffect >= static_cast<int32_t>(EDGE_EFFECT.size())) {
290         return;
291     }
292 
293     SwiperModel::GetInstance()->SetEdgeEffect(EDGE_EFFECT[edgeEffect]);
294 }
295 
SetDisplayCount(const JSCallbackInfo & info)296 void JSSwiper::SetDisplayCount(const JSCallbackInfo& info)
297 {
298     if (info.Length() < 1) {
299         return;
300     }
301 
302     if (info.Length() == 2) {
303         if (info[1]->IsBoolean()) {
304             SwiperModel::GetInstance()->SetSwipeByGroup(info[1]->ToBoolean());
305         } else {
306             SwiperModel::GetInstance()->SetSwipeByGroup(false);
307         }
308     }
309 
310     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
311         if (info[0]->IsString() && info[0]->ToString() == "auto") {
312             SwiperModel::GetInstance()->SetDisplayMode(SwiperDisplayMode::AUTO_LINEAR);
313             SwiperModel::GetInstance()->ResetDisplayCount();
314         } else if (info[0]->IsNumber() && info[0]->ToNumber<int32_t>() > 0) {
315             SwiperModel::GetInstance()->SetDisplayCount(info[0]->ToNumber<int32_t>());
316         } else if (info[0]->IsObject()) {
317             JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
318             auto minSizeParam = jsObj->GetProperty("minSize");
319             if (minSizeParam->IsNull()) {
320                 return;
321             }
322             CalcDimension minSizeValue;
323             if (!ParseJsDimensionVp(minSizeParam, minSizeValue)) {
324                 SwiperModel::GetInstance()->SetMinSize(0.0_vp);
325                 return;
326             }
327             SwiperModel::GetInstance()->SetMinSize(minSizeValue);
328         } else {
329             SwiperModel::GetInstance()->SetDisplayCount(DEFAULT_DISPLAY_COUNT);
330         }
331 
332         return;
333     }
334 
335     if (info[0]->IsString() && info[0]->ToString() == "auto") {
336         SwiperModel::GetInstance()->SetDisplayMode(SwiperDisplayMode::AUTO_LINEAR);
337         SwiperModel::GetInstance()->ResetDisplayCount();
338     } else if (info[0]->IsNumber()) {
339         SwiperModel::GetInstance()->SetDisplayCount(info[0]->ToNumber<int32_t>());
340     }
341 }
342 
SetDuration(const JSCallbackInfo & info)343 void JSSwiper::SetDuration(const JSCallbackInfo& info)
344 {
345     int32_t duration = DEFAULT_DURATION;
346 
347     if (info.Length() < 1) { // user do not set any value
348         return;
349     }
350 
351     // undefined value turn to default 400
352     if (!info[0]->IsUndefined() && info[0]->IsNumber()) {
353         duration = info[0]->ToNumber<int32_t>();
354         if (duration < 0) {
355             duration = DEFAULT_DURATION;
356         }
357     }
358 
359     SwiperModel::GetInstance()->SetDuration(duration);
360 }
361 
ParseSwiperIndexObject(const JSCallbackInfo & args,const JSRef<JSVal> & changeEventVal)362 void ParseSwiperIndexObject(const JSCallbackInfo& args, const JSRef<JSVal>& changeEventVal)
363 {
364     CHECK_NULL_VOID(changeEventVal->IsFunction());
365 
366     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(changeEventVal));
367     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
368     auto onIndex = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
369                        const BaseEventInfo* info) {
370         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
371         ACE_SCORING_EVENT("Swiper.onChangeEvent");
372         PipelineContext::SetCallBackNode(node);
373         const auto* swiperInfo = TypeInfoHelper::DynamicCast<SwiperChangeEvent>(info);
374         if (!swiperInfo) {
375             return;
376         }
377         auto newJSVal = JSRef<JSVal>::Make(ToJSValue(swiperInfo->GetIndex()));
378         func->ExecuteJS(1, &newJSVal);
379     };
380     SwiperModel::GetInstance()->SetOnChangeEvent(std::move(onIndex));
381 }
382 
SetIndex(const JSCallbackInfo & info)383 void JSSwiper::SetIndex(const JSCallbackInfo& info)
384 {
385     auto length = info.Length();
386     if (length < 1 || length > 2) {
387         return;
388     }
389     int32_t index = 0;
390     auto jsIndex = info[0];
391     if (jsIndex->IsObject()) {
392         JSRef<JSObject> obj = JSRef<JSObject>::Cast(jsIndex);
393         jsIndex = obj->GetProperty("value");
394         auto changeEventVal = obj->GetProperty("$value");
395         ParseSwiperIndexObject(info, changeEventVal);
396     }
397 
398     if (length > 0 && jsIndex->IsNumber()) {
399         index = jsIndex->ToNumber<int32_t>();
400     }
401 
402     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
403         index = index < 0 ? 0 : index;
404     }
405 
406     if (index < 0) {
407         return;
408     }
409     SwiperModel::GetInstance()->SetIndex(index);
410 
411     if (length > 1 && info[1]->IsFunction()) {
412         ParseSwiperIndexObject(info, info[1]);
413     }
414 }
415 
SetInterval(const JSCallbackInfo & info)416 void JSSwiper::SetInterval(const JSCallbackInfo& info)
417 {
418     int32_t interval = DEFAULT_INTERVAL;
419 
420     if (info.Length() < 1) { // user do not set any value
421         return;
422     }
423 
424     // undefined value turn to default 3000
425     if (!info[0]->IsUndefined() && info[0]->IsNumber()) {
426         interval = info[0]->ToNumber<int32_t>();
427         if (interval < 0) {
428             interval = DEFAULT_INTERVAL;
429         }
430     }
431 
432     SwiperModel::GetInstance()->SetAutoPlayInterval(interval);
433 }
434 
SetLoop(const JSCallbackInfo & info)435 void JSSwiper::SetLoop(const JSCallbackInfo& info)
436 {
437     if (info.Length() < 1) {
438         return;
439     }
440 
441     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
442         SwiperModel::GetInstance()->SetLoop(info[0]->ToBoolean());
443         return;
444     }
445 
446     if (info[0]->IsBoolean()) {
447         SwiperModel::GetInstance()->SetLoop(info[0]->ToBoolean());
448     } else {
449         SwiperModel::GetInstance()->SetLoop(true);
450     }
451 }
452 
SetVertical(bool isVertical)453 void JSSwiper::SetVertical(bool isVertical)
454 {
455     SwiperModel::GetInstance()->SetDirection(isVertical ? Axis::VERTICAL : Axis::HORIZONTAL);
456 }
457 
GetFontContent(const JSRef<JSVal> & font,bool isSelected,SwiperDigitalParameters & digitalParameters)458 void JSSwiper::GetFontContent(const JSRef<JSVal>& font, bool isSelected, SwiperDigitalParameters& digitalParameters)
459 {
460     JSRef<JSObject> obj = JSRef<JSObject>::Cast(font);
461     JSRef<JSVal> size = obj->GetProperty("size");
462     auto pipelineContext = PipelineBase::GetCurrentContext();
463     CHECK_NULL_VOID(pipelineContext);
464     auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
465     CHECK_NULL_VOID(swiperIndicatorTheme);
466     // set font size, unit FP
467     CalcDimension fontSize;
468     if (!size->IsUndefined() && !size->IsNull() && ParseJsDimensionFp(size, fontSize)) {
469         if (LessOrEqual(fontSize.Value(), 0.0) || LessOrEqual(size->ToNumber<double>(), 0.0) ||
470             fontSize.Unit() == DimensionUnit::PERCENT) {
471             fontSize = swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontSize();
472         }
473     } else {
474         fontSize = swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontSize();
475     }
476     if (isSelected) {
477         digitalParameters.selectedFontSize = fontSize;
478     } else {
479         digitalParameters.fontSize = fontSize;
480     }
481     JSRef<JSVal> weight = obj->GetProperty("weight");
482     if (!weight->IsNull()) {
483         std::string weightValue;
484         if (weight->IsNumber()) {
485             weightValue = std::to_string(weight->ToNumber<int32_t>());
486         } else {
487             ParseJsString(weight, weightValue);
488         }
489         if (isSelected) {
490             digitalParameters.selectedFontWeight = ConvertStrToFontWeight(weightValue);
491         } else {
492             digitalParameters.fontWeight = ConvertStrToFontWeight(weightValue);
493         }
494     } else {
495         if (isSelected) {
496             digitalParameters.selectedFontWeight = swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontWeight();
497         } else {
498             digitalParameters.fontWeight = swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontWeight();
499         }
500     }
501 }
502 
SetIsIndicatorCustomSize(const Dimension & dimPosition,bool parseOk)503 void JSSwiper::SetIsIndicatorCustomSize(const Dimension& dimPosition, bool parseOk)
504 {
505     if (parseOk && dimPosition > 0.0_vp) {
506         SwiperModel::GetInstance()->SetIsIndicatorCustomSize(true);
507     } else {
508         SwiperModel::GetInstance()->SetIsIndicatorCustomSize(false);
509     }
510 }
511 
ParseIndicatorDimension(const JSRef<JSVal> & value)512 std::optional<Dimension> JSSwiper::ParseIndicatorDimension(const JSRef<JSVal>& value)
513 {
514     std::optional<Dimension> indicatorDimension;
515     if (value->IsUndefined()) {
516         return indicatorDimension;
517     }
518     CalcDimension dimPosition;
519     auto parseOk = ParseJsDimensionVp(value, dimPosition);
520     indicatorDimension = parseOk && dimPosition.ConvertToPx() >= 0.0f ? dimPosition : 0.0_vp;
521     return indicatorDimension;
522 }
523 
ParseIndicatorBottom(const JSRef<JSVal> & bottomValue,bool hasIgnoreSize)524 std::optional<Dimension> JSSwiper::ParseIndicatorBottom(const JSRef<JSVal>& bottomValue, bool hasIgnoreSize)
525 {
526     std::optional<Dimension> bottom;
527     if (bottomValue->IsUndefined()) {
528         return bottom;
529     }
530     if (!hasIgnoreSize) {
531         bottom = ParseIndicatorDimension(bottomValue);
532         return bottom;
533     } else {
534         CalcDimension dimBottom;
535         bool parseOk = ParseLengthMetricsToDimension(bottomValue, dimBottom);
536         if (!parseOk) {
537             bottom = ParseIndicatorDimension(bottomValue);
538             return bottom;
539         }
540         dimBottom = parseOk && dimBottom.ConvertToPx() >= 0.0f ? dimBottom : 0.0_vp;
541         return dimBottom;
542     }
543 }
544 
GetDotIndicatorInfo(const JSRef<JSObject> & obj)545 SwiperParameters JSSwiper::GetDotIndicatorInfo(const JSRef<JSObject>& obj)
546 {
547     JSRef<JSVal> leftValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::LEFT_VALUE));
548     JSRef<JSVal> topValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::TOP_VALUE));
549     JSRef<JSVal> rightValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::RIGHT_VALUE));
550     JSRef<JSVal> bottomValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::BOTTOM_VALUE));
551     JSRef<JSVal> startValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::START_VALUE));
552     JSRef<JSVal> endValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::END_VALUE));
553     JSRef<JSVal> itemWidthValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::ITEM_WIDTH_VALUE));
554     JSRef<JSVal> itemHeightValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::ITEM_HEIGHT_VALUE));
555     JSRef<JSVal> selectedItemWidthValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::SELECTED_ITEM_WIDTH_VALUE));
556     JSRef<JSVal> selectedItemHeightValue =
557         obj->GetProperty(static_cast<int32_t>(ArkUIIndex::SELECTED_ITEM_HEIGHT_VALUE));
558     JSRef<JSVal> spaceValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::SPACE_VALUE));
559     JSRef<JSVal> ignoreSizeValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::IGNORE_SIZE_VALUE));
560     JSRef<JSVal> setIgnoreSizeValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::SET_IGNORE_SIZE_VALUE));
561 
562     auto pipelineContext = PipelineBase::GetCurrentContext();
563     CHECK_NULL_RETURN(pipelineContext, SwiperParameters());
564     auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
565     CHECK_NULL_RETURN(swiperIndicatorTheme, SwiperParameters());
566     SwiperParameters swiperParameters;
567     swiperParameters.dimLeft = ParseIndicatorDimension(leftValue);
568     swiperParameters.dimTop = ParseIndicatorDimension(topValue);
569     swiperParameters.dimRight = ParseIndicatorDimension(rightValue);
570     auto hasIgnoreSizeValue = false;
571 
572     if (setIgnoreSizeValue->IsBoolean()) {
573         hasIgnoreSizeValue = setIgnoreSizeValue->ToBoolean();
574         swiperParameters.setIgnoreSizeValue = hasIgnoreSizeValue;
575     }
576 
577     if (ignoreSizeValue->IsBoolean()) {
578         auto ignoreSize = ignoreSizeValue->ToBoolean();
579         swiperParameters.ignoreSizeValue = ignoreSize;
580     }
581     swiperParameters.dimBottom = ParseIndicatorBottom(bottomValue, hasIgnoreSizeValue);
582     CalcDimension dimStart;
583     CalcDimension dimEnd;
584     CalcDimension dimSpace;
585 
586     std::optional<Dimension> indicatorDimension;
587     swiperParameters.dimStart =  ParseLengthMetricsToDimension(startValue, dimStart) ? dimStart : indicatorDimension;
588     swiperParameters.dimEnd =  ParseLengthMetricsToDimension(endValue, dimEnd) ? dimEnd : indicatorDimension;
589 
590     auto parseSpaceOk = ParseSpace(spaceValue, dimSpace) &&
591         (dimSpace.Unit() !=  DimensionUnit::PERCENT) ;
592     auto defalutSpace = swiperIndicatorTheme->GetIndicatorDotItemSpace();
593     swiperParameters.dimSpace =  (parseSpaceOk && !(dimSpace < 0.0_vp)) ? dimSpace : defalutSpace;
594     bool ignoreSize = ignoreSizeValue->IsBoolean() ? ignoreSizeValue->ToBoolean() : false;
595     swiperParameters.ignoreSizeValue = ignoreSize;
596 
597     CalcDimension dimPosition;
598     bool parseItemWOk =
599         ParseJsDimensionVp(itemWidthValue, dimPosition) && (dimPosition.Unit() != DimensionUnit::PERCENT);
600     auto defaultSize = swiperIndicatorTheme->GetSize();
601     swiperParameters.itemWidth = parseItemWOk && dimPosition > 0.0_vp ? dimPosition : defaultSize;
602     bool parseItemHOk =
603         ParseJsDimensionVp(itemHeightValue, dimPosition) && (dimPosition.Unit() != DimensionUnit::PERCENT);
604     swiperParameters.itemHeight = parseItemHOk && dimPosition > 0.0_vp ? dimPosition : defaultSize;
605     bool parseSelectedItemWOk =
606         ParseJsDimensionVp(selectedItemWidthValue, dimPosition) && (dimPosition.Unit() != DimensionUnit::PERCENT);
607     swiperParameters.selectedItemWidth = parseSelectedItemWOk && dimPosition > 0.0_vp ? dimPosition : defaultSize;
608     bool parseSelectedItemHOk =
609         ParseJsDimensionVp(selectedItemHeightValue, dimPosition) && (dimPosition.Unit() != DimensionUnit::PERCENT);
610     swiperParameters.selectedItemHeight = parseSelectedItemHOk && dimPosition > 0.0_vp ? dimPosition : defaultSize;
611     SwiperModel::GetInstance()->SetIsIndicatorCustomSize(
612         parseSelectedItemWOk || parseSelectedItemHOk || parseItemWOk || parseItemHOk);
613     SetDotIndicatorInfo(obj, swiperParameters, swiperIndicatorTheme);
614     return swiperParameters;
615 }
SetDotIndicatorInfo(const JSRef<JSObject> & obj,SwiperParameters & swiperParameters,const RefPtr<SwiperIndicatorTheme> & swiperIndicatorTheme)616 void JSSwiper::SetDotIndicatorInfo(const JSRef<JSObject>& obj, SwiperParameters& swiperParameters,
617     const RefPtr<SwiperIndicatorTheme>& swiperIndicatorTheme)
618 {
619     JSRef<JSVal> maskValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::MASK_VALUE));
620     JSRef<JSVal> colorValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::COLOR_VALUE));
621     JSRef<JSVal> selectedColorValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::SELECTED_COLOR_VALUE));
622     JSRef<JSVal> maxDisplayCountVal = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::MAX_DISPLAY_COUNT_VALUE));
623     if (maskValue->IsBoolean()) {
624         auto mask = maskValue->ToBoolean();
625         swiperParameters.maskValue = mask;
626     }
627     Color colorVal;
628     auto parseOk = ParseJsColor(colorValue, colorVal);
629     swiperParameters.colorVal = parseOk ? colorVal : swiperIndicatorTheme->GetColor();
630     parseOk = ParseJsColor(selectedColorValue, colorVal);
631     swiperParameters.selectedColorVal = parseOk ? colorVal : swiperIndicatorTheme->GetSelectedColor();
632     if (maxDisplayCountVal->IsUndefined()) {
633         return;
634     }
635     uint32_t result = 0;
636     auto setMaxDisplayCountVal = ParseJsInteger(maxDisplayCountVal, result);
637     swiperParameters.maxDisplayCountVal = setMaxDisplayCountVal && result > 0 ? result : 0;
638 }
ParseLengthMetricsToDimension(const JSRef<JSVal> & jsValue,CalcDimension & result)639 bool JSSwiper::ParseLengthMetricsToDimension(const JSRef<JSVal>& jsValue, CalcDimension& result)
640 {
641     if (jsValue->IsNumber()) {
642         result = CalcDimension(jsValue->ToNumber<double>(), DimensionUnit::VP);
643         return true;
644     }
645     if (jsValue->IsString()) {
646         auto value = jsValue->ToString();
647         StringUtils::StringToCalcDimensionNG(value, result, false, DimensionUnit::VP);
648         return true;
649     }
650     if (jsValue->IsObject()) {
651         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
652         double value = jsObj->GetProperty("value")->ToNumber<double>();
653         auto unit = static_cast<DimensionUnit>(jsObj->GetProperty("unit")->ToNumber<int32_t>());
654         result = CalcDimension(value, unit);
655         return true;
656     }
657     if (jsValue->IsNull()) {
658         result = CalcDimension(0.0f, DimensionUnit::VP);
659         return true;
660     }
661 
662     return false;
663 }
664 
ParseSpace(const JSRef<JSVal> & jsValue,CalcDimension & result)665 bool JSSwiper::ParseSpace(const JSRef<JSVal>& jsValue, CalcDimension& result)
666 {
667     if (jsValue->IsNumber()) {
668         result = CalcDimension(jsValue->ToNumber<double>(), DimensionUnit::VP);
669         return true;
670     }
671     if (jsValue->IsString()) {
672         auto value = jsValue->ToString();
673         StringUtils::StringToCalcDimensionNG(value, result, false, DimensionUnit::VP);
674         return true;
675     }
676     if (jsValue->IsObject()) {
677         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
678         double value = jsObj->GetProperty("value")->ToNumber<double>();
679         auto unit = static_cast<DimensionUnit>(jsObj->GetProperty("unit")->ToNumber<int32_t>());
680         result = CalcDimension(value, unit);
681         return true;
682     }
683 
684     return false;
685 }
686 
GetDigitIndicatorInfo(const JSRef<JSObject> & obj)687 SwiperDigitalParameters JSSwiper::GetDigitIndicatorInfo(const JSRef<JSObject>& obj)
688 {
689     JSRef<JSVal> dotLeftValue = obj->GetProperty("leftValue");
690     JSRef<JSVal> dotTopValue = obj->GetProperty("topValue");
691     JSRef<JSVal> dotRightValue = obj->GetProperty("rightValue");
692     JSRef<JSVal> dotBottomValue = obj->GetProperty("bottomValue");
693     JSRef<JSVal> startValue = obj->GetProperty("startValue");
694     JSRef<JSVal> endValue = obj->GetProperty("endValue");
695     JSRef<JSVal> fontColorValue = obj->GetProperty("fontColorValue");
696     JSRef<JSVal> selectedFontColorValue = obj->GetProperty("selectedFontColorValue");
697     JSRef<JSVal> digitFontValue = obj->GetProperty("digitFontValue");
698     JSRef<JSVal> selectedDigitFontValue = obj->GetProperty("selectedDigitFontValue");
699     JSRef<JSVal> ignoreSizeValue = obj->GetProperty("ignoreSizeValue");
700     JSRef<JSVal> setIgnoreSizeValue = obj->GetProperty("setIgnoreSizeValue");
701     auto pipelineContext = PipelineBase::GetCurrentContext();
702     CHECK_NULL_RETURN(pipelineContext, SwiperDigitalParameters());
703     auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
704     CHECK_NULL_RETURN(swiperIndicatorTheme, SwiperDigitalParameters());
705     SwiperDigitalParameters digitalParameters;
706     digitalParameters.dimLeft = ParseIndicatorDimension(dotLeftValue);
707     digitalParameters.dimTop = ParseIndicatorDimension(dotTopValue);
708     digitalParameters.dimRight = ParseIndicatorDimension(dotRightValue);
709 
710     bool hasIgnoreSizeValue = setIgnoreSizeValue->IsBoolean() ? setIgnoreSizeValue->ToBoolean() : false;
711     auto bottom = ParseIndicatorBottom(dotBottomValue, hasIgnoreSizeValue);
712     digitalParameters.dimBottom = bottom;
713     std::optional<Dimension> indicatorDimension;
714     CalcDimension dimStart;
715     CalcDimension dimEnd;
716     digitalParameters.dimStart =  ParseLengthMetricsToDimension(startValue, dimStart) ? dimStart : indicatorDimension;
717     digitalParameters.dimEnd =  ParseLengthMetricsToDimension(endValue, dimEnd) ? dimEnd : indicatorDimension;
718 
719     if (ignoreSizeValue->IsBoolean()) {
720         auto ignoreSize = ignoreSizeValue->ToBoolean();
721         digitalParameters.ignoreSizeValue = ignoreSize;
722     } else {
723         digitalParameters.ignoreSizeValue = false;
724     }
725 
726     Color fontColor;
727     auto parseOk = JSViewAbstract::ParseJsColor(fontColorValue, fontColor);
728     digitalParameters.fontColor =
729         parseOk ? fontColor : swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetTextColor();
730     parseOk = JSViewAbstract::ParseJsColor(selectedFontColorValue, fontColor);
731     digitalParameters.selectedFontColor =
732         parseOk ? fontColor : swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetTextColor();
733     if (!digitFontValue->IsNull() && digitFontValue->IsObject()) {
734         GetFontContent(digitFontValue, false, digitalParameters);
735     }
736     if (!selectedDigitFontValue->IsNull() && selectedDigitFontValue->IsObject()) {
737         GetFontContent(selectedDigitFontValue, true, digitalParameters);
738     }
739     return digitalParameters;
740 }
741 
GetArrowInfo(const JSRef<JSObject> & obj,SwiperArrowParameters & swiperArrowParameters)742 bool JSSwiper::GetArrowInfo(const JSRef<JSObject>& obj, SwiperArrowParameters& swiperArrowParameters)
743 {
744     auto isShowBackgroundValue = obj->GetProperty("showBackground");
745     auto isSidebarMiddleValue = obj->GetProperty("isSidebarMiddle");
746     auto backgroundSizeValue = obj->GetProperty("backgroundSize");
747     auto backgroundColorValue = obj->GetProperty("backgroundColor");
748     auto arrowSizeValue = obj->GetProperty("arrowSize");
749     auto arrowColorValue = obj->GetProperty("arrowColor");
750     auto pipelineContext = PipelineBase::GetCurrentContext();
751     CHECK_NULL_RETURN(pipelineContext, false);
752     auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
753     CHECK_NULL_RETURN(swiperIndicatorTheme, false);
754     swiperArrowParameters.isShowBackground = isShowBackgroundValue->IsBoolean()
755                                                  ? isShowBackgroundValue->ToBoolean()
756                                                  : swiperIndicatorTheme->GetIsShowArrowBackground();
757     swiperArrowParameters.isSidebarMiddle = isSidebarMiddleValue->IsBoolean()
758                                                 ? isSidebarMiddleValue->ToBoolean()
759                                                 : swiperIndicatorTheme->GetIsSidebarMiddle();
760     bool parseOk = false;
761     CalcDimension dimension;
762     Color color;
763     if (swiperArrowParameters.isSidebarMiddle.value()) {
764         parseOk = ParseJsDimensionVp(backgroundSizeValue, dimension);
765         swiperArrowParameters.backgroundSize =
766             parseOk && GreatNotEqual(dimension.ConvertToVp(), 0.0) && !(dimension.Unit() == DimensionUnit::PERCENT)
767                 ? dimension
768                 : swiperIndicatorTheme->GetBigArrowBackgroundSize();
769         parseOk = ParseJsColor(backgroundColorValue, color);
770         swiperArrowParameters.backgroundColor = parseOk ? color : swiperIndicatorTheme->GetBigArrowBackgroundColor();
771         if (swiperArrowParameters.isShowBackground.value()) {
772             swiperArrowParameters.arrowSize = swiperArrowParameters.backgroundSize.value() * ARROW_SIZE_COEFFICIENT;
773         } else {
774             parseOk = ParseJsDimensionVpNG(arrowSizeValue, dimension);
775             swiperArrowParameters.arrowSize =
776                 parseOk && GreatNotEqual(dimension.ConvertToVp(), 0.0) && !(dimension.Unit() == DimensionUnit::PERCENT)
777                     ? dimension
778                     : swiperIndicatorTheme->GetBigArrowSize();
779             swiperArrowParameters.backgroundSize = swiperArrowParameters.arrowSize;
780         }
781         parseOk = ParseJsColor(arrowColorValue, color);
782         swiperArrowParameters.arrowColor = parseOk ? color : swiperIndicatorTheme->GetBigArrowColor();
783     } else {
784         parseOk = ParseJsDimensionVp(backgroundSizeValue, dimension);
785         swiperArrowParameters.backgroundSize =
786             parseOk && GreatNotEqual(dimension.ConvertToVp(), 0.0) && !(dimension.Unit() == DimensionUnit::PERCENT)
787                 ? dimension
788                 : swiperIndicatorTheme->GetSmallArrowBackgroundSize();
789         parseOk = ParseJsColor(backgroundColorValue, color);
790         swiperArrowParameters.backgroundColor = parseOk ? color : swiperIndicatorTheme->GetSmallArrowBackgroundColor();
791         if (swiperArrowParameters.isShowBackground.value()) {
792             swiperArrowParameters.arrowSize = swiperArrowParameters.backgroundSize.value() * ARROW_SIZE_COEFFICIENT;
793         } else {
794             parseOk = ParseJsDimensionVpNG(arrowSizeValue, dimension);
795             swiperArrowParameters.arrowSize =
796                 parseOk && GreatNotEqual(dimension.ConvertToVp(), 0.0) && !(dimension.Unit() == DimensionUnit::PERCENT)
797                     ? dimension
798                     : swiperIndicatorTheme->GetSmallArrowSize();
799             swiperArrowParameters.backgroundSize = swiperArrowParameters.arrowSize;
800         }
801         parseOk = ParseJsColor(arrowColorValue, color);
802         swiperArrowParameters.arrowColor = parseOk ? color : swiperIndicatorTheme->GetSmallArrowColor();
803     }
804     return true;
805 }
806 
SetDisplayArrow(const JSCallbackInfo & info)807 void JSSwiper::SetDisplayArrow(const JSCallbackInfo& info)
808 {
809     if (info[0]->IsEmpty() || info[0]->IsUndefined()) {
810         SwiperModel::GetInstance()->SetDisplayArrow(false);
811         return;
812     }
813     if (info.Length() > 0 && info[0]->IsObject()) {
814         auto obj = JSRef<JSObject>::Cast(info[0]);
815         SwiperArrowParameters swiperArrowParameters;
816         if (!GetArrowInfo(obj, swiperArrowParameters)) {
817             SwiperModel::GetInstance()->SetDisplayArrow(false);
818             return;
819         }
820         JSSwiperTheme::ApplyThemeToDisplayArrow(swiperArrowParameters, obj);
821         SwiperModel::GetInstance()->SetArrowStyle(swiperArrowParameters);
822         SwiperModel::GetInstance()->SetDisplayArrow(true);
823     } else if (info[0]->IsBoolean()) {
824         if (info[0]->ToBoolean()) {
825             auto pipelineContext = PipelineBase::GetCurrentContext();
826             CHECK_NULL_VOID(pipelineContext);
827             auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
828             CHECK_NULL_VOID(swiperIndicatorTheme);
829             SwiperArrowParameters swiperArrowParameters;
830             swiperArrowParameters.isShowBackground = swiperIndicatorTheme->GetIsShowArrowBackground();
831             swiperArrowParameters.isSidebarMiddle = swiperIndicatorTheme->GetIsSidebarMiddle();
832             swiperArrowParameters.backgroundSize = swiperIndicatorTheme->GetSmallArrowBackgroundSize();
833             swiperArrowParameters.backgroundColor = swiperIndicatorTheme->GetSmallArrowBackgroundColor();
834             swiperArrowParameters.arrowSize = swiperIndicatorTheme->GetSmallArrowSize();
835             swiperArrowParameters.arrowColor = swiperIndicatorTheme->GetSmallArrowColor();
836             JSSwiperTheme::ApplyThemeToDisplayArrowForce(swiperArrowParameters);
837             SwiperModel::GetInstance()->SetArrowStyle(swiperArrowParameters);
838             SwiperModel::GetInstance()->SetDisplayArrow(true);
839         } else {
840             SwiperModel::GetInstance()->SetDisplayArrow(false);
841             return;
842         }
843     } else {
844         SwiperModel::GetInstance()->SetDisplayArrow(false);
845         return;
846     }
847     if (info.Length() > 1 && info[1]->IsBoolean()) {
848         SwiperModel::GetInstance()->SetHoverShow(info[1]->ToBoolean());
849     } else {
850         SwiperModel::GetInstance()->SetHoverShow(false);
851     }
852 }
853 
SetIndicatorController(const JSCallbackInfo & info)854 void JSSwiper::SetIndicatorController(const JSCallbackInfo& info)
855 {
856     if (info.Length() < 1 || !info[0]->IsObject()) {
857         return;
858     }
859 
860     auto* jsIndicatorController = JSRef<JSObject>::Cast(info[0])->Unwrap<JSIndicatorController>();
861     if (!jsIndicatorController) {
862         return;
863     }
864     jSIndicatorController_ = jsIndicatorController;
865     SwiperModel::GetInstance()->SetBindIndicator(true);
866     WeakPtr<NG::UINode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
867     jsIndicatorController->SetSwiperNode(targetNode);
868 }
869 
ResetSwiperNode()870 void JSSwiper::ResetSwiperNode()
871 {
872     if (jSIndicatorController_.Upgrade()) {
873         jSIndicatorController_.Upgrade()->ResetSwiperNode();
874     }
875 }
876 
SetIndicator(const JSCallbackInfo & info)877 void JSSwiper::SetIndicator(const JSCallbackInfo& info)
878 {
879     if (info.Length() < 1) {
880         return;
881     }
882 
883     if (info[0]->IsEmpty()) {
884         SwiperModel::GetInstance()->SetShowIndicator(true);
885         return;
886     }
887     SwiperModel::GetInstance()->SetBindIndicator(false);
888     if (info[0]->IsObject()) {
889         auto obj = JSRef<JSObject>::Cast(info[0]);
890         SwiperModel::GetInstance()->SetIndicatorIsBoolean(false);
891         ResetSwiperNode();
892 
893         JSRef<JSVal> typeParam = obj->GetProperty("type");
894         if (typeParam->IsString()) {
895             auto type = typeParam->ToString();
896             if (type == "DigitIndicator") {
897                 SwiperDigitalParameters digitalParameters = GetDigitIndicatorInfo(obj);
898                 JSSwiperTheme::ApplyThemeToDigitIndicator(digitalParameters, obj);
899                 SwiperModel::GetInstance()->SetDigitIndicatorStyle(digitalParameters);
900                 SwiperModel::GetInstance()->SetIndicatorType(SwiperIndicatorType::DIGIT);
901             } else {
902                 SwiperParameters swiperParameters = GetDotIndicatorInfo(obj);
903                 JSSwiperTheme::ApplyThemeToDotIndicator(swiperParameters, obj);
904                 SwiperModel::GetInstance()->SetDotIndicatorStyle(swiperParameters);
905                 SwiperModel::GetInstance()->SetIndicatorType(SwiperIndicatorType::DOT);
906             }
907         } else if (typeParam->IsUndefined()) {
908             SetIndicatorController(info);
909         } else {
910             SwiperParameters swiperParameters = GetDotIndicatorInfo(obj);
911             JSSwiperTheme::ApplyThemeToDotIndicatorForce(swiperParameters);
912             SwiperModel::GetInstance()->SetDotIndicatorStyle(swiperParameters);
913             SwiperModel::GetInstance()->SetIndicatorType(SwiperIndicatorType::DOT);
914         }
915     } else {
916         SwiperParameters swiperParameters = GetDotIndicatorInfo(JSRef<JSObject>::New());
917         JSSwiperTheme::ApplyThemeToDotIndicatorForce(swiperParameters);
918         SwiperModel::GetInstance()->SetDotIndicatorStyle(swiperParameters);
919         SwiperModel::GetInstance()->SetIndicatorType(SwiperIndicatorType::DOT);
920     }
921     if (info[0]->IsBoolean()) {
922         bool showIndicator = false;
923         ParseJsBool(info[0], showIndicator);
924         SwiperModel::GetInstance()->SetShowIndicator(showIndicator);
925     } else {
926         SwiperModel::GetInstance()->SetShowIndicator(true);
927     }
928 }
929 
SetIndicatorStyle(const JSCallbackInfo & info)930 void JSSwiper::SetIndicatorStyle(const JSCallbackInfo& info)
931 {
932     SwiperParameters swiperParameters;
933     if (info[0]->IsObject()) {
934         JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
935         JSRef<JSVal> leftValue = obj->GetProperty("left");
936         JSRef<JSVal> topValue = obj->GetProperty("top");
937         JSRef<JSVal> rightValue = obj->GetProperty("right");
938         JSRef<JSVal> bottomValue = obj->GetProperty("bottom");
939         JSRef<JSVal> sizeValue = obj->GetProperty("size");
940         JSRef<JSVal> maskValue = obj->GetProperty("mask");
941         JSRef<JSVal> colorValue = obj->GetProperty("color");
942         JSRef<JSVal> selectedColorValue = obj->GetProperty("selectedColor");
943         JSRef<JSVal> ignoreSizeValue = obj->GetProperty("ignoreSize");
944         auto pipelineContext = PipelineBase::GetCurrentContext();
945         CHECK_NULL_VOID(pipelineContext);
946         auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
947         CHECK_NULL_VOID(swiperIndicatorTheme);
948         swiperParameters.dimLeft = ParseIndicatorDimension(leftValue);
949         swiperParameters.dimTop = ParseIndicatorDimension(topValue);
950         swiperParameters.dimRight = ParseIndicatorDimension(rightValue);
951         swiperParameters.dimBottom = ParseIndicatorDimension(bottomValue);
952         CalcDimension dimPosition;
953         auto parseOk = ParseJsDimensionVp(sizeValue, dimPosition) && (dimPosition.Unit() != DimensionUnit::PERCENT);
954         SetIsIndicatorCustomSize(dimPosition, parseOk);
955         swiperParameters.itemWidth = parseOk && dimPosition > 0.0_vp ? dimPosition : swiperIndicatorTheme->GetSize();
956         swiperParameters.itemHeight = parseOk && dimPosition > 0.0_vp ? dimPosition : swiperIndicatorTheme->GetSize();
957         swiperParameters.selectedItemWidth =
958             parseOk && dimPosition > 0.0_vp ? dimPosition : swiperIndicatorTheme->GetSize();
959         swiperParameters.selectedItemHeight =
960             parseOk && dimPosition > 0.0_vp ? dimPosition : swiperIndicatorTheme->GetSize();
961         if (maskValue->IsBoolean()) {
962             auto mask = maskValue->ToBoolean();
963             swiperParameters.maskValue = mask;
964         }
965         if (ignoreSizeValue->IsBoolean()) {
966             auto ignoreSize = ignoreSizeValue->ToBoolean();
967             swiperParameters.ignoreSizeValue = ignoreSize;
968         } else {
969             swiperParameters.ignoreSizeValue = false;
970         }
971         Color colorVal;
972         parseOk = ParseJsColor(colorValue, colorVal);
973         swiperParameters.colorVal = parseOk ? colorVal : swiperIndicatorTheme->GetColor();
974         parseOk = ParseJsColor(selectedColorValue, colorVal);
975         swiperParameters.selectedColorVal = parseOk ? colorVal : swiperIndicatorTheme->GetSelectedColor();
976     }
977     SwiperModel::GetInstance()->SetDotIndicatorStyle(swiperParameters);
978     info.ReturnSelf();
979 }
980 
SetItemSpace(const JSCallbackInfo & info)981 void JSSwiper::SetItemSpace(const JSCallbackInfo& info)
982 {
983     if (info.Length() < 1) {
984         return;
985     }
986 
987     CalcDimension value;
988     if (!ParseJsDimensionVp(info[0], value) || LessNotEqual(value.Value(), 0.0)) {
989         value.SetValue(0.0);
990     }
991 
992     SwiperModel::GetInstance()->SetItemSpace(value);
993 }
994 
SetPreviousMargin(const JSCallbackInfo & info)995 void JSSwiper::SetPreviousMargin(const JSCallbackInfo& info)
996 {
997     if (info.Length() < 1) {
998         return;
999     }
1000 
1001     CalcDimension value;
1002     bool ignoreBlank = false;
1003     if (!ParseJsDimensionVp(info[0], value) || info[0]->IsNull() || info[0]->IsUndefined() ||
1004         LessNotEqual(value.Value(), 0.0)) {
1005         value.SetValue(0.0);
1006     }
1007     if (info.Length() > 1 && info[1]->IsBoolean()) {
1008         ignoreBlank = info[1]->ToBoolean();
1009     }
1010     SwiperModel::GetInstance()->SetPreviousMargin(value, ignoreBlank);
1011 }
1012 
SetNextMargin(const JSCallbackInfo & info)1013 void JSSwiper::SetNextMargin(const JSCallbackInfo& info)
1014 {
1015     if (info.Length() < 1) {
1016         return;
1017     }
1018 
1019     CalcDimension value;
1020     bool ignoreBlank = false;
1021     if (!ParseJsDimensionVp(info[0], value) || info[0]->IsNull() || info[0]->IsUndefined() ||
1022         LessNotEqual(value.Value(), 0.0)) {
1023         value.SetValue(0.0);
1024     }
1025     if (info.Length() > 1 && info[1]->IsBoolean()) {
1026         ignoreBlank = info[1]->ToBoolean();
1027     }
1028     SwiperModel::GetInstance()->SetNextMargin(value, ignoreBlank);
1029 }
1030 
SetDisplayMode(int32_t index)1031 void JSSwiper::SetDisplayMode(int32_t index)
1032 {
1033     if (index < 0 || index >= static_cast<int32_t>(DISPLAY_MODE.size())) {
1034         return;
1035     }
1036 
1037     SwiperModel::GetInstance()->SetDisplayMode(DISPLAY_MODE[index]);
1038 }
1039 
SetCachedCount(const JSCallbackInfo & info)1040 void JSSwiper::SetCachedCount(const JSCallbackInfo& info)
1041 {
1042     if (info.Length() < 1) {
1043         return;
1044     }
1045 
1046     int32_t cachedCount = DEFAULT_CACHED_COUNT;
1047     if (!info[0]->IsUndefined() && info[0]->IsNumber()) {
1048         cachedCount = info[0]->ToNumber<int32_t>();
1049         if (cachedCount < 0) {
1050             cachedCount = DEFAULT_CACHED_COUNT;
1051         }
1052     }
1053     SwiperModel::GetInstance()->SetCachedCount(cachedCount);
1054 
1055     auto isShown = info.Length() > 1 && info[1]->IsBoolean() && info[1]->ToBoolean();
1056     SwiperModel::GetInstance()->SetCachedIsShown(isShown);
1057 }
1058 
SetCurve(const JSCallbackInfo & info)1059 void JSSwiper::SetCurve(const JSCallbackInfo& info)
1060 {
1061     RefPtr<Curve> curve = DEFAULT_CURVE;
1062     if (info[0]->IsString()) {
1063         curve = CreateCurve(info[0]->ToString(), false);
1064         if (!curve) {
1065             curve = DEFAULT_CURVE;
1066         }
1067     } else if (info[0]->IsObject()) {
1068         auto object = JSRef<JSObject>::Cast(info[0]);
1069         std::function<float(float)> customCallBack = nullptr;
1070         JSRef<JSVal> onCallBack = object->GetProperty("__curveCustomFunc");
1071         if (onCallBack->IsFunction()) {
1072             RefPtr<JsFunction> jsFuncCallBack =
1073                 AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onCallBack));
1074             customCallBack = [func = std::move(jsFuncCallBack), id = Container::CurrentId()](float time) -> float {
1075                 ContainerScope scope(id);
1076                 JSRef<JSVal> params[1];
1077                 params[0] = JSRef<JSVal>::Make(ToJSValue(time));
1078                 auto result = func->ExecuteJS(1, params);
1079                 auto resultValue = result->IsNumber() ? result->ToNumber<float>() : 1.0f;
1080                 return resultValue;
1081             };
1082         }
1083         auto jsCurveString = object->GetProperty("__curveString");
1084         if (jsCurveString->IsString()) {
1085             auto aniTimFunc = jsCurveString->ToString();
1086             if (aniTimFunc == DOM_ANIMATION_TIMING_FUNCTION_CUSTOM && customCallBack) {
1087                 curve = CreateCurve(customCallBack);
1088             } else if (aniTimFunc != DOM_ANIMATION_TIMING_FUNCTION_CUSTOM) {
1089                 curve = CreateCurve(aniTimFunc);
1090             }
1091         }
1092     }
1093     SwiperModel::GetInstance()->SetCurve(curve);
1094 }
1095 
SetOnChange(const JSCallbackInfo & info)1096 void JSSwiper::SetOnChange(const JSCallbackInfo& info)
1097 {
1098     if (!info[0]->IsFunction()) {
1099         return;
1100     }
1101 
1102     auto changeHandler = AceType::MakeRefPtr<JsEventFunction<SwiperChangeEvent, 1>>(
1103         JSRef<JSFunc>::Cast(info[0]), SwiperChangeEventToJSValue);
1104     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1105     auto onChange = [executionContext = info.GetExecutionContext(), func = std::move(changeHandler), node = targetNode](
1106                         const BaseEventInfo* info) {
1107         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
1108         const auto* swiperInfo = TypeInfoHelper::DynamicCast<SwiperChangeEvent>(info);
1109         if (!swiperInfo) {
1110             TAG_LOGW(AceLogTag::ACE_SWIPER, "Swiper onChange callback execute failed.");
1111             return;
1112         }
1113         ACE_SCORING_EVENT("Swiper.OnChange");
1114         PipelineContext::SetCallBackNode(node);
1115         func->Execute(*swiperInfo);
1116     };
1117 
1118     SwiperModel::GetInstance()->SetOnChange(std::move(onChange));
1119 }
1120 
SetOnUnselected(const JSCallbackInfo & info)1121 void JSSwiper::SetOnUnselected(const JSCallbackInfo& info)
1122 {
1123     if (!info[0]->IsFunction()) {
1124         return;
1125     }
1126     auto unselectedHandler = AceType::MakeRefPtr<JsEventFunction<SwiperChangeEvent, 1>>(
1127         JSRef<JSFunc>::Cast(info[0]), SwiperChangeEventToJSValue);
1128     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1129     auto onUnselected = [executionContext = info.GetExecutionContext(), func = std::move(unselectedHandler),
1130                           node = targetNode](const BaseEventInfo* info) {
1131         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
1132         const auto* swiperInfo = TypeInfoHelper::DynamicCast<SwiperChangeEvent>(info);
1133         if (!swiperInfo) {
1134             TAG_LOGW(AceLogTag::ACE_SWIPER, "Swiper onUnselected callback execute failed.");
1135             return;
1136         }
1137         ACE_SCORING_EVENT("Swiper.onUnselected");
1138         ACE_SCOPED_TRACE("Swiper.onUnselected index %d", swiperInfo->GetIndex());
1139         PipelineContext::SetCallBackNode(node);
1140         func->Execute(*swiperInfo);
1141     };
1142     SwiperModel::GetInstance()->SetOnUnselected(std::move(onUnselected));
1143 }
1144 
SetOnAnimationStart(const JSCallbackInfo & info)1145 void JSSwiper::SetOnAnimationStart(const JSCallbackInfo& info)
1146 {
1147     if (!info[0]->IsFunction()) {
1148         return;
1149     }
1150 
1151     if (Container::IsCurrentUseNewPipeline()) {
1152         auto animationStartHandler = AceType::MakeRefPtr<JsSwiperFunction>(JSRef<JSFunc>::Cast(info[0]));
1153         auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1154         auto onAnimationStart = [executionContext = info.GetExecutionContext(), func = std::move(animationStartHandler),
1155                                     node = targetNode](
1156                                     int32_t index, int32_t targetIndex, const AnimationCallbackInfo& info) {
1157             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
1158             ACE_SCORING_EVENT("Swiper.onAnimationStart");
1159             PipelineContext::SetCallBackNode(node);
1160             func->Execute(index, targetIndex, info);
1161         };
1162 
1163         SwiperModel::GetInstance()->SetOnAnimationStart(std::move(onAnimationStart));
1164         return;
1165     }
1166 
1167     auto animationStartHandler = AceType::MakeRefPtr<JsEventFunction<SwiperChangeEvent, 1>>(
1168         JSRef<JSFunc>::Cast(info[0]), SwiperChangeEventToJSValue);
1169     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1170     auto onAnimationStart = [executionContext = info.GetExecutionContext(), func = std::move(animationStartHandler),
1171                                 node = targetNode](const BaseEventInfo* info) {
1172         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
1173         const auto* swiperInfo = TypeInfoHelper::DynamicCast<SwiperChangeEvent>(info);
1174         if (!swiperInfo) {
1175             TAG_LOGW(AceLogTag::ACE_SWIPER, "Swiper onAnimationStart callback execute failed.");
1176             return;
1177         }
1178         ACE_SCORING_EVENT("Swiper.onAnimationStart");
1179         PipelineContext::SetCallBackNode(node);
1180         func->Execute(*swiperInfo);
1181     };
1182 
1183     SwiperModel::GetInstance()->SetOnAnimationStart(std::move(onAnimationStart));
1184 }
1185 
SetOnAnimationEnd(const JSCallbackInfo & info)1186 void JSSwiper::SetOnAnimationEnd(const JSCallbackInfo& info)
1187 {
1188     if (!info[0]->IsFunction()) {
1189         return;
1190     }
1191 
1192     if (Container::IsCurrentUseNewPipeline()) {
1193         auto animationEndHandler = AceType::MakeRefPtr<JsSwiperFunction>(JSRef<JSFunc>::Cast(info[0]));
1194         auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1195         auto onAnimationEnd = [executionContext = info.GetExecutionContext(), func = std::move(animationEndHandler),
1196                                   node = targetNode](int32_t index, const AnimationCallbackInfo& info) {
1197             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
1198             ACE_SCORING_EVENT("Swiper.onAnimationEnd");
1199             PipelineContext::SetCallBackNode(node);
1200             func->Execute(index, info);
1201         };
1202 
1203         SwiperModel::GetInstance()->SetOnAnimationEnd(std::move(onAnimationEnd));
1204         return;
1205     }
1206 
1207     auto animationEndHandler = AceType::MakeRefPtr<JsEventFunction<SwiperChangeEvent, 1>>(
1208         JSRef<JSFunc>::Cast(info[0]), SwiperChangeEventToJSValue);
1209     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1210     auto onAnimationEnd = [executionContext = info.GetExecutionContext(), func = std::move(animationEndHandler),
1211                               node = targetNode](const BaseEventInfo* info) {
1212         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
1213         const auto* swiperInfo = TypeInfoHelper::DynamicCast<SwiperChangeEvent>(info);
1214         if (!swiperInfo) {
1215             TAG_LOGW(AceLogTag::ACE_SWIPER, "Swiper onAnimationEnd callback execute failed.");
1216             return;
1217         }
1218         ACE_SCORING_EVENT("Swiper.onAnimationEnd");
1219         PipelineContext::SetCallBackNode(node);
1220         func->Execute(*swiperInfo);
1221     };
1222 
1223     SwiperModel::GetInstance()->SetOnAnimationEnd(std::move(onAnimationEnd));
1224 }
1225 
SetOnGestureSwipe(const JSCallbackInfo & info)1226 void JSSwiper::SetOnGestureSwipe(const JSCallbackInfo& info)
1227 {
1228     if (!info[0]->IsFunction()) {
1229         return;
1230     }
1231 
1232     auto gestureSwipeHandler = AceType::MakeRefPtr<JsSwiperFunction>(JSRef<JSFunc>::Cast(info[0]));
1233     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1234     auto onGestureSwipe = [executionContext = info.GetExecutionContext(), func = std::move(gestureSwipeHandler),
1235                               node = targetNode](int32_t index, const AnimationCallbackInfo& info) {
1236         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
1237         ACE_SCORING_EVENT("Swiper.onGestureSwipe");
1238         PipelineContext::SetCallBackNode(node);
1239         func->Execute(index, info);
1240     };
1241 
1242     SwiperModel::GetInstance()->SetOnGestureSwipe(std::move(onGestureSwipe));
1243 }
1244 
SetOnClick(const JSCallbackInfo & info)1245 void JSSwiper::SetOnClick(const JSCallbackInfo& info)
1246 {
1247     if (Container::IsCurrentUseNewPipeline()) {
1248         JSInteractableView::JsOnClick(info);
1249         return;
1250     }
1251 
1252     if (!info[0]->IsFunction()) {
1253         return;
1254     }
1255 
1256     RefPtr<JsClickFunction> jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(info[0]));
1257     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1258     auto onClick = [execCtx = info.GetExecutionContext(), func = std::move(jsOnClickFunc), node = targetNode](
1259                        const BaseEventInfo* info, const RefPtr<V2::InspectorFunctionImpl>& impl) {
1260         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1261         const auto* clickInfo = TypeInfoHelper::DynamicCast<ClickInfo>(info);
1262         if (!clickInfo) {
1263             TAG_LOGW(AceLogTag::ACE_SWIPER, "Swiper onClick callback execute failed.");
1264             return;
1265         }
1266         auto newInfo = *clickInfo;
1267         if (impl) {
1268             impl->UpdateEventInfo(newInfo);
1269         }
1270         ACE_SCORING_EVENT("onClick");
1271         PipelineContext::SetCallBackNode(node);
1272         func->Execute(newInfo);
1273     };
1274 
1275     SwiperModel::GetInstance()->SetOnClick(onClick);
1276 }
1277 
SetWidth(const JSCallbackInfo & info)1278 void JSSwiper::SetWidth(const JSCallbackInfo& info)
1279 {
1280     if (info.Length() < 1) {
1281         return;
1282     }
1283 
1284     SetWidth(info[0]);
1285 }
1286 
SetWidth(const JSRef<JSVal> & jsValue)1287 void JSSwiper::SetWidth(const JSRef<JSVal>& jsValue)
1288 {
1289     if (Container::IsCurrentUseNewPipeline()) {
1290         JSViewAbstract::JsWidth(jsValue);
1291         return;
1292     }
1293 
1294     JSViewAbstract::JsWidth(jsValue);
1295     SwiperModel::GetInstance()->SetMainSwiperSizeWidth();
1296 }
1297 
SetHeight(const JSRef<JSVal> & jsValue)1298 void JSSwiper::SetHeight(const JSRef<JSVal>& jsValue)
1299 {
1300     if (Container::IsCurrentUseNewPipeline()) {
1301         JSViewAbstract::JsHeight(jsValue);
1302         return;
1303     }
1304 
1305     JSViewAbstract::JsHeight(jsValue);
1306     SwiperModel::GetInstance()->SetMainSwiperSizeHeight();
1307 }
1308 
SetHeight(const JSCallbackInfo & info)1309 void JSSwiper::SetHeight(const JSCallbackInfo& info)
1310 {
1311     if (info.Length() < 1) {
1312         return;
1313     }
1314 
1315     SetHeight(info[0]);
1316 }
1317 
SetSize(const JSCallbackInfo & info)1318 void JSSwiper::SetSize(const JSCallbackInfo& info)
1319 {
1320     if (info.Length() < 1) {
1321         return;
1322     }
1323 
1324     if (!info[0]->IsObject()) {
1325         return;
1326     }
1327 
1328     JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(info[0]);
1329     SetWidth(sizeObj->GetProperty("width"));
1330     SetHeight(sizeObj->GetProperty("height"));
1331 }
1332 
JSBind(BindingTarget globalObj)1333 void JSSwiperController::JSBind(BindingTarget globalObj)
1334 {
1335     JSClass<JSSwiperController>::Declare("SwiperController");
1336     JSClass<JSSwiperController>::CustomMethod("swipeTo", &JSSwiperController::SwipeTo);
1337     JSClass<JSSwiperController>::CustomMethod("showNext", &JSSwiperController::ShowNext);
1338     JSClass<JSSwiperController>::CustomMethod("showPrevious", &JSSwiperController::ShowPrevious);
1339     JSClass<JSSwiperController>::CustomMethod("changeIndex", &JSSwiperController::ChangeIndex);
1340     JSClass<JSSwiperController>::CustomMethod("finishAnimation", &JSSwiperController::FinishAnimation);
1341     JSClass<JSSwiperController>::CustomMethod("preloadItems", &JSSwiperController::PreloadItems);
1342     JSClass<JSSwiperController>::Bind(globalObj, JSSwiperController::Constructor, JSSwiperController::Destructor);
1343 }
1344 
Constructor(const JSCallbackInfo & args)1345 void JSSwiperController::Constructor(const JSCallbackInfo& args)
1346 {
1347     auto scroller = Referenced::MakeRefPtr<JSSwiperController>();
1348     scroller->IncRefCount();
1349     args.SetReturnValue(Referenced::RawPtr(scroller));
1350 }
1351 
Destructor(JSSwiperController * scroller)1352 void JSSwiperController::Destructor(JSSwiperController* scroller)
1353 {
1354     if (scroller != nullptr) {
1355         scroller->DecRefCount();
1356     }
1357 }
1358 
SwipeTo(const JSCallbackInfo & args)1359 void JSSwiperController::SwipeTo(const JSCallbackInfo& args)
1360 {
1361     ContainerScope scope(instanceId_);
1362     if (args.Length() < 1 || !args[0]->IsNumber()) {
1363         LOGE("Param is not valid");
1364         return;
1365     }
1366     if (controller_) {
1367         controller_->SwipeTo(args[0]->ToNumber<int32_t>());
1368     } else {
1369         EventReport::ReportScrollableErrorEvent(
1370             "Swiper", ScrollableErrorType::CONTROLLER_NOT_BIND, "swipeTo: Swiper controller not bind.");
1371     }
1372 }
1373 
ShowNext(const JSCallbackInfo & args)1374 void JSSwiperController::ShowNext(const JSCallbackInfo& args)
1375 {
1376     ContainerScope scope(instanceId_);
1377     if (controller_) {
1378         controller_->ShowNext();
1379     } else {
1380         EventReport::ReportScrollableErrorEvent(
1381             "Swiper", ScrollableErrorType::CONTROLLER_NOT_BIND, "showNext: Swiper controller not bind.");
1382     }
1383 }
1384 
ShowPrevious(const JSCallbackInfo & args)1385 void JSSwiperController::ShowPrevious(const JSCallbackInfo& args)
1386 {
1387     ContainerScope scope(instanceId_);
1388     if (controller_) {
1389         controller_->ShowPrevious();
1390     } else {
1391         EventReport::ReportScrollableErrorEvent(
1392             "Swiper", ScrollableErrorType::CONTROLLER_NOT_BIND, "showPrevious: Swiper controller not bind.");
1393     }
1394 }
1395 
ChangeIndex(const JSCallbackInfo & args)1396 void JSSwiperController::ChangeIndex(const JSCallbackInfo& args)
1397 {
1398     if (!controller_) {
1399         EventReport::ReportScrollableErrorEvent(
1400             "Swiper", ScrollableErrorType::CONTROLLER_NOT_BIND, "changeIndex: Swiper controller not bind.");
1401         return;
1402     }
1403     if (args.Length() < 1 || !args[0]->IsNumber()) {
1404         return;
1405     }
1406     int32_t index = args[0]->ToNumber<int32_t>();
1407     if (args.Length() > 1 && args[1]->IsNumber()) {
1408         int32_t animationMode = args[1]->ToNumber<int32_t>();
1409         if (animationMode < 0 || animationMode >= static_cast<int32_t>(SWIPER_ANIMATION_MODE.size())) {
1410             animationMode = 0;
1411         }
1412         controller_->ChangeIndex(index, SWIPER_ANIMATION_MODE[animationMode]);
1413         return;
1414     }
1415     bool useAnimation = false;
1416     if (args.Length() > 1 && args[1]->IsBoolean()) {
1417         useAnimation = args[1]->ToBoolean();
1418     }
1419     controller_->ChangeIndex(index, useAnimation);
1420 }
1421 
FinishAnimation(const JSCallbackInfo & args)1422 void JSSwiperController::FinishAnimation(const JSCallbackInfo& args)
1423 {
1424     ContainerScope scope(instanceId_);
1425     if (!controller_) {
1426         EventReport::ReportScrollableErrorEvent(
1427             "Swiper", ScrollableErrorType::CONTROLLER_NOT_BIND, "finishAnimation: Swiper controller not bind.");
1428         return;
1429     }
1430 
1431     if (args.Length() > 0 && args[0]->IsFunction()) {
1432         RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(args[0]));
1433         auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1434         auto onFinish = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]() {
1435             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1436             ACE_SCORING_EVENT("Swiper.finishAnimation");
1437             PipelineContext::SetCallBackNode(node);
1438             TAG_LOGD(AceLogTag::ACE_SWIPER, "SwiperController finishAnimation callback execute.");
1439             func->Execute();
1440         };
1441 
1442         controller_->SetFinishCallback(onFinish);
1443         controller_->FinishAnimation();
1444         return;
1445     }
1446 
1447     controller_->FinishAnimation();
1448 }
1449 
OldPreloadItems(const JSCallbackInfo & args)1450 void JSSwiperController::OldPreloadItems(const JSCallbackInfo& args)
1451 {
1452     ContainerScope scope(instanceId_);
1453     if (!controller_) {
1454         EventReport::ReportScrollableErrorEvent(
1455             "Swiper", ScrollableErrorType::CONTROLLER_NOT_BIND, "preloadItems: Swiper controller not bind.");
1456         return;
1457     }
1458 
1459     if (args.Length() != LENGTH_TWO || !args[0]->IsArray() || !args[1]->IsFunction()) {
1460         return;
1461     }
1462 
1463     auto indexArray = JSRef<JSArray>::Cast(args[0]);
1464     size_t size = indexArray->Length();
1465     std::set<int32_t> indexSet;
1466     for (size_t i = 0; i < size; i++) {
1467         int32_t index = -1;
1468         JSViewAbstract::ParseJsInt32(indexArray->GetValueAt(i), index);
1469         indexSet.emplace(index);
1470     }
1471 
1472     RefPtr<JsSwiperFunction> jsFunc = AceType::MakeRefPtr<JsSwiperFunction>(JSRef<JSFunc>::Cast(args[1]));
1473     auto onPreloadFinish =
1474         [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](int32_t errorCode, std::string message) {
1475             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1476             ACE_SCORING_EVENT("Swiper.preloadItems");
1477             TAG_LOGI(AceLogTag::ACE_SWIPER, "SwiperController preloadItems callback execute.");
1478             func->Execute(errorCode);
1479         };
1480 
1481     controller_->SetPreloadFinishCallback(onPreloadFinish);
1482     controller_->PreloadItems(indexSet);
1483 }
1484 
NewPreloadItems(const JSCallbackInfo & args)1485 void JSSwiperController::NewPreloadItems(const JSCallbackInfo& args)
1486 {
1487     if (!controller_) {
1488         EventReport::ReportScrollableErrorEvent(
1489             "Swiper", ScrollableErrorType::CONTROLLER_NOT_BIND, "preloadItems: Swiper controller not bind.");
1490         JSException::Throw(ERROR_CODE_NAMED_ROUTE_ERROR, "%s", "Controller not bound to component.");
1491         return;
1492     }
1493 
1494     ContainerScope scope(instanceId_);
1495     auto engine = EngineHelper::GetCurrentEngine();
1496     CHECK_NULL_VOID(engine);
1497     NativeEngine* nativeEngine = engine->GetNativeEngine();
1498     auto env = reinterpret_cast<napi_env>(nativeEngine);
1499     auto asyncContext = std::make_shared<SwiperControllerAsyncContext>();
1500     asyncContext->env = env;
1501     napi_value promise = nullptr;
1502     napi_create_promise(env, &asyncContext->deferred, &promise);
1503     ScopeRAII scopeRaii(env);
1504     std::set<int32_t> indexSet;
1505     if (args.Length() > 0 && args[0]->IsArray()) {
1506         auto indexArray = JSRef<JSArray>::Cast(args[0]);
1507         size_t size = indexArray->Length();
1508         for (size_t i = 0; i < size; i++) {
1509             int32_t index = -1;
1510             JSViewAbstract::ParseJsInt32(indexArray->GetValueAt(i), index);
1511             indexSet.emplace(index);
1512         }
1513     }
1514 
1515     auto onPreloadFinish = [asyncContext](int32_t errorCode, std::string message) {
1516         CHECK_NULL_VOID(asyncContext);
1517         HandleDeferred(asyncContext, errorCode, message);
1518     };
1519     controller_->SetPreloadFinishCallback(onPreloadFinish);
1520     controller_->PreloadItems(indexSet);
1521     ReturnPromise(args, promise);
1522 }
1523 
PreloadItems(const JSCallbackInfo & args)1524 void JSSwiperController::PreloadItems(const JSCallbackInfo& args)
1525 {
1526     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN) && args.Length() == 1) {
1527         NewPreloadItems(args);
1528         return;
1529     }
1530 
1531     OldPreloadItems(args);
1532 }
1533 
SetNestedScroll(const JSCallbackInfo & args)1534 void JSSwiper::SetNestedScroll(const JSCallbackInfo& args)
1535 {
1536     // default value
1537     NestedScrollOptions nestedOpt = {
1538         .forward = NestedScrollMode::SELF_ONLY,
1539         .backward = NestedScrollMode::SELF_ONLY,
1540     };
1541     if (args.Length() < 1 || !args[0]->IsNumber()) {
1542         SwiperModel::GetInstance()->SetNestedScroll(nestedOpt);
1543         return;
1544     }
1545     int32_t value = -1;
1546     JSViewAbstract::ParseJsInt32(args[0], value);
1547     auto mode = static_cast<NestedScrollMode>(value);
1548     if (mode < NestedScrollMode::SELF_ONLY || mode > NestedScrollMode::SELF_FIRST) {
1549         SwiperModel::GetInstance()->SetNestedScroll(nestedOpt);
1550         return;
1551     }
1552     nestedOpt.forward = mode;
1553     nestedOpt.backward = mode;
1554     SwiperModel::GetInstance()->SetNestedScroll(nestedOpt);
1555     args.ReturnSelf();
1556 }
1557 
SetCustomContentTransition(const JSCallbackInfo & info)1558 void JSSwiper::SetCustomContentTransition(const JSCallbackInfo& info)
1559 {
1560     if (info.Length() < 1 || !info[0]->IsObject()) {
1561         return;
1562     }
1563 
1564     SwiperContentAnimatedTransition transitionInfo;
1565     auto transitionObj = JSRef<JSObject>::Cast(info[0]);
1566     JSRef<JSVal> timeoutProperty = transitionObj->GetProperty("timeout");
1567     if (timeoutProperty->IsNumber()) {
1568         auto timeout = timeoutProperty->ToNumber<int32_t>();
1569         transitionInfo.timeout = timeout < 0 ? DEFAULT_CUSTOM_ANIMATION_TIMEOUT : timeout;
1570     } else {
1571         transitionInfo.timeout = DEFAULT_CUSTOM_ANIMATION_TIMEOUT;
1572     }
1573 
1574     JSRef<JSVal> transition = transitionObj->GetProperty("transition");
1575     if (transition->IsFunction()) {
1576         auto jsOnTransition = AceType::MakeRefPtr<JsSwiperFunction>(JSRef<JSFunc>::Cast(transition));
1577         auto onTransition = [execCtx = info.GetExecutionContext(), func = std::move(jsOnTransition)](
1578                                 const RefPtr<SwiperContentTransitionProxy>& proxy) {
1579             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1580             ACE_SCORING_EVENT("Swiper.customContentTransition");
1581             func->Execute(proxy);
1582         };
1583         transitionInfo.transition = std::move(onTransition);
1584     }
1585     SwiperModel::GetInstance()->SetCustomContentTransition(transitionInfo);
1586 }
1587 
SetOnContentDidScroll(const JSCallbackInfo & info)1588 void JSSwiper::SetOnContentDidScroll(const JSCallbackInfo& info)
1589 {
1590     if (info.Length() < 1 || !info[0]->IsFunction()) {
1591         return;
1592     }
1593 
1594     auto contentDidScrollHandler = AceType::MakeRefPtr<JsSwiperFunction>(JSRef<JSFunc>::Cast(info[0]));
1595     auto onContentDidScroll = [execCtx = info.GetExecutionContext(),
1596                                 func = std::move(contentDidScrollHandler)](
1597                                 int32_t selectedIndex, int32_t index, float position, float mainAxisLength) {
1598         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1599         ACE_SCORING_EVENT("Swiper.onContentDidScroll");
1600         func->Execute(selectedIndex, index, position, mainAxisLength);
1601     };
1602     SwiperModel::GetInstance()->SetOnContentDidScroll(std::move(onContentDidScroll));
1603 }
1604 
SetOnContentWillScroll(const JSCallbackInfo & info)1605 void JSSwiper::SetOnContentWillScroll(const JSCallbackInfo& info)
1606 {
1607     if (info.Length() < 1) {
1608         return;
1609     }
1610 
1611     if (info[0]->IsUndefined() || info[0]->IsNull()) {
1612         SwiperModel::GetInstance()->SetOnContentWillScroll(nullptr);
1613         return;
1614     }
1615 
1616     if (!info[0]->IsFunction()) {
1617         return;
1618     }
1619 
1620     auto handler = AceType::MakeRefPtr<JsSwiperFunction>(JSRef<JSFunc>::Cast(info[0]));
1621     auto callback = [execCtx = info.GetExecutionContext(), func = std::move(handler)](
1622                         const SwiperContentWillScrollResult& result) -> bool {
1623         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, true);
1624         ACE_SCORING_EVENT("Swiper.onContentWillScroll");
1625         auto ret = func->Execute(result);
1626         if (!ret->IsBoolean()) {
1627             return true;
1628         }
1629         return ret->ToBoolean();
1630     };
1631     SwiperModel::GetInstance()->SetOnContentWillScroll(std::move(callback));
1632 }
1633 
SetPageFlipMode(const JSCallbackInfo & info)1634 void JSSwiper::SetPageFlipMode(const JSCallbackInfo& info)
1635 {
1636     // default value
1637     int32_t value = 0;
1638     if (info.Length() < 1 || !info[0]->IsNumber()) {
1639         SwiperModel::GetInstance()->SetPageFlipMode(value);
1640         return;
1641     }
1642     JSViewAbstract::ParseJsInt32(info[0], value);
1643     SwiperModel::GetInstance()->SetPageFlipMode(value);
1644 }
1645 
GetAutoPlayOptionsInfo(const JSRef<JSObject> & obj,SwiperAutoPlayOptions & swiperAutoPlayOptions)1646 void JSSwiper::GetAutoPlayOptionsInfo(const JSRef<JSObject>& obj, SwiperAutoPlayOptions& swiperAutoPlayOptions)
1647 {
1648     auto stopWhenTouched = obj->GetProperty("stopWhenTouched");
1649     if (stopWhenTouched->IsBoolean()) {
1650         swiperAutoPlayOptions.stopWhenTouched = stopWhenTouched->ToBoolean();
1651     }
1652 }
1653 
SetOnSelected(const JSCallbackInfo & info)1654 void JSSwiper::SetOnSelected(const JSCallbackInfo& info)
1655 {
1656     if (!info[0]->IsFunction()) {
1657         return;
1658     }
1659     auto selectedHandler = AceType::MakeRefPtr<JsEventFunction<SwiperChangeEvent, 1>>(
1660         JSRef<JSFunc>::Cast(info[0]), SwiperChangeEventToJSValue);
1661     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1662     auto onSelected = [executionContext = info.GetExecutionContext(), func = std::move(selectedHandler),
1663                           node = targetNode](const BaseEventInfo* info) {
1664         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
1665         const auto* swiperInfo = TypeInfoHelper::DynamicCast<SwiperChangeEvent>(info);
1666         if (!swiperInfo) {
1667             TAG_LOGW(AceLogTag::ACE_SWIPER, "Swiper onSelected callback execute failed.");
1668             return;
1669         }
1670         ACE_SCORING_EVENT("Swiper.onSelected");
1671         ACE_SCOPED_TRACE("Swiper.onSelected index %d", swiperInfo->GetIndex());
1672         PipelineContext::SetCallBackNode(node);
1673         func->Execute(*swiperInfo);
1674     };
1675     SwiperModel::GetInstance()->SetOnSelected(std::move(onSelected));
1676 }
1677 } // namespace OHOS::Ace::Framework
1678