• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "frameworks/bridge/declarative_frontend/jsview/js_navigation.h"
17 
18 #include <vector>
19 
20 #include "base/log/ace_scoring_log.h"
21 #include "base/memory/referenced.h"
22 #include "base/system_bar/system_bar_style.h"
23 #include "bridge/declarative_frontend/engine/functions/js_click_function.h"
24 #include "bridge/declarative_frontend/engine/functions/js_event_function.h"
25 #include "bridge/declarative_frontend/engine/functions/js_navigation_function.h"
26 #include "bridge/declarative_frontend/engine/js_converter.h"
27 #include "bridge/declarative_frontend/engine/js_ref_ptr.h"
28 #include "bridge/declarative_frontend/engine/js_types.h"
29 #include "bridge/declarative_frontend/jsview/js_nav_path_stack.h"
30 #include "bridge/declarative_frontend/jsview/js_navigation_stack.h"
31 #include "bridge/declarative_frontend/jsview/js_navigation_utils.h"
32 #include "bridge/declarative_frontend/jsview/js_utils.h"
33 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
34 #include "bridge/declarative_frontend/jsview/models/navigation_model_impl.h"
35 #include "core/components_ng/base/view_abstract_model.h"
36 #include "core/components_ng/base/view_stack_model.h"
37 #include "core/components_ng/base/view_stack_processor.h"
38 #include "core/components_ng/pattern/navigation/navigation_declaration.h"
39 #include "core/components_ng/pattern/navigation/navigation_model_data.h"
40 #include "core/components_ng/pattern/navigation/navigation_model_ng.h"
41 #include "core/components_ng/pattern/navigation/navigation_options.h"
42 #include "core/components_ng/pattern/navigation/title_bar_pattern.h"
43 
44 namespace OHOS::Ace {
45 std::unique_ptr<NavigationModel> NavigationModel::instance_ = nullptr;
46 std::mutex NavigationModel::mutex_;
47 constexpr int32_t NAVIGATION_ANIMATION_TIMEOUT = 1000; // ms
48 
GetInstance()49 NavigationModel* NavigationModel::GetInstance()
50 {
51     if (!instance_) {
52         std::lock_guard<std::mutex> lock(mutex_);
53         if (!instance_) {
54 #ifdef NG_BUILD
55             instance_.reset(new NG::NavigationModelNG());
56 #else
57             if (Container::IsCurrentUseNewPipeline()) {
58                 instance_.reset(new NG::NavigationModelNG());
59             } else {
60                 instance_.reset(new Framework::NavigationModelImpl());
61             }
62 #endif
63         }
64     }
65     return instance_.get();
66 }
67 } // namespace OHOS::Ace
68 
69 namespace OHOS::Ace::Framework {
70 namespace {
71 constexpr int32_t TITLE_MODE_RANGE = 2;
72 constexpr int32_t NAVIGATION_MODE_RANGE = 2;
73 constexpr int32_t NAV_BAR_POSITION_RANGE = 1;
74 constexpr int32_t DEFAULT_NAV_BAR_WIDTH = 240;
75 constexpr Dimension DEFAULT_MIN_CONTENT_WIDTH = 360.0_vp;
76 constexpr int32_t PARAMETER_LENGTH_ONE  = 1;
77 constexpr int32_t PARAMETER_LENGTH_TWO  = 2;
78 constexpr int32_t PARAMETER_LENGTH_THREE  = 3;
79 constexpr int32_t LAYOUT_SAFE_AREA_TYPE_LIMIT = 2;
80 constexpr int32_t LAYOUT_SAFE_AREA_EDGE_LIMIT = 6;
81 constexpr bool ENABLE_TOOLBAR_ADAPTATION_DEFULT = true;
82 constexpr char MORE_BUTTON_OPTIONS_PROPERTY[] = "moreButtonOptions";
83 constexpr char HOME_DESTINATION_INFO_NAME[] = "name";
84 constexpr char HOME_DESTINATION_INFO_PARAM[] = "param";
85 
TitleModeChangeEventToJSValue(const NavigationTitleModeChangeEvent & eventInfo)86 JSRef<JSVal> TitleModeChangeEventToJSValue(const NavigationTitleModeChangeEvent& eventInfo)
87 {
88     return JSRef<JSVal>::Make(ToJSValue(eventInfo.IsMiniBar() ? static_cast<int32_t>(NavigationTitleMode::MINI)
89                                                               : static_cast<int32_t>(NavigationTitleMode::FULL)));
90 }
91 
ParseCreateParamsWithOneArg(const JSCallbackInfo & info,JSRef<JSObject> & stackObj,std::string & moduleName,std::string & pagePath)92 bool ParseCreateParamsWithOneArg(
93     const JSCallbackInfo& info, JSRef<JSObject>& stackObj, std::string& moduleName, std::string& pagePath)
94 {
95     // input format: navPathStack/pathInfo
96     if (!info[0]->IsObject()) {
97         return false;
98     }
99     // instance of NavPathStack
100     JSValueWrapper valueWrapper = info[0].Get().GetLocalHandle();
101     if (!JSNavPathStack::CheckIsValid(valueWrapper)) {
102         // first parameter = pathInfo{'moduleName': stringA, 'pagePath': stringB, 'isUserCreateStack': bool}
103         TAG_LOGE(AceLogTag::ACE_NAVIGATION, "current stack is not navPathStack");
104         auto infoObj = JSRef<JSObject>::Cast(info[0]);
105         if (!infoObj->GetProperty(NG::NAVIGATION_MODULE_NAME)->IsString() ||
106             !infoObj->GetProperty(NG::NAVIGATION_PAGE_PATH)->IsString()) {
107             TAG_LOGE(AceLogTag::ACE_NAVIGATION, "current pageInfo is invalid");
108             return false;
109         }
110         moduleName = infoObj->GetProperty(NG::NAVIGATION_MODULE_NAME)->ToString();
111         pagePath = infoObj->GetProperty(NG::NAVIGATION_PAGE_PATH)->ToString();
112     } else {
113         // first parameter = navPathStack
114         stackObj = JSRef<JSObject>::Cast(info[0]);
115     }
116     return true;
117 }
118 
ParseCreateParamsWithTwoArgs(const JSCallbackInfo & info,JSRef<JSObject> & stackObj,std::string & moduleName,std::string & pagePath)119 bool ParseCreateParamsWithTwoArgs(
120     const JSCallbackInfo& info, JSRef<JSObject>& stackObj, std::string& moduleName, std::string& pagePath)
121 {
122     // parameter = navPathStack(maybe empty) + pathInfo
123     if (!info[0]->IsObject() || !info[1]->IsObject()) {
124         TAG_LOGE(AceLogTag::ACE_NAVIGATION, "stack or pageInfo is invalid");
125         return false;
126     }
127     // instance of NavPathStack
128     JSValueWrapper valueWrapper = info[0].Get().GetLocalHandle();
129     if (!JSNavPathStack::CheckIsValid(valueWrapper)) {
130         TAG_LOGE(AceLogTag::ACE_NAVIGATION, "current stack is not navPathStack");
131         return false;
132     }
133     // pathInfo{'moduleName': stringA, 'pagePath': stringB, 'isUserCreateStack': bool}
134     auto infoObj = JSRef<JSObject>::Cast(info[1]);
135     auto isUserCreateStack = infoObj->GetProperty(NG::IS_USER_CREATE_STACK);
136     bool isUserDefined = true;
137     if (isUserCreateStack->IsBoolean()) {
138         isUserDefined = isUserCreateStack->ToBoolean();
139     }
140     if (isUserDefined) {
141         stackObj = JSRef<JSObject>::Cast(info[0]);
142     }
143     if (!infoObj->GetProperty(NG::NAVIGATION_MODULE_NAME)->IsString() ||
144         !infoObj->GetProperty(NG::NAVIGATION_PAGE_PATH)->IsString()) {
145         TAG_LOGE(AceLogTag::ACE_NAVIGATION, "current pageInfo is invalid");
146         return false;
147     }
148     moduleName = infoObj->GetProperty(NG::NAVIGATION_MODULE_NAME)->ToString();
149     pagePath = infoObj->GetProperty(NG::NAVIGATION_PAGE_PATH)->ToString();
150 
151     return true;
152 }
153 
ParseCreateParamsWithThreeArgs(const JSCallbackInfo & info,JSRef<JSObject> & stackObj,std::string & moduleName,std::string & pagePath,std::function<void (const RefPtr<NG::NavigationStack> &)> & setHomePathInfoCallback)154 bool ParseCreateParamsWithThreeArgs(
155     const JSCallbackInfo& info, JSRef<JSObject>& stackObj, std::string& moduleName, std::string& pagePath,
156     std::function<void(const RefPtr<NG::NavigationStack>&)>& setHomePathInfoCallback)
157 {
158     // 1st param: NavPathStack, 2st param: homeDestination, 3rd param: { 'moduleName': xxx, ... }
159     if (!info[0]->IsObject() || !info[1]->IsObject() || !info[2]->IsObject()) {
160         TAG_LOGE(AceLogTag::ACE_NAVIGATION, "stack, homeDestination or pageInfo is invalid");
161         return false;
162     }
163     // instance of NavPathStack
164     JSValueWrapper valueWrapper = info[0].Get().GetLocalHandle();
165     if (!JSNavPathStack::CheckIsValid(valueWrapper)) {
166         TAG_LOGE(AceLogTag::ACE_NAVIGATION, "current stack is not navPathStack");
167         return false;
168     }
169     // homeDestination
170     auto homeDestObj = JSRef<JSObject>::Cast(info[1]);
171     auto nameObj = homeDestObj->GetProperty(HOME_DESTINATION_INFO_NAME);
172     auto paramObj = homeDestObj->GetProperty(HOME_DESTINATION_INFO_PARAM);
173     HomePathInfo pathInfo;
174     if (!nameObj->IsEmpty() && nameObj->IsString()) {
175         pathInfo.name = nameObj->ToString();
176         pathInfo.param = paramObj;
177     } else {
178         TAG_LOGE(AceLogTag::ACE_NAVIGATION, "Invalid HomeDestination found");
179         return false;
180     }
181     setHomePathInfoCallback = [pathInfo](const RefPtr<NG::NavigationStack>& stack) mutable {
182         auto jsStack = AceType::DynamicCast<JSNavigationStack>(stack);
183         CHECK_NULL_VOID(jsStack);
184         jsStack->SetHomePathInfo(std::move(pathInfo));
185     };
186     // pathInfo{'moduleName': stringA, 'pagePath': stringB, 'isUserCreateStack': bool}
187     auto infoObj = JSRef<JSObject>::Cast(info[2]);
188     auto isUserCreateStack = infoObj->GetProperty(NG::IS_USER_CREATE_STACK);
189     bool isUserDefined = true;
190     if (isUserCreateStack->IsBoolean()) {
191         isUserDefined = isUserCreateStack->ToBoolean();
192     }
193     if (isUserDefined) {
194         stackObj = JSRef<JSObject>::Cast(info[0]);
195     }
196     if (!infoObj->GetProperty(NG::NAVIGATION_MODULE_NAME)->IsString() ||
197         !infoObj->GetProperty(NG::NAVIGATION_PAGE_PATH)->IsString()) {
198         TAG_LOGE(AceLogTag::ACE_NAVIGATION, "current pageInfo is invalid");
199         return false;
200     }
201     moduleName = infoObj->GetProperty(NG::NAVIGATION_MODULE_NAME)->ToString();
202     pagePath = infoObj->GetProperty(NG::NAVIGATION_PAGE_PATH)->ToString();
203 
204     return true;
205 }
206 } // namespace
207 
ParseToolBarItems(const JSCallbackInfo & info,std::list<RefPtr<AceType>> & items)208 void JSNavigation::ParseToolBarItems(const JSCallbackInfo& info, std::list<RefPtr<AceType>>& items)
209 {
210     if (info[0]->IsUndefined()) {
211         return;
212     }
213     JSRef<JSArray> jsArray = JSRef<JSArray>::Cast(info[0]);
214     auto length = jsArray->Length();
215     for (size_t i = 0; i < length; i++) {
216         auto item = jsArray->GetValueAt(i);
217         if (!item->IsObject()) {
218             continue;
219         }
220 
221         auto itemObject = JSRef<JSObject>::Cast(item);
222         auto toolBarItem = AceType::MakeRefPtr<ToolBarItem>();
223         auto itemValueObject = itemObject->GetProperty("value");
224         if (itemValueObject->IsString()) {
225             toolBarItem->value = itemValueObject->ToString();
226         }
227 
228         auto itemIconObject = itemObject->GetProperty("icon");
229         std::string icon;
230         ParseJsMedia(itemIconObject, icon);
231         toolBarItem->icon = icon;
232 
233         auto itemActionValue = itemObject->GetProperty("action");
234         if (itemActionValue->IsFunction()) {
235             auto onClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(itemActionValue));
236             auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
237             toolBarItem->action =
238                 EventMarker([func = std::move(onClickFunc), node = targetNode, execCtx = info.GetExecutionContext()]() {
239                     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
240                     ACE_SCORING_EVENT("Navigation.toolBarItemClick");
241                     PipelineContext::SetCallBackNode(node);
242                     func->Execute();
243                 });
244             auto onClickWithParamFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(itemActionValue));
245             toolBarItem->actionWithParam =
246                 EventMarker([func = std::move(onClickWithParamFunc), node = targetNode,
247                                 execCtx = info.GetExecutionContext()](const BaseEventInfo* info) {
248                     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
249                     ACE_SCORING_EVENT("Navigation.menuItemButtonClick");
250                     PipelineContext::SetCallBackNode(node);
251                     func->Execute();
252                 });
253         }
254         items.push_back(toolBarItem);
255     }
256 }
257 
ParseCommonTitle(const JSRef<JSObject> & jsObj)258 bool JSNavigation::ParseCommonTitle(const JSRef<JSObject>& jsObj)
259 {
260     JSRef<JSVal> subtitle = jsObj->GetProperty("sub");
261     JSRef<JSVal> title = jsObj->GetProperty("main");
262     std::string mainTitle;
263     std::string subTitle;
264     RefPtr<ResourceObject> subResObj;
265     RefPtr<ResourceObject> mainResObj;
266     bool hasSub = ParseJsString(subtitle, subTitle, subResObj);
267     bool hasMain = ParseJsString(title, mainTitle, mainResObj);
268     if (hasSub || hasMain) {
269         if (SystemProperties::ConfigChangePerform() && (mainResObj || subResObj)) {
270             return NavigationModel::GetInstance()->ParseCommonTitle(
271                 hasSub, hasMain, subResObj, mainResObj);
272         } else {
273             return NavigationModel::GetInstance()->ParseCommonTitle(
274                 hasSub, hasMain, subTitle, mainTitle);
275         }
276     }
277     return false;
278 }
279 
ParseCommonAndCustomTitle(const JSRef<JSObject> & jsObj)280 void JSNavigation::ParseCommonAndCustomTitle(const JSRef<JSObject>& jsObj)
281 {
282     // NavigationCommonTitle
283     if (ParseCommonTitle(jsObj)) {
284         return;
285     }
286     // CustomBuilder | NavigationCustomTitle
287     CalcDimension titleHeight;
288     if (!jsObj->HasProperty("height")) {
289         NavigationModel::GetInstance()->SetTitleHeight(titleHeight, false);
290         return;
291     }
292     JSRef<JSVal> height = jsObj->GetProperty("height");
293     RefPtr<ResourceObject> heightResObj;
294     bool isValid = JSContainerBase::ParseJsDimensionVpNG(height, titleHeight, heightResObj);
295     if (height->IsString()) {
296         std::string heightValue;
297         ParseJsString(height, heightValue);
298         if (heightValue == NG::TITLE_MAIN_WITH_SUB) {
299             NavigationModel::GetInstance()->SetTitleHeight(NG::DOUBLE_LINE_TITLEBAR_HEIGHT);
300             return;
301         }
302         if (heightValue == NG::TITLE_MAIN) {
303             NavigationModel::GetInstance()->SetTitleHeight(NG::SINGLE_LINE_TITLEBAR_HEIGHT);
304             return;
305         }
306     }
307     if (!isValid || titleHeight.Value() < 0) {
308         NavigationModel::GetInstance()->SetTitleHeight(Dimension(), true);
309         return;
310     }
311     if (SystemProperties::ConfigChangePerform() && heightResObj) {
312         NavigationModel::GetInstance()->SetTitleHeight(titleHeight, heightResObj);
313         return;
314     }
315     NavigationModel::GetInstance()->SetTitleHeight(titleHeight);
316 }
317 
ParseBackButtonText(const JSCallbackInfo & info,RefPtr<PixelMap> & pixMap,const NG::ImageOption & imageOption,const std::function<void (WeakPtr<NG::FrameNode>)> & iconSymbol,std::string src,const std::vector<std::string> & nameList,RefPtr<ResourceObject> & backButtonIconResObj)318 void JSNavigation::ParseBackButtonText(const JSCallbackInfo& info, RefPtr<PixelMap>& pixMap,
319     const NG::ImageOption& imageOption, const std::function<void(WeakPtr<NG::FrameNode>)>& iconSymbol, std::string src,
320     const std::vector<std::string>& nameList, RefPtr<ResourceObject>& backButtonIconResObj)
321 {
322     std::string backButtonAccessibilityText;
323     RefPtr<ResourceObject> backButtonTextResObj;
324     JSViewAbstract::ParseJsString(info[1], backButtonAccessibilityText, backButtonTextResObj);
325     if (SystemProperties::ConfigChangePerform()) {
326         if (backButtonIconResObj && backButtonTextResObj) {
327             NavigationModel::GetInstance()->SetBackButtonIconSrcAndTextRes(
328                 iconSymbol, backButtonIconResObj, imageOption, pixMap, nameList, true, backButtonTextResObj);
329             return;
330         }
331         if (backButtonTextResObj) {
332             NavigationModel::GetInstance()->SetBackButtonIconTextRes(
333                 iconSymbol, src, imageOption, pixMap, nameList, true, backButtonTextResObj);
334             return;
335         }
336         if (backButtonIconResObj) {
337             NavigationModel::GetInstance()->SetBackButtonIcon(
338                 iconSymbol, backButtonIconResObj, imageOption, pixMap, nameList, true, backButtonAccessibilityText);
339             return;
340         }
341     }
342     NavigationModel::GetInstance()->SetBackButtonIcon(
343         iconSymbol, src, imageOption, pixMap, nameList, true, backButtonAccessibilityText);
344 }
345 
Create(const JSCallbackInfo & info)346 void JSNavigation::Create(const JSCallbackInfo& info)
347 {
348     JSRef<JSObject> newObj;
349     std::string moduleName;
350     std::string pagePath;
351     std::function<void(const RefPtr<NG::NavigationStack>&)> setHomePathInfoCallback;
352     bool parseSuccess = true;
353     bool useHomeDestination = false;
354     if (info.Length() == PARAMETER_LENGTH_ONE) {
355         parseSuccess = ParseCreateParamsWithOneArg(info, newObj, moduleName, pagePath);
356     } else if (info.Length() == PARAMETER_LENGTH_TWO) {
357         parseSuccess = ParseCreateParamsWithTwoArgs(info, newObj, moduleName, pagePath);
358     } else if (info.Length() == PARAMETER_LENGTH_THREE) {
359         useHomeDestination = true;
360         parseSuccess = ParseCreateParamsWithThreeArgs(
361             info, newObj, moduleName, pagePath, setHomePathInfoCallback);
362     }
363     if (!parseSuccess) {
364         return;
365     }
366 
367     NavigationModel::GetInstance()->Create(useHomeDestination);
368     auto stackCreator = []() -> RefPtr<JSNavigationStack> { return AceType::MakeRefPtr<JSNavigationStack>(); };
369     auto stackUpdater = [&newObj, &info](RefPtr<NG::NavigationStack> stack) {
370         NavigationModel::GetInstance()->SetNavigationStackProvided(!newObj->IsEmpty());
371         auto jsStack = AceType::DynamicCast<JSNavigationStack>(stack);
372         CHECK_NULL_VOID(jsStack);
373         jsStack->SetJSExecutionContext(info.GetExecutionContext());
374         const auto& oldObj = jsStack->GetDataSourceObj();
375         if (oldObj->IsEmpty()) {
376             if (newObj->IsEmpty()) {
377                 newObj = JSNavPathStack::CreateNewNavPathStackJSObject();
378             }
379             auto nativeObj = JSClass<JSNavPathStack>::NewInstance();
380             JSNavPathStack::SetNativeNavPathStack(newObj, nativeObj);
381             jsStack->SetDataSourceObj(newObj);
382         } else if (!newObj->IsEmpty()) {
383             auto objStrictEqual = [](const JSRef<JSVal>& obja, const JSRef<JSVal>& objb) -> bool {
384                 return obja->GetLocalHandle()->IsStrictEquals(obja->GetEcmaVM(), objb->GetLocalHandle());
385             };
386             if (objStrictEqual(newObj, oldObj)) {
387                 return;
388             }
389             auto nativeObj = JSClass<JSNavPathStack>::NewInstance();
390             JSNavPathStack::SetNativeNavPathStack(newObj, nativeObj);
391             jsStack->SetDataSourceObj(newObj);
392         }
393     };
394     NavigationModel::GetInstance()->SetNavigationStackWithCreatorAndUpdater(stackCreator, stackUpdater);
395     NavigationModel::GetInstance()->SetNavigationPathInfo(moduleName, pagePath);
396     if (useHomeDestination) {
397         NavigationModel::GetInstance()->SetHomePathInfoWithCallback(std::move(setHomePathInfoCallback));
398     }
399 }
400 
JSBind(BindingTarget globalObj)401 void JSNavigation::JSBind(BindingTarget globalObj)
402 {
403     JsNavigationTransitionProxy::JSBind(globalObj);
404     JSClass<JSNavigation>::Declare("Navigation");
405     MethodOptions opt = MethodOptions::NONE;
406     JSClass<JSNavigation>::StaticMethod("create", &JSNavigation::Create);
407     JSClass<JSNavigation>::StaticMethod("title", &JSNavigation::SetTitle, opt);
408     JSClass<JSNavigation>::StaticMethod("subTitle", &JSNavigation::SetSubTitle, opt);
409     JSClass<JSNavigation>::StaticMethod("titleMode", &JSNavigation::SetTitleMode, opt);
410     JSClass<JSNavigation>::StaticMethod("hideTitleBar", &JSNavigation::SetHideTitleBar, opt);
411     JSClass<JSNavigation>::StaticMethod("hideBackButton", &JSNavigation::SetHideBackButton, opt);
412     JSClass<JSNavigation>::StaticMethod("hideToolBar", &JSNavigation::SetHideToolBar, opt);
413     JSClass<JSNavigation>::StaticMethod("toolBar", &JSNavigation::SetToolBar);
414     JSClass<JSNavigation>::StaticMethod("enableToolBarAdaptation", &JSNavigation::SetEnableToolBarAdaptation);
415     JSClass<JSNavigation>::StaticMethod("toolbarConfiguration", &JSNavigation::SetToolbarConfiguration);
416     JSClass<JSNavigation>::StaticMethod("menus", &JSNavigation::SetMenus);
417     JSClass<JSNavigation>::StaticMethod("menuCount", &JSNavigation::SetMenuCount);
418     JSClass<JSNavigation>::StaticMethod("onTitleModeChange", &JSNavigation::SetOnTitleModeChanged);
419     JSClass<JSNavigation>::StaticMethod("onNavigationModeChange", &JSNavigation::SetOnNavigationModeChange);
420     JSClass<JSNavigation>::StaticMethod("mode", &JSNavigation::SetUsrNavigationMode);
421     JSClass<JSNavigation>::StaticMethod("navBarWidth", &JSNavigation::SetNavBarWidth);
422     JSClass<JSNavigation>::StaticMethod("minContentWidth", &JSNavigation::SetMinContentWidth);
423     JSClass<JSNavigation>::StaticMethod("navBarWidthRange", &JSNavigation::SetNavBarWidthRange);
424     JSClass<JSNavigation>::StaticMethod("navBarPosition", &JSNavigation::SetNavBarPosition);
425     JSClass<JSNavigation>::StaticMethod("hideNavBar", &JSNavigation::SetHideNavBar);
426     JSClass<JSNavigation>::StaticMethod("backButtonIcon", &JSNavigation::SetBackButtonIcon);
427     JSClass<JSNavigation>::StaticMethod("onNavBarStateChange", &JSNavigation::SetOnNavBarStateChange);
428     JSClass<JSNavigation>::StaticMethod("navDestination", &JSNavigation::SetNavDestination);
429     JSClass<JSNavigation>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
430     JSClass<JSNavigation>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
431     JSClass<JSNavigation>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
432     JSClass<JSNavigation>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
433     JSClass<JSNavigation>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
434     JSClass<JSNavigation>::StaticMethod("customNavContentTransition", &JSNavigation::SetCustomNavContentTransition);
435     JSClass<JSNavigation>::StaticMethod("ignoreLayoutSafeArea", &JSNavigation::SetIgnoreLayoutSafeArea);
436     JSClass<JSNavigation>::StaticMethod("systemBarStyle", &JSNavigation::SetSystemBarStyle);
437     JSClass<JSNavigation>::StaticMethod("recoverable", &JSNavigation::SetRecoverable);
438     JSClass<JSNavigation>::StaticMethod("enableDragBar", &JSNavigation::SetEnableDragBar);
439     JSClass<JSNavigation>::StaticMethod("enableModeChangeAnimation", &JSNavigation::SetEnableModeChangeAnimation);
440     JSClass<JSNavigation>::StaticMethod("splitPlaceholder", &JSNavigation::SetSplitPlaceholder);
441     JSClass<JSNavigation>::InheritAndBind<JSContainerBase>(globalObj);
442 }
443 
SetTitle(const JSCallbackInfo & info)444 void JSNavigation::SetTitle(const JSCallbackInfo& info)
445 {
446     if (NavigationModel::GetInstance()->UseHomeDestination()) {
447         return;
448     }
449     if (info.Length() < 1) {
450         return;
451     }
452     NavigationModel::GetInstance()->ResetResObj(NavigationPatternType::TITLE_BAR, "navigation.title.commonMainTitle");
453     NavigationModel::GetInstance()->ResetResObj(NavigationPatternType::TITLE_BAR, "navigation.title.commonSubTitle");
454     NavigationModel::GetInstance()->ResetResObj(NavigationPatternType::TITLE_BAR, "navigation.title.customtitle");
455     // Resource and string type.
456     std::string title;
457     RefPtr<ResourceObject> mainResObj;
458     if (ParseJsString(info[0], title, mainResObj)) {
459         if (SystemProperties::ConfigChangePerform() && mainResObj) {
460             NavigationModel::GetInstance()->ParseCommonTitle(false, true, nullptr, mainResObj);
461         } else {
462             NavigationModel::GetInstance()->ParseCommonTitle(false, true, "", title);
463         }
464     } else if (info[0]->IsObject()) {
465         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
466         ParseCommonAndCustomTitle(jsObj);
467         JSRef<JSVal> builderObject = jsObj->GetProperty("builder");
468         if (builderObject->IsFunction()) {
469             ViewStackModel::GetInstance()->NewScope();
470             JsFunction jsBuilderFunc(info.This(), JSRef<JSFunc>::Cast(builderObject));
471             ACE_SCORING_EVENT("Navigation.title.builder");
472             jsBuilderFunc.Execute();
473             auto customNode = ViewStackModel::GetInstance()->Finish();
474             NavigationModel::GetInstance()->SetCustomTitle(customNode);
475         }
476     } else {
477         NavigationModel::GetInstance()->ParseCommonTitle(false, false, "", "");
478     }
479 
480     NG::NavigationTitlebarOptions options;
481     NavigationModel::GetInstance()->ResetResObj(
482         NavigationPatternType::NAVIGATION, "navigation.navigationTitlebarOptions");
483     JSNavigationUtils::ParseTitleBarOptions(info, true, options);
484     NavigationModel::GetInstance()->SetTitlebarOptions(std::move(options));
485 }
486 
SetTitleMode(int32_t value)487 void JSNavigation::SetTitleMode(int32_t value)
488 {
489     if (NavigationModel::GetInstance()->UseHomeDestination()) {
490         return;
491     }
492     if (value >= 0 && value <= TITLE_MODE_RANGE) {
493         NavigationModel::GetInstance()->SetTitleMode(static_cast<NG::NavigationTitleMode>(value));
494     }
495 }
496 
SetSubTitle(const std::string & subTitle)497 void JSNavigation::SetSubTitle(const std::string& subTitle)
498 {
499     if (NavigationModel::GetInstance()->UseHomeDestination()) {
500         return;
501     }
502     NavigationModel::GetInstance()->SetSubtitle(subTitle);
503 }
504 
SetHideTitleBar(const JSCallbackInfo & info)505 void JSNavigation::SetHideTitleBar(const JSCallbackInfo& info)
506 {
507     if (NavigationModel::GetInstance()->UseHomeDestination()) {
508         return;
509     }
510     bool isHide = false;
511     if (info.Length() > 0 && info[0]->IsBoolean()) {
512         isHide = info[0]->ToBoolean();
513     }
514     bool isAnimated = false;
515     if (info.Length() > 1 && info[1]->IsBoolean()) {
516         isAnimated = info[1]->ToBoolean();
517     }
518     NavigationModel::GetInstance()->SetHideTitleBar(isHide, isAnimated);
519 }
520 
SetEnableToolBarAdaptation(const JSCallbackInfo & info)521 void JSNavigation::SetEnableToolBarAdaptation(const JSCallbackInfo& info)
522 {
523     if (!info[0]->IsBoolean()) {
524         NavigationModel::GetInstance()->SetEnableToolBarAdaptation(ENABLE_TOOLBAR_ADAPTATION_DEFULT);
525         return;
526     }
527     auto enable = info[0]->ToBoolean();
528     NavigationModel::GetInstance()->SetEnableToolBarAdaptation(enable);
529 }
530 
SetEnableModeChangeAnimation(const JSCallbackInfo & info)531 void JSNavigation::SetEnableModeChangeAnimation(const JSCallbackInfo& info)
532 {
533     if (info.Length() < 1) {
534         return;
535     }
536     if (info[0]->IsBoolean()) {
537         NavigationModel::GetInstance()->SetEnableModeChangeAnimation(info[0]->ToBoolean());
538         return;
539     }
540     NavigationModel::GetInstance()->SetEnableModeChangeAnimation(true);
541 }
542 
SetSplitPlaceholder(const JSCallbackInfo & info)543 void JSNavigation::SetSplitPlaceholder(const JSCallbackInfo& info)
544 {
545     if (info.Length() < 1) {
546         TAG_LOGE(AceLogTag::ACE_NAVIGATION, "SplitPlaceholder is invalid");
547         return;
548     }
549     if (info[0]->IsUndefined() || info[0]->IsNull()) {
550         NavigationModel::GetInstance()->ResetSplitPlaceholder();
551         return;
552     }
553     if (!info[0]->IsObject()) {
554         return;
555     }
556     JSRef<JSObject> contentObject = JSRef<JSObject>::Cast(info[0]);
557     JSRef<JSVal> builderNodeParam = contentObject->GetProperty("builderNode_");
558     if (!builderNodeParam->IsObject()) {
559         TAG_LOGE(AceLogTag::ACE_NAVIGATION, "builderNode_ property is not an object");
560         return;
561     }
562     JSRef<JSObject> builderNodeObject = JSRef<JSObject>::Cast(builderNodeParam);
563     JSRef<JSVal> nodeptr = builderNodeObject->GetProperty("nodePtr_");
564     if (nodeptr.IsEmpty()) {
565         TAG_LOGE(AceLogTag::ACE_NAVIGATION, "nodePtr_ is empty");
566         return;
567     }
568     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(info.GetExecutionContext());
569     const auto* vm = nodeptr->GetEcmaVM();
570     CHECK_NULL_VOID(nodeptr->GetLocalHandle()->IsNativePointer(vm));
571     auto* node = reinterpret_cast<NG::UINode*>(nodeptr->GetLocalHandle()->ToNativePointer(vm)->Value());
572     CHECK_NULL_VOID(node);
573     RefPtr<NG::UINode> refPtrNode = AceType::Claim(node);
574     NavigationModel::GetInstance()->SetSplitPlaceholder(refPtrNode);
575 }
576 
SetHideNavBar(bool hide)577 void JSNavigation::SetHideNavBar(bool hide)
578 {
579     NavigationModel::GetInstance()->SetHideNavBar(hide);
580 }
581 
SetBackButtonIcon(const JSCallbackInfo & info)582 void JSNavigation::SetBackButtonIcon(const JSCallbackInfo& info)
583 {
584     if (NavigationModel::GetInstance()->UseHomeDestination()) {
585         return;
586     }
587     if (info.Length() < 1) {
588         return;
589     }
590     NavigationModel::GetInstance()->ResetResObj(NavigationPatternType::TITLE_BAR, "navigation.backButtonIcon.icon");
591     NavigationModel::GetInstance()->ResetResObj(
592         NavigationPatternType::TITLE_BAR, "navigation.backButtonIcon.accessibilityText");
593     std::string src;
594     RefPtr<ResourceObject> backButtonIconResObj;
595     auto noPixMap = ParseJsMedia(info[0], src, backButtonIconResObj);
596     auto isValidImage = false;
597     RefPtr<PixelMap> pixMap = nullptr;
598 #if defined(PIXEL_MAP_SUPPORTED)
599     if (!noPixMap) {
600         pixMap = CreatePixelMapFromNapiValue(info[0]);
601     }
602 #endif
603     if (noPixMap || pixMap != nullptr) {
604         isValidImage = true;
605     }
606     std::vector<std::string> nameList;
607     NG::ImageOption imageOption;
608     std::string bundleName;
609     std::string moduleName;
610     GetJsMediaBundleInfo(info[0], bundleName, moduleName);
611     nameList.emplace_back(bundleName);
612     nameList.emplace_back(moduleName);
613     imageOption.noPixMap = noPixMap;
614     imageOption.isValidImage = isValidImage;
615     std::function<void(WeakPtr<NG::FrameNode>)> iconSymbol = nullptr;
616     auto isSymbol = info[0]->IsObject() && src.empty() && pixMap == nullptr;
617     if (isSymbol) {
618         SetSymbolOptionApply(info, iconSymbol, info[0]);
619     }
620     bool configChange = SystemProperties::ConfigChangePerform();
621     if (info.Length() > 1 && !info[1]->IsNull() && !info[1]->IsUndefined()) {
622         ParseBackButtonText(info, pixMap, imageOption, iconSymbol, src, nameList, backButtonIconResObj);
623         return;
624     }
625     if (configChange && backButtonIconResObj) {
626         NavigationModel::GetInstance()->SetBackButtonIcon(iconSymbol, backButtonIconResObj, imageOption,
627             pixMap, nameList);
628         return;
629     }
630     NavigationModel::GetInstance()->SetBackButtonIcon(iconSymbol, src, imageOption, pixMap, nameList);
631 }
632 
SetHideBackButton(bool hide)633 void JSNavigation::SetHideBackButton(bool hide)
634 {
635     if (NavigationModel::GetInstance()->UseHomeDestination()) {
636         return;
637     }
638     NavigationModel::GetInstance()->SetHideBackButton(hide);
639 }
640 
SetHideToolBar(const JSCallbackInfo & info)641 void JSNavigation::SetHideToolBar(const JSCallbackInfo& info)
642 {
643     if (NavigationModel::GetInstance()->UseHomeDestination()) {
644         return;
645     }
646     bool isHide = false;
647     if (info.Length() > 0 && info[0]->IsBoolean()) {
648         isHide = info[0]->ToBoolean();
649     }
650     bool isAnimated = false;
651     if (info.Length() > 1 && info[1]->IsBoolean()) {
652         isAnimated = info[1]->ToBoolean();
653     }
654     NavigationModel::GetInstance()->SetHideToolBar(isHide, isAnimated);
655 }
656 
SetToolBar(const JSCallbackInfo & info)657 void JSNavigation::SetToolBar(const JSCallbackInfo& info)
658 {
659     if (NavigationModel::GetInstance()->UseHomeDestination()) {
660         return;
661     }
662     if (info.Length() < 1) {
663         return;
664     }
665     if (!info[0]->IsObject() && !info[0]->IsUndefined()) {
666         return;
667     }
668     if (info[0]->IsUndefined()) {
669         NavigationModel::GetInstance()->SetToolBarItems({});
670         return;
671     }
672     auto builderFuncParam = JSRef<JSObject>::Cast(info[0])->GetProperty("builder");
673     if (builderFuncParam->IsFunction()) {
674         ViewStackModel::GetInstance()->NewScope();
675         JsFunction jsBuilderFunc(builderFuncParam);
676         jsBuilderFunc.Execute();
677         auto customNode = ViewStackModel::GetInstance()->Finish();
678         NavigationModel::GetInstance()->SetCustomToolBar(customNode);
679     }
680 
681     auto itemsValue = JSRef<JSObject>::Cast(info[0])->GetProperty("items");
682     if (!itemsValue->IsObject() || !itemsValue->IsArray()) {
683         return;
684     }
685     if (NavigationModel::GetInstance()->NeedSetItems()) {
686         std::vector<NG::BarItem> toolBarItems;
687         auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
688         JSNavigationUtils::ParseBarItems(targetNode, info, JSRef<JSArray>::Cast(itemsValue), toolBarItems);
689         NavigationModel::GetInstance()->SetToolBarItems(std::move(toolBarItems));
690         return;
691     }
692     std::list<RefPtr<AceType>> items;
693     NavigationModel::GetInstance()->GetToolBarItems(items);
694     ParseToolBarItems(info, items);
695 }
696 
SetToolbarConfiguration(const JSCallbackInfo & info)697 void JSNavigation::SetToolbarConfiguration(const JSCallbackInfo& info)
698 {
699     if (NavigationModel::GetInstance()->UseHomeDestination()) {
700         return;
701     }
702     bool hideText = false;
703     JSNavigationUtils::ParseHideToolBarText(info, hideText);
704     NavigationModel::GetInstance()->SetHideItemText(hideText);
705     NavigationModel::GetInstance()->ResetResObj(NavigationPatternType::NAV_BAR, "navigation.toolbarConfiguration");
706     if (info[0]->IsUndefined() || info[0]->IsArray()) {
707         if (NavigationModel::GetInstance()->NeedSetItems()) {
708             std::vector<NG::BarItem> toolbarItems;
709             if (info[0]->IsUndefined()) {
710                 toolbarItems = {};
711             } else {
712                 auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
713                 JSNavigationUtils::ParseToolbarItemsConfiguration(
714                     targetNode, info, JSRef<JSArray>::Cast(info[0]), toolbarItems);
715             }
716             NG::MoreButtonOptions toolbarMoreButtonOptions;
717             if (info.Length() > 1 && info[1]->IsObject()) {
718                 auto optObj = JSRef<JSObject>::Cast(info[1]);
719                 auto moreButtonProperty = optObj->GetProperty(MORE_BUTTON_OPTIONS_PROPERTY);
720                 JSNavigationUtils::ParseToolBarMoreButtonOptions(moreButtonProperty, toolbarMoreButtonOptions);
721             }
722             if (SystemProperties::ConfigChangePerform()) {
723                 NavigationModel::GetInstance()->SetToolbarConfiguration(
724                     std::move(toolbarItems), std::move(toolbarMoreButtonOptions));
725             } else {
726                 NavigationModel::GetInstance()->SetToolbarMorebuttonOptions(std::move(toolbarMoreButtonOptions));
727                 NavigationModel::GetInstance()->SetToolbarConfiguration(std::move(toolbarItems));
728             }
729         } else {
730             std::list<RefPtr<AceType>> items;
731             NavigationModel::GetInstance()->GetToolBarItems(items);
732             ParseToolBarItems(info, items);
733         }
734     } else if (info[0]->IsObject()) {
735         auto builderFuncParam = JSRef<JSObject>::Cast(info[0])->GetProperty("builder");
736         if (builderFuncParam->IsFunction()) {
737             ViewStackModel::GetInstance()->NewScope();
738             JsFunction jsBuilderFunc(builderFuncParam);
739             jsBuilderFunc.Execute();
740             auto customNode = ViewStackModel::GetInstance()->Finish();
741             NavigationModel::GetInstance()->SetCustomToolBar(customNode);
742         }
743     }
744 
745     NG::NavigationToolbarOptions options;
746     NavigationModel::GetInstance()->ResetResObj(NavigationPatternType::NAV_BAR, "navigation.navigationToolbarOptions");
747     JSNavigationUtils::ParseToolbarOptions(info, options);
748     NavigationModel::GetInstance()->SetToolbarOptions(std::move(options));
749 }
750 
SetMenus(const JSCallbackInfo & info)751 void JSNavigation::SetMenus(const JSCallbackInfo& info)
752 {
753     if (NavigationModel::GetInstance()->UseHomeDestination()) {
754         return;
755     }
756     if (info.Length() < 1) {
757         return;
758     }
759 
760     NavigationModel::GetInstance()->ResetResObj(NavigationPatternType::NAV_BAR, "navigation.menuItems");
761     NavigationModel::GetInstance()->ResetResObj(NavigationPatternType::NAV_BAR, "navigation.navigationMenuOptions");
762     NG::NavigationMenuOptions options;
763     if (info.Length() > 1 && info[1]->IsObject()) {
764         auto optObj = JSRef<JSObject>::Cast(info[1]);
765         auto moreButtonProperty = optObj->GetProperty(MORE_BUTTON_OPTIONS_PROPERTY);
766         JSNavigationUtils::ParseMenuOptions(moreButtonProperty, options);
767     }
768     if (info[0]->IsUndefined() || info[0]->IsArray()) {
769         if (NavigationModel::GetInstance()->NeedSetItems()) {
770             std::vector<NG::BarItem> menuItems;
771             if (info[0]->IsUndefined()) {
772                 menuItems = {};
773             } else {
774                 auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
775                 JSNavigationUtils::ParseBarItems(targetNode, info, JSRef<JSArray>::Cast(info[0]), menuItems);
776             }
777             NavigationModel::GetInstance()->SetMenuItems(std::move(menuItems));
778             NavigationModel::GetInstance()->SetMenuOptions(std::move(options));
779             return;
780         }
781         std::list<RefPtr<AceType>> items;
782         NavigationModel::GetInstance()->GetMenuItems(items);
783         ParseToolBarItems(info, items);
784     } else if (info[0]->IsObject()) {
785         auto builderObject = JSRef<JSObject>::Cast(info[0])->GetProperty("builder");
786         if (builderObject->IsFunction()) {
787             ViewStackModel::GetInstance()->NewScope();
788             JsFunction jsBuilderFunc(info.This(), JSRef<JSFunc>::Cast(builderObject));
789             ACE_SCORING_EVENT("Navigation.menu.builder");
790             jsBuilderFunc.Execute();
791             auto customNode = ViewStackModel::GetInstance()->Finish();
792             NavigationModel::GetInstance()->SetCustomMenu(customNode);
793             NavigationModel::GetInstance()->SetMenuOptions(std::move(options));
794         }
795     }
796 }
797 
SetMenuCount(int32_t menuCount)798 void JSNavigation::SetMenuCount(int32_t menuCount)
799 {
800     if (NavigationModel::GetInstance()->UseHomeDestination()) {
801         return;
802     }
803     NavigationModel::GetInstance()->SetMenuCount(menuCount);
804 }
805 
SetOnTitleModeChanged(const JSCallbackInfo & info)806 void JSNavigation::SetOnTitleModeChanged(const JSCallbackInfo& info)
807 {
808     if (NavigationModel::GetInstance()->UseHomeDestination()) {
809         return;
810     }
811     if (info.Length() < 1) {
812         return;
813     }
814     if (info[0]->IsFunction()) {
815         auto onTitleModeChangeCallback =
816             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
817         auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
818         auto onTitleModeChange = [execCtx = info.GetExecutionContext(), func = std::move(onTitleModeChangeCallback),
819                                      node = targetNode](NG::NavigationTitleMode mode) {
820             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
821             ACE_SCORING_EVENT("OnTitleModeChange");
822             PipelineContext::SetCallBackNode(node);
823             JSRef<JSVal> param = JSRef<JSVal>::Make(ToJSValue(mode));
824             func->ExecuteJS(1, &param);
825         };
826         auto changeHandler = AceType::MakeRefPtr<JsEventFunction<NavigationTitleModeChangeEvent, 1>>(
827             JSRef<JSFunc>::Cast(info[0]), TitleModeChangeEventToJSValue);
828         auto eventInfo = [executionContext = info.GetExecutionContext(), func = std::move(changeHandler),
829                              node = targetNode](const BaseEventInfo* baseInfo) {
830             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
831             auto eventInfo = TypeInfoHelper::DynamicCast<NavigationTitleModeChangeEvent>(baseInfo);
832             if (!eventInfo) {
833                 return;
834             }
835             ACE_SCORING_EVENT("Navigation.onTitleModeChanged");
836             PipelineContext::SetCallBackNode(node);
837             func->Execute(*eventInfo);
838         };
839         NavigationModel::GetInstance()->SetOnTitleModeChange(std::move(onTitleModeChange), std::move(eventInfo));
840     }
841     info.ReturnSelf();
842 }
843 
SetUsrNavigationMode(const JSCallbackInfo & info)844 void JSNavigation::SetUsrNavigationMode(const JSCallbackInfo& info)
845 {
846     if (!info[0]->IsNumber()) {
847         NavigationModel::GetInstance()->SetUsrNavigationMode(NG::NavigationMode::AUTO);
848         return;
849     }
850     int32_t value = info[0]->ToNumber<int32_t>();
851     if (value >= 0 && value <= NAVIGATION_MODE_RANGE) {
852         NavigationModel::GetInstance()->SetUsrNavigationMode(static_cast<NG::NavigationMode>(value));
853     }
854 }
855 
SetNavBarPosition(int32_t value)856 void JSNavigation::SetNavBarPosition(int32_t value)
857 {
858     if (value >= 0 && value <= NAV_BAR_POSITION_RANGE) {
859         NavigationModel::GetInstance()->SetNavBarPosition(static_cast<NG::NavBarPosition>(value));
860     }
861 }
862 
ParseNavBarWidthObject(const JSCallbackInfo & info,JSRef<JSVal> arrowFunc,bool isNumber)863 void ParseNavBarWidthObject(const JSCallbackInfo& info, JSRef<JSVal> arrowFunc, bool isNumber)
864 {
865     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(arrowFunc));
866     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
867     auto onChangeEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
868                         node = targetNode, useNumber = isNumber](const Dimension& navBarWidth) {
869         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
870         ACE_SCORING_EVENT("Navigation.onNavBarWidthChangeEvent");
871         PipelineContext::SetCallBackNode(node);
872         auto newJSVal = useNumber ? JSRef<JSVal>::Make(ToJSValue(navBarWidth.ConvertToVp())) :
873             JSRef<JSVal>::Make(ToJSValue(navBarWidth.ToString()));
874         func->ExecuteJS(1, &newJSVal);
875     };
876     NavigationModel::GetInstance()->SetOnNavBarWidthChangeEvent(std::move(onChangeEvent));
877 }
878 
SetNavBarWidth(const JSCallbackInfo & info)879 void JSNavigation::SetNavBarWidth(const JSCallbackInfo& info)
880 {
881     if (info.Length() < 1) {
882         return;
883     }
884 
885     NavigationModel::GetInstance()->ResetResObj(NavigationPatternType::NAVIGATION, "navigation.navBarWidth");
886     if (info[0]->IsObject()) {
887         JSRef<JSObject> callbackObj = JSRef<JSObject>::Cast(info[0]);
888         CalcDimension value;
889         auto navBarWidthValue = callbackObj->GetProperty("value");
890         auto navBarWidthCallbackValue = callbackObj->GetProperty("$value");
891         auto isValid = JSViewAbstract::ParseJsDimensionVpNG(navBarWidthValue, value);
892         if (value.Value() <= 0) {
893             value.SetValue(DEFAULT_NAV_BAR_WIDTH);
894         }
895         bool isNumber = navBarWidthValue->IsNumber();
896         if (isValid && navBarWidthCallbackValue->IsFunction()) {
897             NavigationModel::GetInstance()->SetNavBarWidth(value, true);
898             ParseNavBarWidthObject(info, navBarWidthCallbackValue, isNumber);
899             return;
900         }
901     }
902 
903     CalcDimension navBarWidth;
904     RefPtr<ResourceObject> navBarWidthResObj;
905     if (!ParseJsDimensionVp(info[0], navBarWidth, navBarWidthResObj)) {
906         return;
907     }
908 
909     if (navBarWidth.Value() <= 0) {
910         navBarWidth.SetValue(DEFAULT_NAV_BAR_WIDTH);
911     }
912 
913     if (SystemProperties::ConfigChangePerform() && navBarWidthResObj) {
914         NavigationModel::GetInstance()->SetNavBarWidth(navBarWidthResObj);
915         return;
916     }
917     NavigationModel::GetInstance()->SetNavBarWidth(navBarWidth);
918 }
919 
SetMinContentWidth(const JSCallbackInfo & info)920 void JSNavigation::SetMinContentWidth(const JSCallbackInfo& info)
921 {
922     if (info.Length() < 1) {
923         return;
924     }
925 
926     NavigationModel::GetInstance()->ResetResObj(NavigationPatternType::NAVIGATION, "navigation.minContentWidth");
927     CalcDimension minContentWidth;
928     RefPtr<ResourceObject> minContentWidthResObj;
929     if (!ParseJsDimensionVp(info[0], minContentWidth, minContentWidthResObj)) {
930         NavigationModel::GetInstance()->SetMinContentWidth(DEFAULT_MIN_CONTENT_WIDTH);
931         return;
932     }
933 
934     if (LessNotEqual(minContentWidth.Value(), 0.0)) {
935         minContentWidth = DEFAULT_MIN_CONTENT_WIDTH;
936     }
937 
938     if (SystemProperties::ConfigChangePerform() && minContentWidthResObj) {
939         NavigationModel::GetInstance()->SetMinContentWidth(minContentWidthResObj);
940         return;
941     }
942     NavigationModel::GetInstance()->SetMinContentWidth(minContentWidth);
943 }
944 
SetNavBarWidthRange(const JSCallbackInfo & info)945 void JSNavigation::SetNavBarWidthRange(const JSCallbackInfo& info)
946 {
947     if (info.Length() < 1) {
948         return;
949     }
950     NavigationModel::GetInstance()->ResetResObj(
951         NavigationPatternType::NAVIGATION, "navigation.navBarWidthRange.maxNavBarWidth");
952     NavigationModel::GetInstance()->ResetResObj(
953         NavigationPatternType::NAVIGATION, "navigation.navBarWidthRange.minNavBarWidth");
954     if (info[0]->IsNull() || info[0]->IsUndefined()) {
955         NavigationModel::GetInstance()->SetMinNavBarWidth(NG::DEFAULT_MIN_NAV_BAR_WIDTH);
956         NavigationModel::GetInstance()->SetMaxNavBarWidth(NG::DEFAULT_MAX_NAV_BAR_WIDTH);
957         return;
958     }
959     if (!info[0]->IsArray()) {
960         return;
961     }
962     auto rangeArray = JSRef<JSArray>::Cast(info[0]);
963     JSRef<JSVal> min = rangeArray->GetValueAt(0);
964     JSRef<JSVal> max = rangeArray->GetValueAt(1);
965 
966     CalcDimension minNavBarWidth;
967     CalcDimension maxNavBarWidth;
968     RefPtr<ResourceObject> minNavBarWidthResObj;
969     if (min->IsNull() || min->IsUndefined() || !ParseJsDimensionVp(min, minNavBarWidth, minNavBarWidthResObj)) {
970         minNavBarWidth = NG::DEFAULT_MIN_NAV_BAR_WIDTH;
971     }
972     if (LessNotEqual(minNavBarWidth.Value(), 0.0)) {
973         minNavBarWidth.SetValue(0);
974     }
975     if (SystemProperties::ConfigChangePerform() && minNavBarWidthResObj) {
976         NavigationModel::GetInstance()->SetMinNavBarWidth(minNavBarWidthResObj);
977     } else {
978         NavigationModel::GetInstance()->SetMinNavBarWidth(minNavBarWidth);
979     }
980 
981     RefPtr<ResourceObject> maxNavBarWidthResObj;
982     if (max->IsNull() || max->IsUndefined() || !ParseJsDimensionVp(max, maxNavBarWidth, maxNavBarWidthResObj)) {
983         maxNavBarWidth = NG::DEFAULT_MAX_NAV_BAR_WIDTH;
984     }
985 
986     if (SystemProperties::ConfigChangePerform() && maxNavBarWidthResObj) {
987         NavigationModel::GetInstance()->SetMaxNavBarWidth(maxNavBarWidthResObj);
988         return;
989     }
990 
991     if (LessNotEqual(maxNavBarWidth.Value(), 0.0)) {
992         maxNavBarWidth.SetValue(0);
993     }
994     NavigationModel::GetInstance()->SetMaxNavBarWidth(maxNavBarWidth);
995 }
996 
SetOnNavBarStateChange(const JSCallbackInfo & info)997 void JSNavigation::SetOnNavBarStateChange(const JSCallbackInfo& info)
998 {
999     if (info.Length() < 1) {
1000         return;
1001     }
1002 
1003     if (info[0]->IsFunction()) {
1004         auto onNavBarStateChangeCallback =
1005             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
1006         auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1007         auto onNavBarStateChange = [execCtx = info.GetExecutionContext(), func = std::move(onNavBarStateChangeCallback),
1008                                        node = targetNode](bool isVisible) {
1009             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1010             ACE_SCORING_EVENT("OnNavBarStateChange");
1011             PipelineContext::SetCallBackNode(node);
1012             JSRef<JSVal> param = JSRef<JSVal>::Make(ToJSValue(isVisible));
1013             func->ExecuteJS(1, &param);
1014         };
1015         NavigationModel::GetInstance()->SetOnNavBarStateChange(std::move(onNavBarStateChange));
1016     }
1017     info.ReturnSelf();
1018 }
1019 
SetNavDestination(const JSCallbackInfo & info)1020 void JSNavigation::SetNavDestination(const JSCallbackInfo& info)
1021 {
1022     if (info.Length() < 1) {
1023         return;
1024     }
1025 
1026     if (!info[0]->IsObject()) {
1027         return;
1028     }
1029 
1030     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
1031     auto builder = obj->GetProperty("builder");
1032     if (!builder->IsFunction()) {
1033         return;
1034     }
1035 
1036     auto navigationStack = NavigationModel::GetInstance()->GetNavigationStack();
1037     auto jsNavigationStack = AceType::DynamicCast<JSNavigationStack>(navigationStack);
1038     if (jsNavigationStack) {
1039         jsNavigationStack->SetNavDestBuilderFunc(JSRef<JSFunc>::Cast(builder));
1040     }
1041 }
1042 
SetOnNavigationModeChange(const JSCallbackInfo & info)1043 void JSNavigation::SetOnNavigationModeChange(const JSCallbackInfo& info)
1044 {
1045     if (info.Length() < 1) {
1046         return;
1047     }
1048     if (!info[0]->IsFunction()) {
1049         info.ReturnSelf();
1050         return;
1051     }
1052     auto onModeChangeCallback = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
1053     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1054     auto onModeChange = [execCtx = info.GetExecutionContext(), func = std::move(onModeChangeCallback),
1055                             node = targetNode](NG::NavigationMode mode) {
1056         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1057         ACE_SCORING_EVENT("OnNavigationModeChange");
1058         PipelineContext::SetCallBackNode(node);
1059         JSRef<JSVal> param = JSRef<JSVal>::Make(ToJSValue(static_cast<int8_t>(mode)));
1060         func->ExecuteJS(1, &param);
1061     };
1062     NavigationModel::GetInstance()->SetOnNavigationModeChange(std::move(onModeChange));
1063     info.ReturnSelf();
1064 }
1065 
SetCustomNavContentTransition(const JSCallbackInfo & info)1066 void JSNavigation::SetCustomNavContentTransition(const JSCallbackInfo& info)
1067 {
1068     if (info.Length() == 0 || !info[0]->IsFunction()) {
1069         NavigationModel::GetInstance()->SetIsCustomAnimation(false);
1070         return;
1071     }
1072     RefPtr<JsNavigationFunction> jsNavigationFunction =
1073         AceType::MakeRefPtr<JsNavigationFunction>(JSRef<JSFunc>::Cast(info[0]));
1074     auto onNavigationAnimation = [execCtx = info.GetExecutionContext(), func = std::move(jsNavigationFunction)](
1075                                      RefPtr<NG::NavDestinationContext> from, RefPtr<NG::NavDestinationContext> to,
1076                                      NG::NavigationOperation operation) -> NG::NavigationTransition {
1077         NG::NavigationTransition transition;
1078         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, transition);
1079         auto ret = func->Execute(from, to, operation);
1080         if (!ret->IsObject()) {
1081             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "custom transition is invalid, do default animation");
1082             transition.isValid = false;
1083             return transition;
1084         }
1085 
1086         auto transitionObj = JSRef<JSObject>::Cast(ret);
1087         JSRef<JSVal> interactive = transitionObj->GetProperty("isInteractive");
1088         if (interactive->IsBoolean()) {
1089             transition.interactive = interactive->ToBoolean();
1090         } else {
1091             transition.interactive = false;
1092         }
1093         int32_t timeout = -1;
1094         JSRef<JSVal> time = transitionObj->GetProperty("timeout");
1095         if (time->IsNumber()) {
1096             timeout = time->ToNumber<int32_t>();
1097         }
1098         if (!transition.interactive) {
1099             timeout = timeout < 0 ? NAVIGATION_ANIMATION_TIMEOUT : timeout;
1100         }
1101         transition.timeout = timeout;
1102         JSRef<JSVal> transitionContext = transitionObj->GetProperty("transition");
1103         if (!transitionContext->IsFunction()) {
1104             return transition;
1105         }
1106         auto jsOnTransition = AceType::MakeRefPtr<JsNavigationFunction>(JSRef<JSFunc>::Cast(transitionContext));
1107         if (transitionContext->IsFunction()) {
1108             auto onTransition = [execCtx, func = std::move(jsOnTransition)](
1109                                     const RefPtr<NG::NavigationTransitionProxy>& proxy) {
1110                 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1111                 ACE_SCORING_EVENT("transition");
1112                 func->Execute(proxy);
1113             };
1114             transition.transition = std::move(onTransition);
1115         }
1116         JSRef<JSVal> endCallback = transitionObj->GetProperty("onTransitionEnd");
1117         if (endCallback->IsFunction()) {
1118             auto onEndedCallback = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(endCallback));
1119             auto onEndTransition = [execCtx, func = std::move(onEndedCallback)](bool isSuccess) {
1120                 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1121                 ACE_SCORING_EVENT("onTransitionEnded");
1122                 JSRef<JSVal> successVal = JSRef<JSVal>::Make(ToJSValue(isSuccess));
1123                 func->ExecuteJS(1, &successVal);
1124             };
1125             transition.endCallback = std::move(onEndTransition);
1126         }
1127         return transition;
1128     };
1129     NavigationModel::GetInstance()->SetIsCustomAnimation(true);
1130     NavigationModel::GetInstance()->SetCustomTransition(onNavigationAnimation);
1131 }
1132 
SetIgnoreLayoutSafeArea(const JSCallbackInfo & info)1133 void JSNavigation::SetIgnoreLayoutSafeArea(const JSCallbackInfo& info)
1134 {
1135     if (NavigationModel::GetInstance()->UseHomeDestination()) {
1136         return;
1137     }
1138     NG::IgnoreLayoutSafeAreaOpts opts { .type = NG::LAYOUT_SAFE_AREA_TYPE_SYSTEM,
1139         .rawEdges = NG::LAYOUT_SAFE_AREA_EDGE_ALL };
1140     if (info.Length() >= PARAMETER_LENGTH_ONE && info[0]->IsArray()) {
1141         auto paramArray = JSRef<JSArray>::Cast(info[0]);
1142         uint32_t layoutSafeAreaType = NG::LAYOUT_SAFE_AREA_TYPE_NONE;
1143         for (size_t i = 0; i < paramArray->Length(); ++i) {
1144             if (!paramArray->GetValueAt(i)->IsNumber() ||
1145                 paramArray->GetValueAt(i)->ToNumber<uint32_t>() > LAYOUT_SAFE_AREA_TYPE_LIMIT) {
1146                 layoutSafeAreaType = NG::SAFE_AREA_TYPE_SYSTEM;
1147                 break;
1148             }
1149             layoutSafeAreaType |=
1150                 NG::IgnoreLayoutSafeAreaOpts::TypeToMask(paramArray->GetValueAt(i)->ToNumber<uint32_t>());
1151         }
1152         opts.type = layoutSafeAreaType;
1153     }
1154     if (info.Length() >= PARAMETER_LENGTH_TWO && info[1]->IsArray()) {
1155         auto paramArray = JSRef<JSArray>::Cast(info[1]);
1156         uint32_t layoutSafeAreaEdge = NG::LAYOUT_SAFE_AREA_EDGE_NONE;
1157         for (size_t i = 0; i < paramArray->Length(); ++i) {
1158             if (!paramArray->GetValueAt(i)->IsNumber() ||
1159                 paramArray->GetValueAt(i)->ToNumber<uint32_t>() > LAYOUT_SAFE_AREA_EDGE_LIMIT) {
1160                 layoutSafeAreaEdge = NG::LAYOUT_SAFE_AREA_EDGE_ALL;
1161                 break;
1162             }
1163             layoutSafeAreaEdge |=
1164                 NG::IgnoreLayoutSafeAreaOpts::EdgeToMask(paramArray->GetValueAt(i)->ToNumber<uint32_t>());
1165         }
1166         opts.rawEdges = layoutSafeAreaEdge;
1167     }
1168     NavigationModel::GetInstance()->SetIgnoreLayoutSafeArea(opts);
1169 }
1170 
SetSystemBarStyle(const JSCallbackInfo & info)1171 void JSNavigation::SetSystemBarStyle(const JSCallbackInfo& info)
1172 {
1173     if (NavigationModel::GetInstance()->UseHomeDestination()) {
1174         return;
1175     }
1176     RefPtr<SystemBarStyle> style = nullptr;
1177     if (info.Length() == 1 && info[0]->IsObject()) {
1178         auto styleObj = JsConverter::ConvertJsValToNapiValue(info[0]);
1179         auto env = GetCurrentEnv();
1180         if (env) {
1181             style = SystemBarStyle::CreateStyleFromJsObj(env, styleObj);
1182         }
1183     }
1184     NavigationModel::GetInstance()->SetSystemBarStyle(style);
1185 }
1186 
SetRecoverable(const JSCallbackInfo & info)1187 void JSNavigation::SetRecoverable(const JSCallbackInfo& info)
1188 {
1189     if (!info[0]->IsBoolean()) {
1190         // the default value of navigation's recoverable is false
1191         NavigationModel::GetInstance()->SetRecoverable(false);
1192         return;
1193     }
1194     auto recoverable = info[0]->ToBoolean();
1195     NavigationModel::GetInstance()->SetRecoverable(recoverable);
1196 }
1197 
SetEnableDragBar(const JSCallbackInfo & info)1198 void JSNavigation::SetEnableDragBar(const JSCallbackInfo& info)
1199 {
1200     if (!info[0]->IsBoolean()) {
1201         // the default value of navigation's drag bar is false
1202         NavigationModel::GetInstance()->SetEnableDragBar(false);
1203         return;
1204     }
1205     auto enableDragBar = info[0]->ToBoolean();
1206     NavigationModel::GetInstance()->SetEnableDragBar(enableDragBar);
1207 }
1208 } // namespace OHOS::Ace::Framework
1209