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