1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "bridge/declarative_frontend/jsview/js_view_context.h"
17
18 #include <algorithm>
19 #include <functional>
20 #include <memory>
21 #include <optional>
22 #include <sstream>
23
24 #include "base/log/ace_trace.h"
25 #include "base/log/jank_frame_report.h"
26 #include "base/utils/system_properties.h"
27 #include "base/utils/utils.h"
28 #include "bridge/common/utils/engine_helper.h"
29 #include "bridge/common/utils/utils.h"
30 #include "bridge/declarative_frontend/engine/functions/js_animation_on_finish_function.h"
31 #include "bridge/declarative_frontend/engine/js_converter.h"
32 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
33 #include "bridge/declarative_frontend/jsview/js_tabs_feature.h"
34 #include "bridge/declarative_frontend/jsview/models/view_context_model_impl.h"
35 #include "core/animation/animation_pub.h"
36 #include "core/common/ace_engine.h"
37 #include "core/common/recorder/event_recorder.h"
38 #include "core/components/common/properties/animation_option.h"
39 #include "core/components_ng/base/view_stack_model.h"
40 #include "core/components_ng/base/view_stack_processor.h"
41 #include "core/components_ng/pattern/view_context/view_context_model_ng.h"
42 #include "core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.h"
43 #include "bridge/declarative_frontend/jsview/js_search.h"
44 #include "bridge/declarative_frontend/jsview/js_textfield.h"
45
46 #ifdef USE_ARK_ENGINE
47 #include "bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.h"
48 #endif
49
50 namespace OHOS::Ace {
51
52 std::unique_ptr<ViewContextModel> ViewContextModel::instance_ = nullptr;
53 std::mutex ViewContextModel::mutex_;
54
GetInstance()55 ViewContextModel* ViewContextModel::GetInstance()
56 {
57 if (!instance_) {
58 std::lock_guard<std::mutex> lock(mutex_);
59 if (!instance_) {
60 #ifdef NG_BUILD
61 instance_.reset(new NG::ViewContextModelNG());
62 #else
63 if (Container::IsCurrentUseNewPipeline()) {
64 instance_.reset(new NG::ViewContextModelNG());
65 } else {
66 instance_.reset(new Framework::ViewContextModelImpl());
67 }
68 #endif
69 }
70 }
71 return instance_.get();
72 }
73
74 } // namespace OHOS::Ace
75
76 namespace OHOS::Ace::Framework {
77 namespace {
78
79 constexpr uint32_t DEFAULT_DURATION = 1000; // ms
80 constexpr int64_t MICROSEC_TO_MILLISEC = 1000;
81 constexpr int32_t INVALID_ID = -1;
82 constexpr int32_t INDEX_ONE = 1;
83 constexpr int32_t INDEX_TWO = 2;
84 constexpr int32_t LENGTH_ONE = 1;
85 constexpr int32_t LENGTH_TWO = 2;
86 constexpr int32_t LENGTH_THREE = 3;
87 constexpr int32_t MAX_FLUSH_COUNT = 2;
88 constexpr uint32_t DEBUG_DURATION = 150;
89
90 std::unordered_map<int32_t, std::string> UICONTEXT_ERROR_MAP = {
91 { ERROR_CODE_BIND_SHEET_CONTENT_ERROR, "The bindSheetContent is incorrect." },
92 { ERROR_CODE_BIND_SHEET_CONTENT_ALREADY_EXIST, "The bindSheetContent already exists." },
93 { ERROR_CODE_BIND_SHEET_CONTENT_NOT_FOUND, "The bindSheetContent cannot be found." },
94 { ERROR_CODE_TARGET_ID_NOT_EXIST, "The targetId does not exist." },
95 { ERROR_CODE_TARGET_NOT_ON_MAIN_TREE, "The node of targetId is not in the component tree." },
96 { ERROR_CODE_TARGET_NOT_PAGE_CHILD,
97 "The node of targetId is not a child of the page node or NavDestination node." },
98 { ERROR_CODE_INTERNAL_ERROR, "Internal error." },
99 { ERROR_CODE_PARAM_INVALID, "Parameter error. Possible causes: 1. Mandatory parameters are left unspecified;"
100 "2. Incorrect parameter types; 3. Parameter verification failed." },
101 { ERROR_CODE_DIALOG_CONTENT_ERROR, "The ComponentContent is incorrect. " },
102 { ERROR_CODE_DIALOG_CONTENT_ALREADY_EXIST, "The ComponentContent already exists. " },
103 { ERROR_CODE_DIALOG_CONTENT_NOT_FOUND, "The ComponentContent cannot be found. " },
104 { ERROR_CODE_TARGET_INFO_NOT_EXIST, "The targetId does not exist. " },
105 { ERROR_CODE_TARGET_NOT_ON_COMPONENT_TREE, "The node of targetId is not in the component tree. " }
106 };
107
PrintAnimationInfo(const AnimationOption & option,AnimationInterface interface,const std::optional<int32_t> & cnt)108 void PrintAnimationInfo(const AnimationOption& option, AnimationInterface interface, const std::optional<int32_t>& cnt)
109 {
110 auto animationInterfaceName = GetAnimationInterfaceName(interface);
111 CHECK_NULL_VOID(animationInterfaceName);
112 if (option.GetIteration() == ANIMATION_REPEAT_INFINITE) {
113 if (interface == AnimationInterface::KEYFRAME_ANIMATE_TO) {
114 TAG_LOGI(AceLogTag::ACE_ANIMATION,
115 "keyframeAnimateTo iteration is infinite, remember to stop it. total duration:%{public}d",
116 option.GetDuration());
117 } else {
118 TAG_LOGI(AceLogTag::ACE_ANIMATION,
119 "%{public}s iteration is infinite. duration:%{public}d, curve:%{public}s",
120 animationInterfaceName, option.GetDuration(), option.GetCurve()->ToString().c_str());
121 }
122 return;
123 }
124 if (cnt) {
125 TAG_LOGI(AceLogTag::ACE_ANIMATION, "%{public}s starts, [%{public}s], finish cnt:%{public}d",
126 animationInterfaceName, option.ToString().c_str(), cnt.value());
127 }
128 }
129
130 // check whether this container needs to perform animateTo
CheckContainer(const RefPtr<Container> & container)131 bool CheckContainer(const RefPtr<Container>& container)
132 {
133 auto context = container->GetPipelineContext();
134 if (!context) {
135 return false;
136 }
137 if (!container->GetSettings().usingSharedRuntime) {
138 return false;
139 }
140 if (!container->IsFRSCardContainer() && !container->WindowIsShow()) {
141 return false;
142 }
143 auto executor = container->GetTaskExecutor();
144 CHECK_NULL_RETURN(executor, false);
145 return executor->WillRunOnCurrentThread(TaskExecutor::TaskType::UI);
146 }
147
GetAnyContextIsLayouting(const RefPtr<PipelineBase> & currentPipeline)148 bool GetAnyContextIsLayouting(const RefPtr<PipelineBase>& currentPipeline)
149 {
150 if (currentPipeline->IsLayouting()) {
151 return true;
152 }
153 bool isLayouting = false;
154 AceEngine::Get().NotifyContainers([&isLayouting](const RefPtr<Container>& container) {
155 if (isLayouting) {
156 // One container is already in layouting
157 return;
158 }
159 if (!CheckContainer(container)) {
160 return;
161 }
162 auto context = container->GetPipelineContext();
163 isLayouting |= context->IsLayouting();
164 });
165 return isLayouting;
166 }
167
AnimateToForStageMode(const RefPtr<PipelineBase> & pipelineContext,const AnimationOption & option,JSRef<JSFunc> jsAnimateToFunc,int32_t triggerId,const std::optional<int32_t> & count)168 void AnimateToForStageMode(const RefPtr<PipelineBase>& pipelineContext, const AnimationOption& option,
169 JSRef<JSFunc> jsAnimateToFunc, int32_t triggerId, const std::optional<int32_t>& count)
170 {
171 pipelineContext->StartImplicitAnimation(option, option.GetCurve(), option.GetOnFinishEvent(), count);
172 auto previousOption = pipelineContext->GetSyncAnimationOption();
173 pipelineContext->SetSyncAnimationOption(option);
174 // Execute the function.
175 jsAnimateToFunc->Call(jsAnimateToFunc);
176 pipelineContext->FlushOnceVsyncTask();
177 AceEngine::Get().NotifyContainersOrderly([triggerId,
178 multiInstanceEnabled = SystemProperties::GetMultiInstanceEnabled()](const RefPtr<Container>& container) {
179 if (!CheckContainer(container)) {
180 return;
181 }
182 auto context = container->GetPipelineContext();
183 ContainerScope scope(container->GetInstanceId());
184 context->FlushBuild();
185 if (context->GetInstanceId() == triggerId) {
186 return;
187 }
188 context->PrepareCloseImplicitAnimation();
189 if (multiInstanceEnabled) {
190 AnimationUtils::CloseImplicitAnimation(context);
191 }
192 });
193 pipelineContext->CloseImplicitAnimation();
194 pipelineContext->SetSyncAnimationOption(previousOption);
195 }
196
FlushDirtyNodesWhenExist(const RefPtr<PipelineBase> & pipelineContext,const AnimationOption & option,const std::optional<int32_t> & count,AnimationInterface interface)197 void FlushDirtyNodesWhenExist(const RefPtr<PipelineBase>& pipelineContext,
198 const AnimationOption& option, const std::optional<int32_t>& count, AnimationInterface interface)
199 {
200 auto animationInterfaceName = GetAnimationInterfaceName(interface);
201 CHECK_NULL_VOID(animationInterfaceName);
202 int32_t flushCount = 0;
203 bool isDirtyNodesEmpty = pipelineContext->IsDirtyNodesEmpty();
204 bool isDirtyLayoutNodesEmpty = pipelineContext->IsDirtyLayoutNodesEmpty();
205 while (!isDirtyNodesEmpty || (!isDirtyLayoutNodesEmpty && !pipelineContext->IsLayouting())) {
206 if (flushCount >= MAX_FLUSH_COUNT || option.GetIteration() != ANIMATION_REPEAT_INFINITE) {
207 TAG_LOGD(AceLogTag::ACE_ANIMATION, "%{public}s, option:%{public}s, finish cnt:%{public}d,"
208 "dirtyNodes is empty:%{public}d, dirtyLayoutNodes is empty:%{public}d",
209 animationInterfaceName, option.ToString().c_str(), count.value_or(-1),
210 isDirtyNodesEmpty, isDirtyLayoutNodesEmpty);
211 break;
212 }
213 if (!isDirtyNodesEmpty) {
214 pipelineContext->FlushBuild();
215 isDirtyLayoutNodesEmpty = pipelineContext->IsDirtyLayoutNodesEmpty();
216 }
217 if (!isDirtyLayoutNodesEmpty && !pipelineContext->IsLayouting()) {
218 pipelineContext->FlushUITasks(true);
219 }
220 isDirtyNodesEmpty = pipelineContext->IsDirtyNodesEmpty();
221 isDirtyLayoutNodesEmpty = pipelineContext->IsDirtyLayoutNodesEmpty();
222 flushCount++;
223 }
224 }
225
StartAnimationForStageMode(const RefPtr<PipelineBase> & pipelineContext,const AnimationOption & option,JSRef<JSFunc> jsAnimateToFunc,const std::optional<int32_t> & count,bool immediately)226 void StartAnimationForStageMode(const RefPtr<PipelineBase>& pipelineContext, const AnimationOption& option,
227 JSRef<JSFunc> jsAnimateToFunc, const std::optional<int32_t>& count, bool immediately)
228 {
229 auto triggerId = pipelineContext->GetInstanceId();
230 ACE_SCOPED_TRACE("%s, instanceId:%d, finish cnt:%d", option.ToString().c_str(), triggerId, count.value_or(-1));
231 PrintAnimationInfo(
232 option, immediately ? AnimationInterface::ANIMATE_TO_IMMEDIATELY : AnimationInterface::ANIMATE_TO, count);
233 if (!ViewStackModel::GetInstance()->IsEmptyStack()) {
234 TAG_LOGW(AceLogTag::ACE_ANIMATION,
235 "when call animateTo, node stack is not empty, not suitable for animateTo."
236 "param is [option:%{public}s]", option.ToString().c_str());
237 }
238 NG::ScopedViewStackProcessor scopedProcessor;
239 AceEngine::Get().NotifyContainersOrderly([triggerId, &option,
240 multiInstanceEnabled = SystemProperties::GetMultiInstanceEnabled()](const RefPtr<Container>& container) {
241 if (!CheckContainer(container)) {
242 return;
243 }
244 auto context = container->GetPipelineContext();
245 ContainerScope scope(container->GetInstanceId());
246 context->FlushBuild();
247 if (context->GetInstanceId() == triggerId) {
248 return;
249 }
250 context->PrepareOpenImplicitAnimation();
251 if (multiInstanceEnabled) {
252 AnimationUtils::OpenImplicitAnimation(option, option.GetCurve(), nullptr, context);
253 }
254 });
255 pipelineContext->PrepareOpenImplicitAnimation();
256 FlushDirtyNodesWhenExist(pipelineContext, option, count,
257 immediately ? AnimationInterface::ANIMATE_TO_IMMEDIATELY : AnimationInterface::ANIMATE_TO);
258 if (!pipelineContext->CatchInteractiveAnimations([pipelineContext, option, jsAnimateToFunc, triggerId, count]() {
259 AnimateToForStageMode(pipelineContext, option, jsAnimateToFunc, triggerId, count);
260 })) {
261 AnimateToForStageMode(pipelineContext, option, jsAnimateToFunc, triggerId, count);
262 }
263 pipelineContext->FlushAfterLayoutCallbackInImplicitAnimationTask();
264 if (immediately) {
265 pipelineContext->FlushModifier();
266 pipelineContext->FlushMessages();
267 JankFrameReport::GetInstance().RecordAnimateEnd();
268 } else {
269 pipelineContext->RequestFrame();
270 }
271 }
272
StartAnimateToForFaMode(const RefPtr<PipelineBase> & pipelineContext,AnimationOption & option,JSRef<JSFunc> jsAnimateToFunc,const std::optional<int32_t> & count,bool immediately)273 void StartAnimateToForFaMode(const RefPtr<PipelineBase>& pipelineContext, AnimationOption& option,
274 JSRef<JSFunc> jsAnimateToFunc, const std::optional<int32_t>& count, bool immediately)
275 {
276 ACE_SCOPED_TRACE("%s, instanceId:%d, finish cnt:%d", option.ToString().c_str(), pipelineContext->GetInstanceId(),
277 count.value_or(-1));
278 PrintAnimationInfo(
279 option, immediately ? AnimationInterface::ANIMATE_TO_IMMEDIATELY : AnimationInterface::ANIMATE_TO, count);
280 if (!ViewStackModel::GetInstance()->IsEmptyStack()) {
281 TAG_LOGW(AceLogTag::ACE_ANIMATION,
282 "when call animateTo, node stack is not empty, not suitable for animateTo. param is [duration:%{public}d, "
283 "curve:%{public}s, iteration:%{public}d]",
284 option.GetDuration(), option.GetCurve()->ToString().c_str(), option.GetIteration());
285 }
286 NG::ScopedViewStackProcessor scopedProcessor;
287 pipelineContext->FlushBuild();
288 pipelineContext->OpenImplicitAnimation(option, option.GetCurve(), option.GetOnFinishEvent());
289 auto previousOption = pipelineContext->GetSyncAnimationOption();
290 pipelineContext->SetSyncAnimationOption(option);
291 jsAnimateToFunc->Call(jsAnimateToFunc);
292 pipelineContext->FlushBuild();
293 pipelineContext->CloseImplicitAnimation();
294 pipelineContext->SetSyncAnimationOption(previousOption);
295 if (immediately) {
296 pipelineContext->FlushModifier();
297 pipelineContext->FlushMessages();
298 JankFrameReport::GetInstance().RecordAnimateEnd();
299 } else {
300 pipelineContext->RequestFrame();
301 }
302 }
303
GetFormAnimationTimeInterval(const RefPtr<PipelineBase> & pipelineContext)304 int64_t GetFormAnimationTimeInterval(const RefPtr<PipelineBase>& pipelineContext)
305 {
306 CHECK_NULL_RETURN(pipelineContext, 0);
307 return (GetMicroTickCount() - pipelineContext->GetFormAnimationStartTime()) / MICROSEC_TO_MILLISEC;
308 }
309
CheckIfSetFormAnimationDuration(const RefPtr<PipelineBase> & pipelineContext,const AnimationOption & option)310 bool CheckIfSetFormAnimationDuration(const RefPtr<PipelineBase>& pipelineContext, const AnimationOption& option)
311 {
312 CHECK_NULL_RETURN(pipelineContext, false);
313 return pipelineContext->IsFormAnimationFinishCallback() && pipelineContext->IsFormRenderExceptDynamicComponent() &&
314 option.GetDuration() > (DEFAULT_DURATION - GetFormAnimationTimeInterval(pipelineContext));
315 }
316
ParseCallBackFunction(const JSRef<JSObject> & curveObj)317 std::function<float(float)> ParseCallBackFunction(const JSRef<JSObject>& curveObj)
318 {
319 std::function<float(float)> customCallBack = nullptr;
320 JSRef<JSVal> onCallBack = curveObj->GetProperty("__curveCustomFunc");
321 if (onCallBack->IsFunction()) {
322 auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
323 RefPtr<JsFunction> jsFuncCallBack =
324 AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onCallBack));
325 customCallBack = [func = std::move(jsFuncCallBack), id = Container::CurrentIdSafely(), node = frameNode](
326 float time) -> float {
327 ContainerScope scope(id);
328 auto pipelineContext = PipelineContext::GetCurrentContextSafely();
329 CHECK_NULL_RETURN(pipelineContext, 1.0f);
330 pipelineContext->UpdateCurrentActiveNode(node);
331 JSRef<JSVal> params[1];
332 params[0] = JSRef<JSVal>::Make(ToJSValue(time));
333 auto result = func->ExecuteJS(1, params);
334 return result->IsNumber() ? result->ToNumber<float>() : 1.0f;
335 };
336 }
337 return customCallBack;
338 }
339
340 struct KeyframeParam {
341 int32_t duration = 0;
342 RefPtr<Curve> curve;
343 std::function<void()> animationClosure;
344 };
345
ParseKeyframeOverallParam(const JSExecutionContext & executionContext,const JSRef<JSObject> & obj,std::optional<int32_t> & count)346 AnimationOption ParseKeyframeOverallParam(const JSExecutionContext& executionContext,
347 const JSRef<JSObject>& obj, std::optional<int32_t>& count)
348 {
349 JSRef<JSVal> onFinish = obj->GetProperty("onFinish");
350 AnimationOption option;
351 if (onFinish->IsFunction()) {
352 count = GetAnimationFinishCount();
353 auto jsFunc = AceType::MakeRefPtr<JsAnimationOnFinishFunction>(JSRef<JSFunc>::Cast(onFinish));
354 std::function<void()> onFinishEvent = [execCtx = executionContext, func = std::move(jsFunc),
355 id = Container::CurrentIdSafely()]() mutable {
356 CHECK_NULL_VOID(func);
357 ContainerScope scope(id);
358 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
359 func->Execute(false);
360 func = nullptr;
361 };
362 option.SetOnFinishEvent(onFinishEvent);
363 }
364 auto delay = obj->GetPropertyValue<int32_t>("delay", 0);
365 auto iterations = obj->GetPropertyValue<int32_t>("iterations", 1);
366 JSRef<JSVal> rateRangeObjectArgs = obj->GetProperty("expectedFrameRateRange");
367 if (rateRangeObjectArgs->IsObject()) {
368 JSRef<JSObject> rateRangeObj = JSRef<JSObject>::Cast(rateRangeObjectArgs);
369 int32_t fRRmin = rateRangeObj->GetPropertyValue<int32_t>("min", -1);
370 int32_t fRRmax = rateRangeObj->GetPropertyValue<int32_t>("max", -1);
371 int32_t fRRExpected = rateRangeObj->GetPropertyValue<int32_t>("expected", -1);
372 TAG_LOGD(AceLogTag::ACE_ANIMATION, "[keyframe] SetExpectedFrameRateRange"
373 "{%{public}d, %{public}d, %{public}d}", fRRmin, fRRmax, fRRExpected);
374 RefPtr<FrameRateRange> frameRateRange = AceType::MakeRefPtr<FrameRateRange>(fRRmin, fRRmax, fRRExpected);
375 option.SetFrameRateRange(frameRateRange);
376 }
377 option.SetDelay(delay);
378 option.SetIteration(iterations);
379 return option;
380 }
381
ParseKeyframes(const JSExecutionContext & executionContext,const JSRef<JSArray> & arr)382 std::vector<KeyframeParam> ParseKeyframes(const JSExecutionContext& executionContext, const JSRef<JSArray>& arr)
383 {
384 std::vector<KeyframeParam> params;
385 for (size_t index = 0; index != arr->Length(); ++index) {
386 if (!arr->GetValueAt(index)->IsObject()) {
387 continue;
388 }
389 auto info = JSRef<JSObject>::Cast(arr->GetValueAt(index));
390 KeyframeParam param;
391
392 auto jsEventValue = info->GetProperty("event");
393 if (!jsEventValue->IsFunction()) {
394 continue;
395 }
396 param.duration = info->GetPropertyValue<int32_t>("duration", DEFAULT_DURATION);
397 if (param.duration < 0) {
398 param.duration = 0;
399 }
400 RefPtr<JsFunction> jsFunc =
401 AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(jsEventValue));
402 param.animationClosure = [execCtx = executionContext, func = std::move(jsFunc)]() {
403 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
404 func->Execute();
405 };
406 auto curveArgs = info->GetProperty("curve");
407 param.curve = JSViewContext::ParseCurve(curveArgs, true);
408 params.emplace_back(param);
409 }
410 return params;
411 }
412
CreateErrorValue(napi_env env,int32_t errCode,const std::string & errMsg="")413 napi_value CreateErrorValue(napi_env env, int32_t errCode, const std::string& errMsg = "")
414 {
415 napi_value code = nullptr;
416 std::string codeStr = std::to_string(errCode);
417 napi_create_string_utf8(env, codeStr.c_str(), codeStr.length(), &code);
418 napi_value msg = nullptr;
419 napi_create_string_utf8(env, errMsg.c_str(), errMsg.length(), &msg);
420 napi_value error = nullptr;
421 napi_create_error(env, code, msg, &error);
422 return error;
423 }
424
ParseContentNode(const JSCallbackInfo & info)425 RefPtr<NG::FrameNode> ParseContentNode(const JSCallbackInfo& info)
426 {
427 EcmaVM* vm = info.GetVm();
428 CHECK_NULL_RETURN(vm, nullptr);
429 auto jsTargetNode = info[0];
430 auto* targetNodePtr = jsTargetNode->GetLocalHandle()->ToNativePointer(vm)->Value();
431 CHECK_NULL_RETURN(targetNodePtr, nullptr);
432 NG::FrameNode* sheetContentNode = reinterpret_cast<NG::FrameNode*>(targetNodePtr);
433 CHECK_NULL_RETURN(sheetContentNode, nullptr);
434 return AceType::Claim(sheetContentNode);
435 }
436
ReturnPromise(const JSCallbackInfo & info,int32_t errCode)437 void ReturnPromise(const JSCallbackInfo& info, int32_t errCode)
438 {
439 auto engine = EngineHelper::GetCurrentEngine();
440 CHECK_NULL_VOID(engine);
441 NativeEngine* nativeEngine = engine->GetNativeEngine();
442 auto env = reinterpret_cast<napi_env>(nativeEngine);
443 napi_deferred deferred = nullptr;
444 napi_value promise = nullptr;
445 napi_create_promise(env, &deferred, &promise);
446
447 if (errCode != ERROR_CODE_NO_ERROR) {
448 napi_value result = CreateErrorValue(env, errCode, UICONTEXT_ERROR_MAP[errCode]);
449 napi_reject_deferred(env, deferred, result);
450 } else {
451 napi_value result = nullptr;
452 napi_get_undefined(env, &result);
453 napi_resolve_deferred(env, deferred, result);
454 }
455 CHECK_NULL_VOID(promise);
456 auto jsPromise = JsConverter::ConvertNapiValueToJsVal(promise);
457 if (!jsPromise->IsObject()) {
458 TAG_LOGE(AceLogTag::ACE_SHEET, "Return promise failed.");
459 return;
460 }
461 info.SetReturnValue(JSRef<JSObject>::Cast(jsPromise));
462 }
463
StartKeyframeAnimation(const RefPtr<PipelineBase> & pipelineContext,AnimationOption & overallAnimationOption,std::vector<KeyframeParam> & keyframes,const std::optional<int32_t> & count)464 void StartKeyframeAnimation(const RefPtr<PipelineBase>& pipelineContext, AnimationOption& overallAnimationOption,
465 std::vector<KeyframeParam>& keyframes, const std::optional<int32_t>& count)
466 {
467 // flush build and flush ui tasks before open animation closure.
468 pipelineContext->FlushBuild();
469 if (!pipelineContext->IsLayouting()) {
470 pipelineContext->FlushUITasks(true);
471 }
472
473 // flush build when exist dirty nodes, flush ui tasks when exist dirty layout nodes.
474 FlushDirtyNodesWhenExist(pipelineContext,
475 overallAnimationOption, count, AnimationInterface::KEYFRAME_ANIMATE_TO);
476
477 // start KeyframeAnimation.
478 pipelineContext->StartImplicitAnimation(
479 overallAnimationOption, overallAnimationOption.GetCurve(), overallAnimationOption.GetOnFinishEvent(), count);
480 for (auto& keyframe : keyframes) {
481 if (!keyframe.animationClosure) {
482 continue;
483 }
484 AceTraceBeginWithArgs("keyframe duration%d", keyframe.duration);
485 AnimationUtils::AddDurationKeyFrame(keyframe.duration, keyframe.curve, [&keyframe, &pipelineContext]() {
486 keyframe.animationClosure();
487 pipelineContext->FlushBuild();
488 if (!pipelineContext->IsLayouting()) {
489 pipelineContext->FlushUITasks(true);
490 } else {
491 TAG_LOGI(AceLogTag::ACE_ANIMATION, "isLayouting, maybe some layout keyframe animation not generated");
492 }
493 });
494 AceTraceEnd();
495 }
496
497 // close KeyframeAnimation.
498 AnimationUtils::CloseImplicitAnimation();
499 }
500 } // namespace
501
ParseCurve(const JSRef<JSVal> & curveArgs,bool exceptSpring)502 RefPtr<Curve> JSViewContext::ParseCurve(const JSRef<JSVal>& curveArgs, bool exceptSpring)
503 {
504 RefPtr<Curve> curve;
505 if (curveArgs->IsString()) {
506 auto curveString = curveArgs->ToString();
507 if (exceptSpring) {
508 curve = CreateCurveExceptSpring(curveString);
509 } else {
510 curve = CreateCurve(curveString);
511 }
512 } else if (curveArgs->IsObject()) {
513 JSRef<JSObject> curveObject = JSRef<JSObject>::Cast(curveArgs);
514 JSRef<JSVal> curveString = curveObject->GetProperty("__curveString");
515 if (!curveString->IsString()) {
516 return Curves::EASE_IN_OUT;
517 }
518 auto aniTimFunc = curveString->ToString();
519 std::string customFuncName(DOM_ANIMATION_TIMING_FUNCTION_CUSTOM);
520 if (aniTimFunc == customFuncName) {
521 auto customCurveFunc = ParseCallBackFunction(curveObject);
522 curve = CreateCurve(customCurveFunc);
523 } else if (exceptSpring) {
524 curve = CreateCurveExceptSpring(aniTimFunc);
525 } else {
526 curve = CreateCurve(aniTimFunc);
527 }
528 } else {
529 curve = Curves::EASE_IN_OUT;
530 }
531 return curve;
532 }
533
CreateAnimation(const JSRef<JSObject> & animationArgs,bool isForm)534 const AnimationOption JSViewContext::CreateAnimation(const JSRef<JSObject>& animationArgs, bool isForm)
535 {
536 AnimationOption option;
537 // If the attribute does not exist, the default value is used.
538 auto duration = animationArgs->GetPropertyValue<int32_t>("duration", DEFAULT_DURATION);
539 auto delay = animationArgs->GetPropertyValue<int32_t>("delay", 0);
540 auto iterations = animationArgs->GetPropertyValue<int32_t>("iterations", 1);
541 auto tempo = animationArgs->GetPropertyValue<double>("tempo", 1.0);
542 if (SystemProperties::GetRosenBackendEnabled() && NearZero(tempo)) {
543 // set duration to 0 to disable animation.
544 duration = 0;
545 }
546 auto direction = StringToAnimationDirection(animationArgs->GetPropertyValue<std::string>("playMode", "normal"));
547 auto finishCallbackType = static_cast<FinishCallbackType>(
548 animationArgs->GetPropertyValue<int32_t>("finishCallbackType", 0));
549 auto curve = ParseCurve(animationArgs->GetProperty("curve"));
550
551 // limit animation for ArkTS Form
552 if (isForm) {
553 if (duration > static_cast<int32_t>(DEFAULT_DURATION)) {
554 duration = static_cast<int32_t>(DEFAULT_DURATION);
555 }
556 if (delay != 0) {
557 delay = 0;
558 }
559 if (SystemProperties::IsFormAnimationLimited() && iterations != 1) {
560 iterations = 1;
561 }
562 if (!NearEqual(tempo, 1.0)) {
563 tempo = 1.0;
564 }
565 }
566
567 int32_t fRRmin = 0;
568 int32_t fRRmax = 0;
569 int32_t fRRExpected = 0;
570 JSRef<JSVal> rateRangeObjectArgs = animationArgs->GetProperty("expectedFrameRateRange");
571 if (rateRangeObjectArgs->IsObject()) {
572 JSRef<JSObject> rateRangeObj = JSRef<JSObject>::Cast(rateRangeObjectArgs);
573 fRRmin = rateRangeObj->GetPropertyValue<int32_t>("min", -1);
574 fRRmax = rateRangeObj->GetPropertyValue<int32_t>("max", -1);
575 fRRExpected = rateRangeObj->GetPropertyValue<int32_t>("expected", -1);
576 TAG_LOGD(AceLogTag::ACE_ANIMATION, "[animation/animateTo] SetExpectedFrameRateRange"
577 "{%{public}d, %{public}d, %{public}d}", fRRmin, fRRmax, fRRExpected);
578 }
579 RefPtr<FrameRateRange> frameRateRange = AceType::MakeRefPtr<FrameRateRange>(fRRmin, fRRmax, fRRExpected);
580
581 option.SetDuration(duration);
582 option.SetDelay(delay);
583 option.SetIteration(iterations);
584 option.SetTempo(tempo);
585 option.SetAnimationDirection(direction);
586 option.SetCurve(curve);
587 option.SetFinishCallbackType(finishCallbackType);
588 option.SetFrameRateRange(frameRateRange);
589 return option;
590 }
591
JSAnimation(const JSCallbackInfo & info)592 void JSViewContext::JSAnimation(const JSCallbackInfo& info)
593 {
594 ACE_FUNCTION_TRACE();
595 auto scopedDelegate = EngineHelper::GetCurrentDelegateSafely();
596 if (!scopedDelegate) {
597 // this case usually means there is no foreground container, need to figure out the reason.
598 return;
599 }
600 if (ViewStackModel::GetInstance()->CheckTopNodeFirstBuilding()) {
601 // the node sets attribute value for the first time. No animation is generated.
602 return;
603 }
604 AnimationOption option = AnimationOption();
605 auto container = Container::CurrentSafely();
606 CHECK_NULL_VOID(container);
607 auto pipelineContextBase = container->GetPipelineContext();
608 CHECK_NULL_VOID(pipelineContextBase);
609 if (pipelineContextBase->IsFormAnimationFinishCallback() &&
610 pipelineContextBase->IsFormRenderExceptDynamicComponent() &&
611 GetFormAnimationTimeInterval(pipelineContextBase) > DEFAULT_DURATION) {
612 TAG_LOGW(
613 AceLogTag::ACE_FORM, "[Form animation] Form finish callback triggered animation cannot exceed 1000ms.");
614 return;
615 }
616 if (info[0]->IsNull() || !info[0]->IsObject()) {
617 ViewContextModel::GetInstance()->closeAnimation(option, true);
618 return;
619 }
620 JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
621 JSRef<JSVal> onFinish = obj->GetProperty("onFinish");
622 std::function<void()> onFinishEvent;
623 if (onFinish->IsFunction()) {
624 auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
625 RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onFinish));
626 onFinishEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
627 id = Container::CurrentIdSafely(), node = frameNode]() mutable {
628 CHECK_NULL_VOID(func);
629 ContainerScope scope(id);
630 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
631 auto pipelineContext = PipelineContext::GetCurrentContextSafely();
632 CHECK_NULL_VOID(pipelineContext);
633 pipelineContext->UpdateCurrentActiveNode(node);
634 func->Execute();
635 func = nullptr;
636 };
637 }
638
639 option = CreateAnimation(obj, pipelineContextBase->IsFormRenderExceptDynamicComponent());
640 if (pipelineContextBase->IsFormAnimationFinishCallback() &&
641 pipelineContextBase->IsFormRenderExceptDynamicComponent() &&
642 option.GetDuration() > (DEFAULT_DURATION - GetFormAnimationTimeInterval(pipelineContextBase))) {
643 option.SetDuration(DEFAULT_DURATION - GetFormAnimationTimeInterval(pipelineContextBase));
644 TAG_LOGW(AceLogTag::ACE_FORM, "[Form animation] Form animation SetDuration: %{public}lld ms",
645 static_cast<long long>(DEFAULT_DURATION - GetFormAnimationTimeInterval(pipelineContextBase)));
646 }
647
648 option.SetOnFinishEvent(onFinishEvent);
649 if (SystemProperties::GetRosenBackendEnabled()) {
650 option.SetAllowRunningAsynchronously(true);
651 }
652 PrintAnimationInfo(option, AnimationInterface::ANIMATION, std::nullopt);
653 AceScopedTrace paramTrace("duration:%d, curve:%s, iteration:%d", option.GetDuration(),
654 option.GetCurve()->ToString().c_str(), option.GetIteration());
655 option.SetAnimationInterface(AnimationInterface::ANIMATION);
656 ViewContextModel::GetInstance()->openAnimation(option);
657 JankFrameReport::GetInstance().ReportJSAnimation();
658 }
659
JSAnimateTo(const JSCallbackInfo & info)660 void JSViewContext::JSAnimateTo(const JSCallbackInfo& info)
661 {
662 ACE_FUNCTION_TRACE();
663 AnimateToInner(info, false);
664 }
665
JSAnimateToImmediately(const JSCallbackInfo & info)666 void JSViewContext::JSAnimateToImmediately(const JSCallbackInfo& info)
667 {
668 ACE_FUNCTION_TRACE();
669 AnimateToInner(info, true);
670 }
671
RecordAnimationFinished(int32_t count)672 void RecordAnimationFinished(int32_t count)
673 {
674 if (Recorder::EventRecorder::Get().IsRecordEnable(Recorder::EventCategory::CATEGORY_ANIMATION)) {
675 Recorder::EventParamsBuilder builder;
676 builder.SetEventCategory(Recorder::EventCategory::CATEGORY_ANIMATION)
677 .SetEventType(Recorder::EventType::ANIMATION_FINISHED)
678 .SetExtra(Recorder::KEY_COUNT, std::to_string(count));
679 Recorder::EventRecorder::Get().OnEvent(std::move(builder));
680 }
681 }
682
AnimateToInner(const JSCallbackInfo & info,bool immediately)683 void JSViewContext::AnimateToInner(const JSCallbackInfo& info, bool immediately)
684 {
685 auto currentId = Container::CurrentIdSafelyWithCheck();
686 bool needCheck = false;
687 if (!Container::CheckRunOnThreadByThreadId(currentId, false)) {
688 // fix DynamicComponent get wrong container when calling the animateTo function.
689 auto localContainerId = ContainerScope::CurrentLocalId();
690 TAG_LOGI(AceLogTag::ACE_ANIMATION,
691 "AnimateToInner not run on running thread, currentId: %{public}d, localId: %{public}d",
692 currentId, localContainerId);
693 if (localContainerId > 0 && Container::CheckRunOnThreadByThreadId(localContainerId, false)) {
694 currentId = localContainerId;
695 } else {
696 needCheck = true;
697 }
698 }
699 ContainerScope scope(currentId);
700 auto scopedDelegate = EngineHelper::GetCurrentDelegateSafely();
701 if (!scopedDelegate) {
702 // this case usually means there is no foreground container, need to figure out the reason.
703 const char* funcName = immediately ? "animateToImmediately" : "animateTo";
704 TAG_LOGW(AceLogTag::ACE_ANIMATION,
705 "can not find current context ,%{public}s faild, please use uiContext.%{public}s to specify the context",
706 funcName, funcName);
707 return;
708 }
709 if (info.Length() < 2) {
710 return;
711 }
712 if (!info[0]->IsObject()) {
713 return;
714 }
715 // 2nd argument should be a closure passed to the animateTo function.
716 if (!info[1]->IsFunction()) {
717 return;
718 }
719
720 auto container = Container::CurrentSafely();
721 CHECK_NULL_VOID(container);
722 if (needCheck && !Container::CheckRunOnThreadByThreadId(container->GetInstanceId(), false)) {
723 const char* funcName = immediately ? "animateToImmediately" : "animateTo";
724 TAG_LOGW(AceLogTag::ACE_ANIMATION,
725 "the context found cannot run on current thread, %{public}s failed, "
726 "please use uiContext.%{public}s to specify the context",
727 funcName, funcName);
728 return;
729 }
730 auto pipelineContext = container->GetPipelineContext();
731 CHECK_NULL_VOID(pipelineContext);
732 if (pipelineContext->IsFormAnimationFinishCallback() && pipelineContext->IsFormRenderExceptDynamicComponent() &&
733 GetFormAnimationTimeInterval(pipelineContext) > DEFAULT_DURATION) {
734 TAG_LOGW(
735 AceLogTag::ACE_FORM, "[Form animation] Form finish callback triggered animation cannot exceed 1000ms.");
736 return;
737 }
738
739 JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
740 AnimationOption option = CreateAnimation(obj, pipelineContext->IsFormRenderExceptDynamicComponent());
741 auto iterations = option.GetIteration();
742 JSRef<JSVal> onFinish = obj->GetProperty("onFinish");
743 std::function<void()> onFinishEvent;
744 std::optional<int32_t> count;
745 auto traceStreamPtr = std::make_shared<std::stringstream>();
746 RefPtr<Curve> debugCurve = Curves::FAST_OUT_LINEAR_IN;
747 auto isDebugAnim = option.GetDuration() == DEBUG_DURATION && debugCurve->IsEqual(option.GetCurve());
748 if (onFinish->IsFunction()) {
749 count = GetAnimationFinishCount();
750 auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
751 auto jsFunc = AceType::MakeRefPtr<JsAnimationOnFinishFunction>(JSRef<JSFunc>::Cast(onFinish));
752 onFinishEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
753 id = Container::CurrentIdSafely(), traceStreamPtr, node = frameNode, count,
754 iterations, isDebugAnim]() mutable {
755 RecordAnimationFinished(iterations);
756 CHECK_NULL_VOID(func);
757 ContainerScope scope(id);
758 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
759 ACE_SCOPED_TRACE("onFinish[cnt:%d]", count.value());
760 auto pipelineContext = PipelineContext::GetCurrentContextSafely();
761 CHECK_NULL_VOID(pipelineContext);
762 pipelineContext->UpdateCurrentActiveNode(node);
763 TAG_LOGI(AceLogTag::ACE_ANIMATION, "animateTo finish, cnt:%{public}d", count.value());
764 func->Execute(isDebugAnim);
765 if (isDebugAnim) {
766 TAG_LOGI(AceLogTag::ACE_ANIMATION, "animateTo finish after ExecuteJS, cnt:%{public}d", count.value());
767 }
768 func = nullptr;
769 AceAsyncTraceEnd(0, traceStreamPtr->str().c_str(), true);
770 };
771 } else {
772 onFinishEvent = [traceStreamPtr, iterations]() {
773 RecordAnimationFinished(iterations);
774 AceAsyncTraceEnd(0, traceStreamPtr->str().c_str(), true);
775 };
776 }
777
778 option.SetOnFinishEvent(onFinishEvent);
779 option.SetAnimationInterface(
780 immediately ? AnimationInterface::ANIMATE_TO_IMMEDIATELY : AnimationInterface::ANIMATE_TO);
781 *traceStreamPtr << "AnimateTo, Options"
782 << " duration:" << option.GetDuration()
783 << ",iteration:" << option.GetIteration()
784 << ",delay:" << option.GetDelay()
785 << ",tempo:" << option.GetTempo()
786 << ",direction:" << (uint32_t) option.GetAnimationDirection()
787 << ",curve:" << (option.GetCurve() ? option.GetCurve()->ToString().c_str() : "");
788 AceAsyncTraceBegin(0, traceStreamPtr->str().c_str(), true);
789 if (CheckIfSetFormAnimationDuration(pipelineContext, option)) {
790 option.SetDuration(DEFAULT_DURATION - GetFormAnimationTimeInterval(pipelineContext));
791 TAG_LOGW(AceLogTag::ACE_FORM, "[Form animation] Form animation SetDuration: %{public}lld ms",
792 static_cast<long long>(DEFAULT_DURATION - GetFormAnimationTimeInterval(pipelineContext)));
793 }
794 if (SystemProperties::GetRosenBackendEnabled()) {
795 bool usingSharedRuntime = container->GetSettings().usingSharedRuntime;
796 if (usingSharedRuntime) {
797 if (GetAnyContextIsLayouting(pipelineContext)) {
798 TAG_LOGW(AceLogTag::ACE_ANIMATION,
799 "Pipeline layouting, post animateTo, dur:%{public}d, curve:%{public}s",
800 option.GetDuration(), option.GetCurve() ? option.GetCurve()->ToString().c_str() : "");
801 pipelineContext->GetTaskExecutor()->PostTask(
802 [id = Container::CurrentIdSafely(), option, func = JSRef<JSFunc>::Cast(info[1]), count,
803 immediately]() mutable {
804 ContainerScope scope(id);
805 auto container = Container::CurrentSafely();
806 CHECK_NULL_VOID(container);
807 auto pipelineContext = container->GetPipelineContext();
808 CHECK_NULL_VOID(pipelineContext);
809 StartAnimationForStageMode(pipelineContext, option, func, count, immediately);
810 },
811 TaskExecutor::TaskType::UI, "ArkUIAnimateToForStageMode", PriorityType::IMMEDIATE);
812 return;
813 }
814 StartAnimationForStageMode(pipelineContext, option, JSRef<JSFunc>::Cast(info[1]), count, immediately);
815 } else {
816 StartAnimateToForFaMode(pipelineContext, option, JSRef<JSFunc>::Cast(info[1]), count, immediately);
817 }
818 } else {
819 pipelineContext->FlushBuild();
820 pipelineContext->SaveExplicitAnimationOption(option);
821 // Execute the function.
822 JSRef<JSFunc> jsAnimateToFunc = JSRef<JSFunc>::Cast(info[1]);
823 jsAnimateToFunc->Call(info[1]);
824 pipelineContext->FlushBuild();
825 pipelineContext->CreateExplicitAnimator(onFinishEvent);
826 pipelineContext->ClearExplicitAnimationOption();
827 }
828 }
829
JSKeyframeAnimateTo(const JSCallbackInfo & info)830 void JSViewContext::JSKeyframeAnimateTo(const JSCallbackInfo& info)
831 {
832 ACE_FUNCTION_TRACE();
833 auto scopedDelegate = EngineHelper::GetCurrentDelegateSafely();
834 if (!scopedDelegate) {
835 // this case usually means there is no foreground container, need to figure out the reason.
836 return;
837 }
838 if (info.Length() < 2) {
839 return;
840 }
841 if (!info[0]->IsObject()) {
842 return;
843 }
844 if (!info[1]->IsArray()) {
845 return;
846 }
847 JSRef<JSArray> keyframeArr = JSRef<JSArray>::Cast(info[1]);
848 if (keyframeArr->Length() == 0) {
849 return;
850 }
851
852 auto container = Container::CurrentSafely();
853 CHECK_NULL_VOID(container);
854 if (!Container::CheckRunOnThreadByThreadId(container->GetInstanceId(), false)) {
855 TAG_LOGW(AceLogTag::ACE_ANIMATION, "the context found cannot run current thread, KeyframeAnimateTo "
856 "failed, please use correct ui context.");
857 return;
858 }
859 auto pipelineContext = container->GetPipelineContext();
860 CHECK_NULL_VOID(pipelineContext);
861 JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
862 std::optional<int32_t> count;
863 auto overallAnimationOption = ParseKeyframeOverallParam(info.GetExecutionContext(), obj, count);
864 auto keyframes = ParseKeyframes(info.GetExecutionContext(), keyframeArr);
865 int duration = 0;
866 for (auto& keyframe : keyframes) {
867 duration += keyframe.duration;
868 }
869 overallAnimationOption.SetDuration(duration);
870 // actual curve is in keyframe, this curve will not be effective
871 overallAnimationOption.SetCurve(Curves::EASE_IN_OUT);
872 AceScopedTrace trace("KeyframeAnimateTo iteration:%d, delay:%d",
873 overallAnimationOption.GetIteration(), overallAnimationOption.GetDelay());
874 PrintAnimationInfo(overallAnimationOption, AnimationInterface::KEYFRAME_ANIMATE_TO, count);
875 overallAnimationOption.SetAnimationInterface(AnimationInterface::KEYFRAME_ANIMATE_TO);
876 if (!ViewStackModel::GetInstance()->IsEmptyStack()) {
877 TAG_LOGW(AceLogTag::ACE_ANIMATION,
878 "when call keyframeAnimateTo, node stack is not empty, not suitable for keyframeAnimateTo."
879 "param is [duration:%{public}d, delay:%{public}d, iteration:%{public}d]",
880 overallAnimationOption.GetDuration(), overallAnimationOption.GetDelay(),
881 overallAnimationOption.GetIteration());
882 }
883 NG::ScopedViewStackProcessor scopedProcessor;
884 StartKeyframeAnimation(pipelineContext, overallAnimationOption, keyframes, count);
885 pipelineContext->FlushAfterLayoutCallbackInImplicitAnimationTask();
886 }
887
SetDynamicDimming(const JSCallbackInfo & info)888 void JSViewContext::SetDynamicDimming(const JSCallbackInfo& info)
889 {
890 EcmaVM* vm = info.GetVm();
891 CHECK_NULL_VOID(vm);
892 auto jsTargetNode = info[0];
893 auto jsDimming = info[1];
894 auto* targetNodePtr = jsTargetNode->GetLocalHandle()->ToNativePointer(vm)->Value();
895 auto* frameNode = reinterpret_cast<NG::FrameNode*>(targetNodePtr);
896 CHECK_NULL_VOID(frameNode);
897 if (!info[1]->IsNumber()) {
898 return;
899 }
900 float dimming = info[1]->ToNumber<float>();
901 RefPtr<Ace::NG::RenderContext> renderContext = frameNode->GetRenderContext();
902 renderContext->UpdateDynamicDimDegree(std::clamp(dimming, 0.0f, 1.0f));
903 }
904
JSOpenBindSheet(const JSCallbackInfo & info)905 void JSViewContext::JSOpenBindSheet(const JSCallbackInfo& info)
906 {
907 auto paramCnt = info.Length();
908 if (paramCnt < LENGTH_ONE) {
909 ReturnPromise(info, ERROR_CODE_PARAM_INVALID);
910 return;
911 }
912
913 auto sheetContentNode = ParseContentNode(info);
914 if (sheetContentNode == nullptr) {
915 ReturnPromise(info, ERROR_CODE_BIND_SHEET_CONTENT_ERROR);
916 return;
917 }
918
919 // parse SheetStyle and callbacks
920 NG::SheetStyle sheetStyle;
921 sheetStyle.sheetHeight.sheetMode = NG::SheetMode::LARGE;
922 sheetStyle.showDragBar = true;
923 sheetStyle.showInPage = false;
924 std::function<void()> onAppearCallback;
925 std::function<void()> onDisappearCallback;
926 std::function<void()> onWillAppearCallback;
927 std::function<void()> onWillDisappearCallback;
928 std::function<void()> shouldDismissFunc;
929 std::function<void(const int32_t)> onWillDismissCallback;
930 std::function<void(const float)> onHeightDidChangeCallback;
931 std::function<void(const float)> onDetentsDidChangeCallback;
932 std::function<void(const float)> onWidthDidChangeCallback;
933 std::function<void(const float)> onTypeDidChangeCallback;
934 std::function<void()> titleBuilderFunction;
935 std::function<void()> sheetSpringBackFunc;
936 if (paramCnt >= LENGTH_TWO && info[INDEX_ONE]->IsObject()) {
937 JSViewAbstract::ParseSheetCallback(info[INDEX_ONE], onAppearCallback, onDisappearCallback, shouldDismissFunc,
938 onWillDismissCallback, onWillAppearCallback, onWillDisappearCallback, onHeightDidChangeCallback,
939 onDetentsDidChangeCallback, onWidthDidChangeCallback, onTypeDidChangeCallback, sheetSpringBackFunc);
940 JSViewAbstract::ParseSheetStyle(info[INDEX_ONE], sheetStyle);
941 JSViewAbstract::ParseSheetTitle(info[INDEX_ONE], sheetStyle, titleBuilderFunction);
942 }
943
944 int32_t targetId = INVALID_ID;
945 if (paramCnt >= LENGTH_THREE) {
946 if (!info[INDEX_TWO]->IsNumber()) {
947 ReturnPromise(info, ERROR_CODE_PARAM_INVALID);
948 return;
949 }
950 targetId = info[INDEX_TWO]->ToNumber<int32_t>();
951 if (targetId < 0) {
952 ReturnPromise(info, ERROR_CODE_TARGET_ID_NOT_EXIST);
953 return;
954 }
955 }
956 TAG_LOGI(AceLogTag::ACE_SHEET, "paramCnt: %{public}d, contentId: %{public}d, targetId: %{public}d",
957 paramCnt, sheetContentNode->GetId(), targetId);
958 auto ret = ViewContextModel::GetInstance()->OpenBindSheet(sheetContentNode,
959 std::move(titleBuilderFunction), sheetStyle, std::move(onAppearCallback), std::move(onDisappearCallback),
960 std::move(shouldDismissFunc), std::move(onWillDismissCallback), std::move(onWillAppearCallback),
961 std::move(onWillDisappearCallback), std::move(onHeightDidChangeCallback),
962 std::move(onDetentsDidChangeCallback), std::move(onWidthDidChangeCallback),
963 std::move(onTypeDidChangeCallback), std::move(sheetSpringBackFunc), Container::CurrentId(), targetId);
964
965 ReturnPromise(info, ret);
966 return;
967 }
968
JSUpdateBindSheet(const JSCallbackInfo & info)969 void JSViewContext::JSUpdateBindSheet(const JSCallbackInfo& info)
970 {
971 auto paramCnt = info.Length();
972 if (paramCnt < LENGTH_TWO) {
973 ReturnPromise(info, ERROR_CODE_PARAM_INVALID);
974 return;
975 }
976 auto sheetContentNode = ParseContentNode(info);
977 if (sheetContentNode == nullptr) {
978 ReturnPromise(info, ERROR_CODE_BIND_SHEET_CONTENT_ERROR);
979 return;
980 }
981
982 bool isPartialUpdate = false;
983 if (paramCnt == LENGTH_THREE) {
984 if (!info[INDEX_TWO]->IsBoolean()) {
985 ReturnPromise(info, ERROR_CODE_PARAM_INVALID);
986 return;
987 }
988 isPartialUpdate = info[INDEX_TWO]->ToBoolean();
989 }
990
991 NG::SheetStyle sheetStyle;
992 std::function<void()> titleBuilderFunction;
993 if (paramCnt >= LENGTH_TWO && info[INDEX_ONE]->IsObject()) {
994 JSViewAbstract::ParseSheetStyle(info[INDEX_ONE], sheetStyle, isPartialUpdate);
995 JSViewAbstract::ParseSheetTitle(info[INDEX_ONE], sheetStyle, titleBuilderFunction);
996 } else {
997 sheetStyle.sheetHeight.sheetMode = NG::SheetMode::LARGE;
998 sheetStyle.showDragBar = true;
999 sheetStyle.showInPage = false;
1000 isPartialUpdate = false;
1001 }
1002 TAG_LOGI(AceLogTag::ACE_SHEET, "paramCnt: %{public}d, contentId: %{public}d, isPartialUpdate: %{public}d",
1003 paramCnt, sheetContentNode->GetId(), isPartialUpdate);
1004 auto ret = ViewContextModel::GetInstance()->UpdateBindSheet(
1005 sheetContentNode, sheetStyle, isPartialUpdate, Container::CurrentId());
1006 ReturnPromise(info, ret);
1007 return;
1008 }
1009
JSCloseBindSheet(const JSCallbackInfo & info)1010 void JSViewContext::JSCloseBindSheet(const JSCallbackInfo& info)
1011 {
1012 auto paramCnt = info.Length();
1013 if (paramCnt < LENGTH_ONE) {
1014 ReturnPromise(info, ERROR_CODE_PARAM_INVALID);
1015 return;
1016 }
1017
1018 auto sheetContentNode = ParseContentNode(info);
1019 if (sheetContentNode == nullptr) {
1020 ReturnPromise(info, ERROR_CODE_BIND_SHEET_CONTENT_ERROR);
1021 return;
1022 }
1023
1024 TAG_LOGI(AceLogTag::ACE_SHEET, "paramCnt: %{public}d, contentId: %{public}d", paramCnt, sheetContentNode->GetId());
1025 auto ret =
1026 ViewContextModel::GetInstance()->CloseBindSheet(sheetContentNode, Container::CurrentId());
1027 ReturnPromise(info, ret);
1028 return;
1029 }
1030
ParseTargetInfo(const JSRef<JSObject> & obj,int32_t & targetId)1031 int32_t ParseTargetInfo(const JSRef<JSObject>& obj, int32_t& targetId)
1032 {
1033 CHECK_EQUAL_RETURN(obj->IsEmpty(), true, ERROR_CODE_PARAM_INVALID);
1034 auto targetInfoID = obj->GetProperty("id");
1035 if (targetInfoID->IsNumber()) {
1036 targetId = targetInfoID->ToNumber<int32_t>();
1037 } else if (targetInfoID->IsString()) {
1038 std::string targetIdString = targetInfoID->ToString();
1039 auto targetInfoComponentId = obj->GetProperty("componentId");
1040 if (targetInfoComponentId->IsNumber()) {
1041 auto componentId = targetInfoComponentId->ToNumber<int32_t>();
1042 auto targetComponentIdNode =
1043 ElementRegister::GetInstance()->GetSpecificItemById<NG::FrameNode>(componentId);
1044 CHECK_NULL_RETURN(targetComponentIdNode, ERROR_CODE_TARGET_INFO_NOT_EXIST);
1045 if (targetComponentIdNode->GetInspectorId().value_or("") == targetIdString) {
1046 targetId = targetComponentIdNode->GetId();
1047 return ERROR_CODE_NO_ERROR;
1048 }
1049 auto targetNode = NG::FrameNode::FindChildByName(targetComponentIdNode, targetIdString);
1050 CHECK_NULL_RETURN(targetNode, ERROR_CODE_TARGET_INFO_NOT_EXIST);
1051 targetId = targetNode->GetId();
1052 } else {
1053 auto targetNode = ElementRegister::GetInstance()->GetAttachedFrameNodeById(targetIdString);
1054 CHECK_NULL_RETURN(targetNode, ERROR_CODE_TARGET_INFO_NOT_EXIST);
1055 targetId = targetNode->GetId();
1056 }
1057 }
1058 if (targetId < 0) {
1059 return ERROR_CODE_PARAM_INVALID;
1060 }
1061 return ERROR_CODE_NO_ERROR;
1062 }
1063
JSOpenPopup(const JSCallbackInfo & info)1064 void JSViewContext::JSOpenPopup(const JSCallbackInfo& info)
1065 {
1066 auto paramCnt = info.Length();
1067 if (paramCnt < LENGTH_TWO) {
1068 ReturnPromise(info, ERROR_CODE_PARAM_INVALID);
1069 return;
1070 }
1071 auto popupContentNode = ParseContentNode(info);
1072 if (popupContentNode == nullptr) {
1073 ReturnPromise(info, ERROR_CODE_DIALOG_CONTENT_ERROR);
1074 return;
1075 }
1076 auto popupParam = AceType::MakeRefPtr<PopupParam>();
1077 CHECK_NULL_VOID(popupParam);
1078 popupParam->SetIsShow(true);
1079 popupParam->SetUseCustomComponent(true);
1080 if (info[INDEX_ONE]->IsObject()) {
1081 auto popupObj = JSRef<JSObject>::Cast(info[INDEX_ONE]);
1082 int32_t targetId = INVALID_ID;
1083 auto result = ParseTargetInfo(popupObj, targetId);
1084 if (result == ERROR_CODE_NO_ERROR) {
1085 popupParam->SetTargetId(std::to_string(targetId));
1086 } else {
1087 ReturnPromise(info, result);
1088 return;
1089 }
1090 } else {
1091 ReturnPromise(info, ERROR_CODE_PARAM_INVALID);
1092 return;
1093 }
1094 if (paramCnt == LENGTH_THREE && info[INDEX_TWO]->IsObject()) {
1095 auto popupObj = JSRef<JSObject>::Cast(info[INDEX_TWO]);
1096 JSViewAbstract::ParseContentPopupCommonParam(info, popupObj, popupParam);
1097 } else {
1098 JSRef<JSObject> popupObj = JSRef<JSObject>::New();
1099 JSViewAbstract::ParseContentPopupCommonParam(info, popupObj, popupParam);
1100 }
1101 auto ret = JSViewAbstract::OpenPopup(popupParam, popupContentNode);
1102 if (ret == ERROR_CODE_INTERNAL_ERROR) {
1103 ret = ERROR_CODE_NO_ERROR;
1104 }
1105 ReturnPromise(info, ret);
1106 return;
1107 }
1108
UpdateParsePopupParam(const JSCallbackInfo & info,RefPtr<PopupParam> & popupParam,const RefPtr<NG::UINode> & customNode,bool isPartialUpdate)1109 bool UpdateParsePopupParam(const JSCallbackInfo& info, RefPtr<PopupParam>& popupParam,
1110 const RefPtr<NG::UINode>& customNode, bool isPartialUpdate)
1111 {
1112 if ((!popupParam) || (!customNode)) {
1113 return false;
1114 }
1115 auto paramCnt = info.Length();
1116 if (!(paramCnt >= LENGTH_TWO && info[INDEX_ONE]->IsObject())) {
1117 ReturnPromise(info, ERROR_CODE_PARAM_INVALID);
1118 return false;
1119 }
1120 auto param = AceType::MakeRefPtr<PopupParam>();
1121 CHECK_NULL_RETURN(param, false);
1122 auto result = JSViewAbstract::GetPopupParam(param, customNode);
1123 if (result == ERROR_CODE_NO_ERROR) {
1124 if (isPartialUpdate) {
1125 popupParam = param;
1126 } else {
1127 popupParam->SetTargetId(param->GetTargetId());
1128 }
1129 } else {
1130 if (result == ERROR_CODE_INTERNAL_ERROR) {
1131 result = ERROR_CODE_NO_ERROR;
1132 }
1133 ReturnPromise(info, result);
1134 return false;
1135 }
1136 auto isShowInSubWindow = param->IsShowInSubWindow();
1137 auto focusable = param->GetFocusable();
1138 popupParam->SetIsShow(true);
1139 popupParam->SetUseCustomComponent(true);
1140 popupParam->SetIsPartialUpdate(isPartialUpdate);
1141 auto popupObj = JSRef<JSObject>::Cast(info[INDEX_ONE]);
1142 JSViewAbstract::ParseContentPopupCommonParam(info, popupObj, popupParam);
1143 popupParam->SetShowInSubWindow(isShowInSubWindow);
1144 popupParam->SetFocusable(focusable);
1145 return true;
1146 }
1147
JSUpdatePopup(const JSCallbackInfo & info)1148 void JSViewContext::JSUpdatePopup(const JSCallbackInfo& info)
1149 {
1150 auto paramCnt = info.Length();
1151 if (paramCnt < LENGTH_TWO) {
1152 ReturnPromise(info, ERROR_CODE_PARAM_INVALID);
1153 return;
1154 }
1155 auto popupContentNode = ParseContentNode(info);
1156 if (popupContentNode == nullptr) {
1157 ReturnPromise(info, ERROR_CODE_DIALOG_CONTENT_ERROR);
1158 return;
1159 }
1160 auto popupParam = AceType::MakeRefPtr<PopupParam>();
1161 CHECK_NULL_VOID(popupParam);
1162 bool isPartialUpdate = false;
1163 if (paramCnt == LENGTH_THREE) {
1164 if (!info[INDEX_TWO]->IsBoolean()) {
1165 ReturnPromise(info, ERROR_CODE_PARAM_INVALID);
1166 return;
1167 }
1168 isPartialUpdate = info[INDEX_TWO]->ToBoolean();
1169 }
1170 auto result = UpdateParsePopupParam(info, popupParam, popupContentNode, isPartialUpdate);
1171 if (!result) {
1172 return;
1173 }
1174 auto ret = JSViewAbstract::UpdatePopup(popupParam, popupContentNode);
1175 if (ret == ERROR_CODE_INTERNAL_ERROR) {
1176 ret = ERROR_CODE_NO_ERROR;
1177 }
1178 ReturnPromise(info, ret);
1179 return;
1180 }
1181
JSClosePopup(const JSCallbackInfo & info)1182 void JSViewContext::JSClosePopup(const JSCallbackInfo& info)
1183 {
1184 auto paramCnt = info.Length();
1185 if (paramCnt < LENGTH_ONE) {
1186 ReturnPromise(info, ERROR_CODE_PARAM_INVALID);
1187 return;
1188 }
1189 auto popupContentNode = ParseContentNode(info);
1190 if (popupContentNode == nullptr) {
1191 ReturnPromise(info, ERROR_CODE_DIALOG_CONTENT_ERROR);
1192 return;
1193 }
1194 auto ret = JSViewAbstract::ClosePopup(popupContentNode);
1195 if (ret == ERROR_CODE_INTERNAL_ERROR) {
1196 ret = ERROR_CODE_NO_ERROR;
1197 }
1198 ReturnPromise(info, ret);
1199 return;
1200 }
1201
GetMenuParam(NG::MenuParam & menuParam,const RefPtr<NG::UINode> & node)1202 int32_t GetMenuParam(NG::MenuParam& menuParam, const RefPtr<NG::UINode>& node)
1203 {
1204 if (!node) {
1205 TAG_LOGE(AceLogTag::ACE_DIALOG, "Content of menu is null.");
1206 return ERROR_CODE_DIALOG_CONTENT_ERROR;
1207 }
1208 auto context = node->GetContextWithCheck();
1209 CHECK_NULL_RETURN(context, ERROR_CODE_INTERNAL_ERROR);
1210 auto overlayManager = context->GetOverlayManager();
1211 if (!overlayManager) {
1212 return ERROR_CODE_INTERNAL_ERROR;
1213 }
1214 auto menuNode = overlayManager->GetMenuNodeWithExistContent(node);
1215 if (!menuNode) {
1216 TAG_LOGE(AceLogTag::ACE_DIALOG, "GetMenuParam failed because cannot find menuNode.");
1217 return ERROR_CODE_DIALOG_CONTENT_NOT_FOUND;
1218 }
1219 auto wrapperPattern = AceType::DynamicCast<NG::MenuWrapperPattern>(menuNode->GetPattern());
1220 CHECK_NULL_RETURN(wrapperPattern, ERROR_CODE_INTERNAL_ERROR);
1221 auto menuProperties = wrapperPattern->GetMenuParam();
1222 menuParam = menuProperties;
1223 return ERROR_CODE_NO_ERROR;
1224 }
1225
JSOpenMenu(const JSCallbackInfo & info)1226 void JSViewContext::JSOpenMenu(const JSCallbackInfo& info)
1227 {
1228 auto paramCnt = info.Length();
1229 if (paramCnt < LENGTH_TWO) {
1230 ReturnPromise(info, ERROR_CODE_PARAM_INVALID);
1231 return;
1232 }
1233 auto menuContentNode = ParseContentNode(info);
1234 if (menuContentNode == nullptr) {
1235 ReturnPromise(info, ERROR_CODE_DIALOG_CONTENT_ERROR);
1236 return;
1237 }
1238 int32_t targetId = INVALID_ID;
1239 if (info[INDEX_ONE]->IsObject()) {
1240 auto menuObj = JSRef<JSObject>::Cast(info[INDEX_ONE]);
1241 auto result = ParseTargetInfo(menuObj, targetId);
1242 if (result != ERROR_CODE_NO_ERROR) {
1243 ReturnPromise(info, result);
1244 return;
1245 }
1246 } else {
1247 ReturnPromise(info, ERROR_CODE_PARAM_INVALID);
1248 return;
1249 }
1250 NG::MenuParam menuParam;
1251 JSRef<JSObject> menuObj;
1252 if (paramCnt == LENGTH_THREE && info[INDEX_TWO]->IsObject()) {
1253 menuObj = JSRef<JSObject>::Cast(info[INDEX_TWO]);
1254 }
1255 JSViewAbstract::ParseContentMenuCommonParam(info, menuObj, menuParam);
1256 auto ret = JSViewAbstract::OpenMenu(menuParam, menuContentNode, targetId);
1257 if (ret == ERROR_CODE_INTERNAL_ERROR) {
1258 ret = ERROR_CODE_NO_ERROR;
1259 }
1260 ReturnPromise(info, ret);
1261 return;
1262 }
1263
JSUpdateMenu(const JSCallbackInfo & info)1264 void JSViewContext::JSUpdateMenu(const JSCallbackInfo& info)
1265 {
1266 auto paramCnt = info.Length();
1267 if (paramCnt < LENGTH_TWO) {
1268 ReturnPromise(info, ERROR_CODE_PARAM_INVALID);
1269 return;
1270 }
1271 auto menuContentNode = ParseContentNode(info);
1272 if (menuContentNode == nullptr) {
1273 ReturnPromise(info, ERROR_CODE_DIALOG_CONTENT_ERROR);
1274 return;
1275 }
1276 bool isPartialUpdate = false;
1277 if (paramCnt == LENGTH_THREE) {
1278 if (!info[INDEX_TWO]->IsBoolean()) {
1279 ReturnPromise(info, ERROR_CODE_PARAM_INVALID);
1280 return;
1281 }
1282 isPartialUpdate = info[INDEX_TWO]->ToBoolean();
1283 }
1284 NG::MenuParam menuParam;
1285 if (paramCnt >= LENGTH_TWO && info[INDEX_ONE]->IsObject()) {
1286 NG::MenuParam menuParamOpen;
1287 //Get current param config
1288 auto result = GetMenuParam(menuParamOpen, menuContentNode);
1289 if (result != ERROR_CODE_NO_ERROR && result != ERROR_CODE_INTERNAL_ERROR) {
1290 ReturnPromise(info, result);
1291 return;
1292 }
1293 if (isPartialUpdate) {
1294 menuParam = menuParamOpen;
1295 }
1296 auto menuObj = JSRef<JSObject>::Cast(info[INDEX_ONE]);
1297 JSViewAbstract::ParseContentMenuCommonParam(info, menuObj, menuParam);
1298 //Updating these parameters is not supported
1299 menuParam.isShowInSubWindow = menuParamOpen.isShowInSubWindow;
1300 menuParam.previewMode = menuParamOpen.previewMode;
1301 } else {
1302 ReturnPromise(info, ERROR_CODE_PARAM_INVALID);
1303 return;
1304 }
1305 auto ret = JSViewAbstract::UpdateMenu(menuParam, menuContentNode);
1306 if (ret == ERROR_CODE_INTERNAL_ERROR) {
1307 ret = ERROR_CODE_NO_ERROR;
1308 }
1309 ReturnPromise(info, ret);
1310 return;
1311 }
1312
JSCloseMenu(const JSCallbackInfo & info)1313 void JSViewContext::JSCloseMenu(const JSCallbackInfo& info)
1314 {
1315 auto paramCnt = info.Length();
1316 if (paramCnt < LENGTH_ONE) {
1317 ReturnPromise(info, ERROR_CODE_PARAM_INVALID);
1318 return;
1319 }
1320 auto menuContentNode = ParseContentNode(info);
1321 if (menuContentNode == nullptr) {
1322 ReturnPromise(info, ERROR_CODE_DIALOG_CONTENT_ERROR);
1323 return;
1324 }
1325 auto ret = JSViewAbstract::CloseMenu(menuContentNode);
1326 if (ret == ERROR_CODE_INTERNAL_ERROR) {
1327 ret = ERROR_CODE_NO_ERROR;
1328 }
1329 ReturnPromise(info, ret);
1330 return;
1331 }
1332
IsFollowingSystemFontScale(const JSCallbackInfo & info)1333 void JSViewContext::IsFollowingSystemFontScale(const JSCallbackInfo& info)
1334 {
1335 auto container = Container::CurrentSafely();
1336 CHECK_NULL_VOID(container);
1337 auto pipelineContext = container->GetPipelineContext();
1338 CHECK_NULL_VOID(pipelineContext);
1339 auto follow = pipelineContext->IsFollowSystem();
1340 auto followRef = JSRef<JSVal>::Make(JSVal(ToJSValue(follow)));
1341 info.SetReturnValue(followRef);
1342 return;
1343 }
1344
GetMaxFontScale(const JSCallbackInfo & info)1345 void JSViewContext::GetMaxFontScale(const JSCallbackInfo& info)
1346 {
1347 auto container = Container::CurrentSafely();
1348 CHECK_NULL_VOID(container);
1349 auto pipelineContext = container->GetPipelineContext();
1350 CHECK_NULL_VOID(pipelineContext);
1351 auto maxFontScale = pipelineContext->GetMaxAppFontScale();
1352 auto maxFontScaleRef = JSRef<JSVal>::Make(JSVal(ToJSValue(maxFontScale)));
1353 info.SetReturnValue(maxFontScaleRef);
1354 return;
1355 }
1356
SetEnableSwipeBack(const JSCallbackInfo & info)1357 void JSViewContext::SetEnableSwipeBack(const JSCallbackInfo& info)
1358 {
1359 if (info.Length() < 1) {
1360 return;
1361 }
1362 if (!info[0]->IsBoolean()) {
1363 return;
1364 }
1365 auto container = Container::CurrentSafely();
1366 CHECK_NULL_VOID(container);
1367 auto pipelineContext = container->GetPipelineContext();
1368 CHECK_NULL_VOID(pipelineContext);
1369 pipelineContext->SetEnableSwipeBack(info[0]->ToBoolean());
1370 }
1371
JSSetKeyboardAppearanceConfig(const JSCallbackInfo & info)1372 void JSViewContext::JSSetKeyboardAppearanceConfig(const JSCallbackInfo& info)
1373 {
1374 EcmaVM* vm = info.GetVm();
1375 CHECK_NULL_VOID(vm);
1376 auto jsTargetNode = info[0];
1377 auto* targetNodePtr = jsTargetNode->GetLocalHandle()->ToNativePointer(vm)->Value();
1378 auto* frameNode = reinterpret_cast<NG::FrameNode*>(targetNodePtr);
1379 CHECK_NULL_VOID(frameNode);
1380 if (!info[1]->IsObject()) {
1381 return;
1382 }
1383 auto nodeTag = frameNode->GetTag();
1384 if (nodeTag == V2::TEXTINPUT_ETS_TAG) {
1385 JSTextField::SetKeyboardAppearanceConfig(info);
1386 } else if (nodeTag == V2::SEARCH_ETS_TAG) {
1387 JSSearch::SetKeyboardAppearanceConfig(info);
1388 }
1389 }
1390
JSBind(BindingTarget globalObj)1391 void JSViewContext::JSBind(BindingTarget globalObj)
1392 {
1393 JSClass<JSViewContext>::Declare("Context");
1394 JSClass<JSViewContext>::StaticMethod("animation", JSAnimation);
1395 JSClass<JSViewContext>::StaticMethod("animateTo", JSAnimateTo);
1396 JSClass<JSViewContext>::StaticMethod("animateToImmediately", JSAnimateToImmediately);
1397 JSClass<JSViewContext>::StaticMethod("keyframeAnimateTo", JSKeyframeAnimateTo);
1398 JSClass<JSViewContext>::StaticMethod("setDynamicDimming", SetDynamicDimming);
1399 JSClass<JSViewContext>::StaticMethod("openBindSheet", JSOpenBindSheet);
1400 JSClass<JSViewContext>::StaticMethod("updateBindSheet", JSUpdateBindSheet);
1401 JSClass<JSViewContext>::StaticMethod("closeBindSheet", JSCloseBindSheet);
1402 JSClass<JSViewContext>::StaticMethod("openPopup", JSOpenPopup);
1403 JSClass<JSViewContext>::StaticMethod("updatePopup", JSUpdatePopup);
1404 JSClass<JSViewContext>::StaticMethod("closePopup", JSClosePopup);
1405 JSClass<JSViewContext>::StaticMethod("openMenu", JSOpenMenu);
1406 JSClass<JSViewContext>::StaticMethod("updateMenu", JSUpdateMenu);
1407 JSClass<JSViewContext>::StaticMethod("closeMenu", JSCloseMenu);
1408 JSClass<JSViewContext>::StaticMethod("isFollowingSystemFontScale", IsFollowingSystemFontScale);
1409 JSClass<JSViewContext>::StaticMethod("getMaxFontScale", GetMaxFontScale);
1410 JSClass<JSViewContext>::StaticMethod("bindTabsToScrollable", JSTabsFeature::BindTabsToScrollable);
1411 JSClass<JSViewContext>::StaticMethod("unbindTabsFromScrollable", JSTabsFeature::UnbindTabsFromScrollable);
1412 JSClass<JSViewContext>::StaticMethod("bindTabsToNestedScrollable", JSTabsFeature::BindTabsToNestedScrollable);
1413 JSClass<JSViewContext>::StaticMethod(
1414 "unbindTabsFromNestedScrollable", JSTabsFeature::UnbindTabsFromNestedScrollable);
1415 JSClass<JSViewContext>::StaticMethod("enableSwipeBack", JSViewContext::SetEnableSwipeBack);
1416 JSClass<JSViewContext>::StaticMethod("setKeyboardAppearanceConfig", JSViewContext::JSSetKeyboardAppearanceConfig);
1417 JSClass<JSViewContext>::Bind<>(globalObj);
1418 }
1419
1420 } // namespace OHOS::Ace::Framework
1421