• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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