• 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_navigation_function.h"
25 #include "bridge/declarative_frontend/engine/js_converter.h"
26 #include "bridge/declarative_frontend/engine/js_ref_ptr.h"
27 #include "bridge/declarative_frontend/engine/js_types.h"
28 #include "bridge/declarative_frontend/jsview/js_nav_path_stack.h"
29 #include "bridge/declarative_frontend/jsview/js_navigation_stack.h"
30 #include "bridge/declarative_frontend/jsview/js_navigation_utils.h"
31 #include "bridge/declarative_frontend/jsview/js_utils.h"
32 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
33 #include "bridge/declarative_frontend/jsview/models/navigation_model_impl.h"
34 #include "core/components_ng/base/view_abstract_model.h"
35 #include "core/components_ng/base/view_stack_model.h"
36 #include "core/components_ng/base/view_stack_processor.h"
37 #include "core/components_ng/pattern/navigation/navigation_declaration.h"
38 #include "core/components_ng/pattern/navigation/navigation_model_data.h"
39 #include "core/components_ng/pattern/navigation/navigation_model_ng.h"
40 #include "core/components_ng/pattern/navigation/navigation_options.h"
41 
42 namespace OHOS::Ace {
43 std::unique_ptr<NavigationModel> NavigationModel::instance_ = nullptr;
44 std::mutex NavigationModel::mutex_;
45 constexpr int32_t NAVIGATION_ANIMATION_TIMEOUT = 1000; // ms
46 
GetInstance()47 NavigationModel* NavigationModel::GetInstance()
48 {
49     if (!instance_) {
50         std::lock_guard<std::mutex> lock(mutex_);
51         if (!instance_) {
52 #ifdef NG_BUILD
53             instance_.reset(new NG::NavigationModelNG());
54 #else
55             if (Container::IsCurrentUseNewPipeline()) {
56                 instance_.reset(new NG::NavigationModelNG());
57             } else {
58                 instance_.reset(new Framework::NavigationModelImpl());
59             }
60 #endif
61         }
62     }
63     return instance_.get();
64 }
65 } // namespace OHOS::Ace
66 
67 namespace OHOS::Ace::Framework {
68 namespace {
69 constexpr int32_t TITLE_MODE_RANGE = 2;
70 constexpr int32_t NAVIGATION_MODE_RANGE = 2;
71 constexpr int32_t NAV_BAR_POSITION_RANGE = 1;
72 constexpr int32_t DEFAULT_NAV_BAR_WIDTH = 240;
73 constexpr Dimension DEFAULT_MIN_CONTENT_WIDTH = 360.0_vp;
74 constexpr uint32_t SAFE_AREA_TYPE_LIMIT = 3;
75 constexpr uint32_t SAFE_AREA_EDGE_LIMIT = 4;
76 constexpr uint32_t SAFE_AREA_EDGE_SYSTEM = 0;
77 constexpr uint32_t SAFE_AREA_EDGE_TOP = 0;
78 constexpr uint32_t SAFE_AREA_EDGE_BOTTOM = 1;
79 constexpr int32_t PARAMETER_LENGTH_ONE  = 1;
80 constexpr int32_t PARAMETER_LENGTH_TWO  = 2;
81 constexpr int32_t FIRST_INDEX  = 0;
82 constexpr int32_t SECOND_INDEX  = 1;
83 constexpr bool ENABLE_TOOLBAR_ADAPTATION_DEFULT = true;
84 constexpr char MORE_BUTTON_OPTIONS_PROPERTY[] = "moreButtonOptions";
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 } // namespace
92 
ParseToolBarItems(const JSCallbackInfo & info,std::list<RefPtr<AceType>> & items)93 void JSNavigation::ParseToolBarItems(const JSCallbackInfo& info, std::list<RefPtr<AceType>>& items)
94 {
95     if (info[0]->IsUndefined()) {
96         return;
97     }
98     JSRef<JSArray> jsArray = JSRef<JSArray>::Cast(info[0]);
99     auto length = jsArray->Length();
100     for (size_t i = 0; i < length; i++) {
101         auto item = jsArray->GetValueAt(i);
102         if (!item->IsObject()) {
103             continue;
104         }
105 
106         auto itemObject = JSRef<JSObject>::Cast(item);
107         auto toolBarItem = AceType::MakeRefPtr<ToolBarItem>();
108         auto itemValueObject = itemObject->GetProperty("value");
109         if (itemValueObject->IsString()) {
110             toolBarItem->value = itemValueObject->ToString();
111         }
112 
113         auto itemIconObject = itemObject->GetProperty("icon");
114         std::string icon;
115         ParseJsMedia(itemIconObject, icon);
116         toolBarItem->icon = icon;
117 
118         auto itemActionValue = itemObject->GetProperty("action");
119         if (itemActionValue->IsFunction()) {
120             auto onClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(itemActionValue));
121             auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
122             toolBarItem->action =
123                 EventMarker([func = std::move(onClickFunc), node = targetNode, execCtx = info.GetExecutionContext()]() {
124                     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
125                     ACE_SCORING_EVENT("Navigation.toolBarItemClick");
126                     PipelineContext::SetCallBackNode(node);
127                     func->Execute();
128                 });
129             auto onClickWithParamFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(itemActionValue));
130             toolBarItem->actionWithParam =
131                 EventMarker([func = std::move(onClickWithParamFunc), node = targetNode,
132                                 execCtx = info.GetExecutionContext()](const BaseEventInfo* info) {
133                     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
134                     ACE_SCORING_EVENT("Navigation.menuItemButtonClick");
135                     PipelineContext::SetCallBackNode(node);
136                     func->Execute();
137                 });
138         }
139         items.push_back(toolBarItem);
140     }
141 }
142 
ParseCommonTitle(const JSRef<JSObject> & jsObj)143 bool JSNavigation::ParseCommonTitle(const JSRef<JSObject>& jsObj)
144 {
145     JSRef<JSVal> subtitle = jsObj->GetProperty("sub");
146     JSRef<JSVal> title = jsObj->GetProperty("main");
147     std::string mainTitle;
148     std::string subTitle;
149     bool hasSub = ParseJsString(subtitle, subTitle);
150     bool hasMain = ParseJsString(title, mainTitle);
151     if (hasSub || hasMain) {
152         return NavigationModel::GetInstance()->ParseCommonTitle(
153             hasSub, hasMain, subTitle, mainTitle);
154     }
155     return false;
156 }
157 
Create(const JSCallbackInfo & info)158 void JSNavigation::Create(const JSCallbackInfo& info)
159 {
160     JSRef<JSObject> newObj;
161     std::string moduleName;
162     std::string pagePath;
163     if (info.Length() == 1) {
164         // input format: navPathStack/pathInfo
165         if (!info[0]->IsObject()) {
166             return;
167         }
168         // instance of NavPathStack
169         JSValueWrapper valueWrapper = info[0].Get().GetLocalHandle();
170         if (!JSNavPathStack::CheckIsValid(valueWrapper)) {
171             // first parameter = pathInfo{'moduleName': stringA, 'pagePath': stringB, 'isUserCreateStack': bool}
172             TAG_LOGE(AceLogTag::ACE_NAVIGATION, "current stack is not navPathStack");
173             auto infoObj = JSRef<JSObject>::Cast(info[0]);
174             if (!infoObj->GetProperty(NG::NAVIGATION_MODULE_NAME)->IsString() ||
175                 !infoObj->GetProperty(NG::NAVIGATION_PAGE_PATH)->IsString()) {
176                 TAG_LOGE(AceLogTag::ACE_NAVIGATION, "current pageInfo is invalid");
177                 return;
178             }
179             moduleName = infoObj->GetProperty(NG::NAVIGATION_MODULE_NAME)->ToString();
180             pagePath = infoObj->GetProperty(NG::NAVIGATION_PAGE_PATH)->ToString();
181         } else {
182             // first parameter = navPathStack
183             newObj = JSRef<JSObject>::Cast(info[0]);
184         }
185     } else if (info.Length() == 2) {
186         // parameter = navPathStack(maybe empty) + pathInfo
187         if (!info[0]->IsObject() || !info[1]->IsObject()) {
188             TAG_LOGE(AceLogTag::ACE_NAVIGATION, "stack or pageInfo is invalid");
189             return;
190         }
191         // instance of NavPathStack
192         JSValueWrapper valueWrapper = info[0].Get().GetLocalHandle();
193         if (!JSNavPathStack::CheckIsValid(valueWrapper)) {
194             TAG_LOGE(AceLogTag::ACE_NAVIGATION, "current stack is not navPathStack");
195             return;
196         }
197         // pathInfo{'moduleName': stringA, 'pagePath': stringB, 'isUserCreateStack': bool}
198         auto infoObj = JSRef<JSObject>::Cast(info[1]);
199         auto isUserCreateStack = infoObj->GetProperty(NG::IS_USER_CREATE_STACK);
200         bool isUserDefined = true;
201         if (isUserCreateStack->IsBoolean()) {
202             isUserDefined = isUserCreateStack->ToBoolean();
203         }
204         if (isUserDefined) {
205             newObj = JSRef<JSObject>::Cast(info[0]);
206         }
207         if (!infoObj->GetProperty(NG::NAVIGATION_MODULE_NAME)->IsString() ||
208             !infoObj->GetProperty(NG::NAVIGATION_PAGE_PATH)->IsString()) {
209             TAG_LOGE(AceLogTag::ACE_NAVIGATION, "current pageInfo is invalid");
210             return;
211         }
212         moduleName = infoObj->GetProperty(NG::NAVIGATION_MODULE_NAME)->ToString();
213         pagePath = infoObj->GetProperty(NG::NAVIGATION_PAGE_PATH)->ToString();
214     }
215 
216     NavigationModel::GetInstance()->Create();
217     auto stackCreator = []() -> RefPtr<JSNavigationStack> { return AceType::MakeRefPtr<JSNavigationStack>(); };
218     auto stackUpdater = [&newObj, &info](RefPtr<NG::NavigationStack> stack) {
219         NavigationModel::GetInstance()->SetNavigationStackProvided(!newObj->IsEmpty());
220         auto jsStack = AceType::DynamicCast<JSNavigationStack>(stack);
221         CHECK_NULL_VOID(jsStack);
222         jsStack->SetJSExecutionContext(info.GetExecutionContext());
223         const auto& oldObj = jsStack->GetDataSourceObj();
224         if (oldObj->IsEmpty()) {
225             if (newObj->IsEmpty()) {
226                 newObj = JSNavPathStack::CreateNewNavPathStackJSObject();
227             }
228             auto nativeObj = JSClass<JSNavPathStack>::NewInstance();
229             JSNavPathStack::SetNativeNavPathStack(newObj, nativeObj);
230             jsStack->SetDataSourceObj(newObj);
231         } else if (!newObj->IsEmpty()) {
232             auto objStrictEqual = [](const JSRef<JSVal>& obja, const JSRef<JSVal>& objb) -> bool {
233                 return obja->GetLocalHandle()->IsStrictEquals(obja->GetEcmaVM(), objb->GetLocalHandle());
234             };
235             if (objStrictEqual(newObj, oldObj)) {
236                 return;
237             }
238             auto nativeObj = JSClass<JSNavPathStack>::NewInstance();
239             JSNavPathStack::SetNativeNavPathStack(newObj, nativeObj);
240             jsStack->SetDataSourceObj(newObj);
241         }
242     };
243     NavigationModel::GetInstance()->SetNavigationStackWithCreatorAndUpdater(stackCreator, stackUpdater);
244     NavigationModel::GetInstance()->SetNavigationPathInfo(moduleName, pagePath);
245 }
246 
JSBind(BindingTarget globalObj)247 void JSNavigation::JSBind(BindingTarget globalObj)
248 {
249     JsNavigationTransitionProxy::JSBind(globalObj);
250     JSClass<JSNavigation>::Declare("Navigation");
251     MethodOptions opt = MethodOptions::NONE;
252     JSClass<JSNavigation>::StaticMethod("create", &JSNavigation::Create);
253     JSClass<JSNavigation>::StaticMethod("title", &JSNavigation::SetTitle, opt);
254     JSClass<JSNavigation>::StaticMethod("subTitle", &JSNavigation::SetSubTitle, opt);
255     JSClass<JSNavigation>::StaticMethod("titleMode", &JSNavigation::SetTitleMode, opt);
256     JSClass<JSNavigation>::StaticMethod("hideTitleBar", &JSNavigation::SetHideTitleBar, opt);
257     JSClass<JSNavigation>::StaticMethod("hideBackButton", &JSNavigation::SetHideBackButton, opt);
258     JSClass<JSNavigation>::StaticMethod("hideToolBar", &JSNavigation::SetHideToolBar, opt);
259     JSClass<JSNavigation>::StaticMethod("toolBar", &JSNavigation::SetToolBar);
260     JSClass<JSNavigation>::StaticMethod("enableToolBarAdaptation", &JSNavigation::SetEnableToolBarAdaptation);
261     JSClass<JSNavigation>::StaticMethod("toolbarConfiguration", &JSNavigation::SetToolbarConfiguration);
262     JSClass<JSNavigation>::StaticMethod("menus", &JSNavigation::SetMenus);
263     JSClass<JSNavigation>::StaticMethod("menuCount", &JSNavigation::SetMenuCount);
264     JSClass<JSNavigation>::StaticMethod("onTitleModeChange", &JSNavigation::SetOnTitleModeChanged);
265     JSClass<JSNavigation>::StaticMethod("onNavigationModeChange", &JSNavigation::SetOnNavigationModeChange);
266     JSClass<JSNavigation>::StaticMethod("mode", &JSNavigation::SetUsrNavigationMode);
267     JSClass<JSNavigation>::StaticMethod("navBarWidth", &JSNavigation::SetNavBarWidth);
268     JSClass<JSNavigation>::StaticMethod("minContentWidth", &JSNavigation::SetMinContentWidth);
269     JSClass<JSNavigation>::StaticMethod("navBarWidthRange", &JSNavigation::SetNavBarWidthRange);
270     JSClass<JSNavigation>::StaticMethod("navBarPosition", &JSNavigation::SetNavBarPosition);
271     JSClass<JSNavigation>::StaticMethod("hideNavBar", &JSNavigation::SetHideNavBar);
272     JSClass<JSNavigation>::StaticMethod("backButtonIcon", &JSNavigation::SetBackButtonIcon);
273     JSClass<JSNavigation>::StaticMethod("onNavBarStateChange", &JSNavigation::SetOnNavBarStateChange);
274     JSClass<JSNavigation>::StaticMethod("navDestination", &JSNavigation::SetNavDestination);
275     JSClass<JSNavigation>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
276     JSClass<JSNavigation>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
277     JSClass<JSNavigation>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
278     JSClass<JSNavigation>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
279     JSClass<JSNavigation>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
280     JSClass<JSNavigation>::StaticMethod("customNavContentTransition", &JSNavigation::SetCustomNavContentTransition);
281     JSClass<JSNavigation>::StaticMethod("ignoreLayoutSafeArea", &JSNavigation::SetIgnoreLayoutSafeArea);
282     JSClass<JSNavigation>::StaticMethod("systemBarStyle", &JSNavigation::SetSystemBarStyle);
283     JSClass<JSNavigation>::StaticMethod("recoverable", &JSNavigation::SetRecoverable);
284     JSClass<JSNavigation>::StaticMethod("enableDragBar", &JSNavigation::SetEnableDragBar);
285     JSClass<JSNavigation>::StaticMethod("enableModeChangeAnimation", &JSNavigation::SetEnableModeChangeAnimation);
286     JSClass<JSNavigation>::InheritAndBind<JSContainerBase>(globalObj);
287 }
288 
SetTitle(const JSCallbackInfo & info)289 void JSNavigation::SetTitle(const JSCallbackInfo& info)
290 {
291     if (info.Length() < 1) {
292         return;
293     }
294     // Resource and string type.
295     std::string title;
296     if (ParseJsString(info[0], title)) {
297         NavigationModel::GetInstance()->ParseCommonTitle(false, true, "", title);
298     } else if (info[0]->IsObject()) {
299         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
300         do {
301             // NavigationCommonTitle
302             if (ParseCommonTitle(jsObj)) {
303                 break;
304             }
305             // CustomBuilder | NavigationCustomTitle
306             CalcDimension titleHeight;
307             if (!jsObj->HasProperty("height")) {
308                 NavigationModel::GetInstance()->SetTitleHeight(titleHeight, false);
309                 break;
310             }
311             JSRef<JSVal> height = jsObj->GetProperty("height");
312             bool isValid = JSContainerBase::ParseJsDimensionVpNG(height, titleHeight);
313             if (height->IsString()) {
314                 std::string heightValue;
315                 ParseJsString(height, heightValue);
316                 if (heightValue == NG::TITLE_MAIN_WITH_SUB) {
317                     NavigationModel::GetInstance()->SetTitleHeight(NG::DOUBLE_LINE_TITLEBAR_HEIGHT);
318                     break;
319                 }
320                 if (heightValue == NG::TITLE_MAIN) {
321                     NavigationModel::GetInstance()->SetTitleHeight(NG::SINGLE_LINE_TITLEBAR_HEIGHT);
322                     break;
323                 }
324             }
325             if (!isValid || titleHeight.Value() < 0) {
326                 NavigationModel::GetInstance()->SetTitleHeight(Dimension(), true);
327                 break;
328             }
329             NavigationModel::GetInstance()->SetTitleHeight(titleHeight);
330         } while (0);
331         JSRef<JSVal> builderObject = jsObj->GetProperty("builder");
332         if (builderObject->IsFunction()) {
333             ViewStackModel::GetInstance()->NewScope();
334             JsFunction jsBuilderFunc(info.This(), JSRef<JSFunc>::Cast(builderObject));
335             ACE_SCORING_EVENT("Navigation.title.builder");
336             jsBuilderFunc.Execute();
337             auto customNode = ViewStackModel::GetInstance()->Finish();
338             NavigationModel::GetInstance()->SetCustomTitle(customNode);
339         }
340     } else {
341         NavigationModel::GetInstance()->ParseCommonTitle(false, false, "", "");
342     }
343 
344     NG::NavigationTitlebarOptions options;
345     JSNavigationUtils::ParseTitleBarOptions(info, true, options);
346     NavigationModel::GetInstance()->SetTitlebarOptions(std::move(options));
347 }
348 
SetTitleMode(int32_t value)349 void JSNavigation::SetTitleMode(int32_t value)
350 {
351     if (value >= 0 && value <= TITLE_MODE_RANGE) {
352         NavigationModel::GetInstance()->SetTitleMode(static_cast<NG::NavigationTitleMode>(value));
353     }
354 }
355 
SetSubTitle(const std::string & subTitle)356 void JSNavigation::SetSubTitle(const std::string& subTitle)
357 {
358     NavigationModel::GetInstance()->SetSubtitle(subTitle);
359 }
360 
SetHideTitleBar(const JSCallbackInfo & info)361 void JSNavigation::SetHideTitleBar(const JSCallbackInfo& info)
362 {
363     bool isHide = false;
364     if (info.Length() > 0 && info[0]->IsBoolean()) {
365         isHide = info[0]->ToBoolean();
366     }
367     bool isAnimated = false;
368     if (info.Length() > 1 && info[1]->IsBoolean()) {
369         isAnimated = info[1]->ToBoolean();
370     }
371     NavigationModel::GetInstance()->SetHideTitleBar(isHide, isAnimated);
372 }
373 
SetEnableToolBarAdaptation(const JSCallbackInfo & info)374 void JSNavigation::SetEnableToolBarAdaptation(const JSCallbackInfo& info)
375 {
376     if (!info[0]->IsBoolean()) {
377         NavigationModel::GetInstance()->SetEnableToolBarAdaptation(ENABLE_TOOLBAR_ADAPTATION_DEFULT);
378         return;
379     }
380     auto enable = info[0]->ToBoolean();
381     NavigationModel::GetInstance()->SetEnableToolBarAdaptation(enable);
382 }
383 
SetEnableModeChangeAnimation(const JSCallbackInfo & info)384 void JSNavigation::SetEnableModeChangeAnimation(const JSCallbackInfo& info)
385 {
386     if (info.Length() < 1) {
387         return;
388     }
389     if (info[0]->IsBoolean()) {
390         NavigationModel::GetInstance()->SetEnableModeChangeAnimation(info[0]->ToBoolean());
391         return;
392     }
393     NavigationModel::GetInstance()->SetEnableModeChangeAnimation(true);
394 }
395 
SetHideNavBar(bool hide)396 void JSNavigation::SetHideNavBar(bool hide)
397 {
398     NavigationModel::GetInstance()->SetHideNavBar(hide);
399 }
400 
SetBackButtonIcon(const JSCallbackInfo & info)401 void JSNavigation::SetBackButtonIcon(const JSCallbackInfo& info)
402 {
403     if (info.Length() < 1) {
404         return;
405     }
406     std::string src;
407     auto noPixMap = ParseJsMedia(info[0], src);
408     auto isValidImage = false;
409     RefPtr<PixelMap> pixMap = nullptr;
410 #if defined(PIXEL_MAP_SUPPORTED)
411     if (!noPixMap) {
412         pixMap = CreatePixelMapFromNapiValue(info[0]);
413     }
414 #endif
415     if (noPixMap || pixMap != nullptr) {
416         isValidImage = true;
417     }
418     std::vector<std::string> nameList;
419     NG::ImageOption imageOption;
420     std::string bundleName;
421     std::string moduleName;
422     GetJsMediaBundleInfo(info[0], bundleName, moduleName);
423     nameList.emplace_back(bundleName);
424     nameList.emplace_back(moduleName);
425     imageOption.noPixMap = noPixMap;
426     imageOption.isValidImage = isValidImage;
427     std::function<void(WeakPtr<NG::FrameNode>)> iconSymbol = nullptr;
428     auto isSymbol = info[0]->IsObject() && src.empty() && pixMap == nullptr;
429     if (isSymbol) {
430         SetSymbolOptionApply(info, iconSymbol, info[0]);
431     }
432     if (info.Length() > 1) {
433         if (!info[1]->IsNull() && !info[1]->IsUndefined()) {
434             std::string backButtonAccessibilityText;
435             ParseJsString(info[1], backButtonAccessibilityText);
436             NavigationModel::GetInstance()->SetBackButtonIcon(iconSymbol, src, imageOption, pixMap, nameList,
437                 true, backButtonAccessibilityText);
438             return;
439         }
440     }
441     NavigationModel::GetInstance()->SetBackButtonIcon(iconSymbol, src, imageOption, pixMap, nameList);
442 }
443 
SetHideBackButton(bool hide)444 void JSNavigation::SetHideBackButton(bool hide)
445 {
446     NavigationModel::GetInstance()->SetHideBackButton(hide);
447 }
448 
SetHideToolBar(const JSCallbackInfo & info)449 void JSNavigation::SetHideToolBar(const JSCallbackInfo& info)
450 {
451     bool isHide = false;
452     if (info.Length() > 0 && info[0]->IsBoolean()) {
453         isHide = info[0]->ToBoolean();
454     }
455     bool isAnimated = false;
456     if (info.Length() > 1 && info[1]->IsBoolean()) {
457         isAnimated = info[1]->ToBoolean();
458     }
459     NavigationModel::GetInstance()->SetHideToolBar(isHide, isAnimated);
460 }
461 
SetToolBar(const JSCallbackInfo & info)462 void JSNavigation::SetToolBar(const JSCallbackInfo& info)
463 {
464     if (info.Length() < 1) {
465         return;
466     }
467     if (!info[0]->IsObject() && !info[0]->IsUndefined()) {
468         return;
469     }
470     if (info[0]->IsUndefined()) {
471         NavigationModel::GetInstance()->SetToolBarItems({});
472         return;
473     }
474     auto builderFuncParam = JSRef<JSObject>::Cast(info[0])->GetProperty("builder");
475     if (builderFuncParam->IsFunction()) {
476         ViewStackModel::GetInstance()->NewScope();
477         JsFunction jsBuilderFunc(builderFuncParam);
478         jsBuilderFunc.Execute();
479         auto customNode = ViewStackModel::GetInstance()->Finish();
480         NavigationModel::GetInstance()->SetCustomToolBar(customNode);
481     }
482 
483     auto itemsValue = JSRef<JSObject>::Cast(info[0])->GetProperty("items");
484     if (!itemsValue->IsObject() || !itemsValue->IsArray()) {
485         return;
486     }
487     if (NavigationModel::GetInstance()->NeedSetItems()) {
488         std::vector<NG::BarItem> toolBarItems;
489         auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
490         JSNavigationUtils::ParseBarItems(targetNode, info, JSRef<JSArray>::Cast(itemsValue), toolBarItems);
491         NavigationModel::GetInstance()->SetToolBarItems(std::move(toolBarItems));
492         return;
493     }
494     std::list<RefPtr<AceType>> items;
495     NavigationModel::GetInstance()->GetToolBarItems(items);
496     ParseToolBarItems(info, items);
497 }
498 
SetToolbarConfiguration(const JSCallbackInfo & info)499 void JSNavigation::SetToolbarConfiguration(const JSCallbackInfo& info)
500 {
501     bool hideText = false;
502     JSNavigationUtils::ParseHideToolBarText(info, hideText);
503     NavigationModel::GetInstance()->SetHideItemText(hideText);
504     if (info[0]->IsUndefined() || info[0]->IsArray()) {
505         if (NavigationModel::GetInstance()->NeedSetItems()) {
506             std::vector<NG::BarItem> toolbarItems;
507             if (info[0]->IsUndefined()) {
508                 toolbarItems = {};
509             } else {
510                 auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
511                 JSNavigationUtils::ParseToolbarItemsConfiguration(
512                     targetNode, info, JSRef<JSArray>::Cast(info[0]), toolbarItems);
513             }
514             NG::MoreButtonOptions toolbarMoreButtonOptions;
515             if (info.Length() > 1) {
516                 auto optObj = JSRef<JSObject>::Cast(info[1]);
517                 auto moreButtonProperty = optObj->GetProperty(MORE_BUTTON_OPTIONS_PROPERTY);
518                 JSNavigationUtils::ParseToolBarMoreButtonOptions(moreButtonProperty, toolbarMoreButtonOptions);
519             }
520             NavigationModel::GetInstance()->SetToolbarMorebuttonOptions(std::move(toolbarMoreButtonOptions));
521             NavigationModel::GetInstance()->SetToolbarConfiguration(std::move(toolbarItems));
522         } else {
523             std::list<RefPtr<AceType>> items;
524             NavigationModel::GetInstance()->GetToolBarItems(items);
525             ParseToolBarItems(info, items);
526         }
527     } else if (info[0]->IsObject()) {
528         auto builderFuncParam = JSRef<JSObject>::Cast(info[0])->GetProperty("builder");
529         if (builderFuncParam->IsFunction()) {
530             ViewStackModel::GetInstance()->NewScope();
531             JsFunction jsBuilderFunc(builderFuncParam);
532             jsBuilderFunc.Execute();
533             auto customNode = ViewStackModel::GetInstance()->Finish();
534             NavigationModel::GetInstance()->SetCustomToolBar(customNode);
535         }
536     }
537 
538     NG::NavigationToolbarOptions options;
539     JSNavigationUtils::ParseToolbarOptions(info, options);
540     NavigationModel::GetInstance()->SetToolbarOptions(std::move(options));
541 }
542 
SetMenus(const JSCallbackInfo & info)543 void JSNavigation::SetMenus(const JSCallbackInfo& info)
544 {
545     if (info.Length() < 1) {
546         return;
547     }
548 
549     NG::NavigationMenuOptions options;
550     if (info.Length() > 1) {
551         auto optObj = JSRef<JSObject>::Cast(info[1]);
552         auto moreButtonProperty = optObj->GetProperty(MORE_BUTTON_OPTIONS_PROPERTY);
553         JSNavigationUtils::ParseMenuOptions(moreButtonProperty, options);
554     }
555     if (info[0]->IsUndefined() || info[0]->IsArray()) {
556         if (NavigationModel::GetInstance()->NeedSetItems()) {
557             std::vector<NG::BarItem> menuItems;
558             if (info[0]->IsUndefined()) {
559                 menuItems = {};
560             } else {
561                 auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
562                 JSNavigationUtils::ParseBarItems(targetNode, info, JSRef<JSArray>::Cast(info[0]), menuItems);
563             }
564             NavigationModel::GetInstance()->SetMenuItems(std::move(menuItems));
565             NavigationModel::GetInstance()->SetMenuOptions(std::move(options));
566             return;
567         }
568         std::list<RefPtr<AceType>> items;
569         NavigationModel::GetInstance()->GetMenuItems(items);
570         ParseToolBarItems(info, items);
571     } else if (info[0]->IsObject()) {
572         auto builderObject = JSRef<JSObject>::Cast(info[0])->GetProperty("builder");
573         if (builderObject->IsFunction()) {
574             ViewStackModel::GetInstance()->NewScope();
575             JsFunction jsBuilderFunc(info.This(), JSRef<JSFunc>::Cast(builderObject));
576             ACE_SCORING_EVENT("Navigation.menu.builder");
577             jsBuilderFunc.Execute();
578             auto customNode = ViewStackModel::GetInstance()->Finish();
579             NavigationModel::GetInstance()->SetCustomMenu(customNode);
580             NavigationModel::GetInstance()->SetMenuOptions(std::move(options));
581         }
582     }
583 }
584 
SetMenuCount(int32_t menuCount)585 void JSNavigation::SetMenuCount(int32_t menuCount)
586 {
587     NavigationModel::GetInstance()->SetMenuCount(menuCount);
588 }
589 
SetOnTitleModeChanged(const JSCallbackInfo & info)590 void JSNavigation::SetOnTitleModeChanged(const JSCallbackInfo& info)
591 {
592     if (info.Length() < 1) {
593         return;
594     }
595     if (info[0]->IsFunction()) {
596         auto onTitleModeChangeCallback =
597             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
598         auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
599         auto onTitleModeChange = [execCtx = info.GetExecutionContext(), func = std::move(onTitleModeChangeCallback),
600                                      node = targetNode](NG::NavigationTitleMode mode) {
601             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
602             ACE_SCORING_EVENT("OnTitleModeChange");
603             PipelineContext::SetCallBackNode(node);
604             JSRef<JSVal> param = JSRef<JSVal>::Make(ToJSValue(mode));
605             func->ExecuteJS(1, &param);
606         };
607         auto changeHandler = AceType::MakeRefPtr<JsEventFunction<NavigationTitleModeChangeEvent, 1>>(
608             JSRef<JSFunc>::Cast(info[0]), TitleModeChangeEventToJSValue);
609         auto eventInfo = [executionContext = info.GetExecutionContext(), func = std::move(changeHandler),
610                              node = targetNode](const BaseEventInfo* baseInfo) {
611             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
612             auto eventInfo = TypeInfoHelper::DynamicCast<NavigationTitleModeChangeEvent>(baseInfo);
613             if (!eventInfo) {
614                 return;
615             }
616             ACE_SCORING_EVENT("Navigation.onTitleModeChanged");
617             PipelineContext::SetCallBackNode(node);
618             func->Execute(*eventInfo);
619         };
620         NavigationModel::GetInstance()->SetOnTitleModeChange(std::move(onTitleModeChange), std::move(eventInfo));
621     }
622     info.ReturnSelf();
623 }
624 
SetUsrNavigationMode(const JSCallbackInfo & info)625 void JSNavigation::SetUsrNavigationMode(const JSCallbackInfo& info)
626 {
627     if (!info[0]->IsNumber()) {
628         NavigationModel::GetInstance()->SetUsrNavigationMode(NG::NavigationMode::AUTO);
629         return;
630     }
631     int32_t value = info[0]->ToNumber<int32_t>();
632     if (value >= 0 && value <= NAVIGATION_MODE_RANGE) {
633         NavigationModel::GetInstance()->SetUsrNavigationMode(static_cast<NG::NavigationMode>(value));
634     }
635 }
636 
SetNavBarPosition(int32_t value)637 void JSNavigation::SetNavBarPosition(int32_t value)
638 {
639     if (value >= 0 && value <= NAV_BAR_POSITION_RANGE) {
640         NavigationModel::GetInstance()->SetNavBarPosition(static_cast<NG::NavBarPosition>(value));
641     }
642 }
643 
ParseNavBarWidthObject(const JSCallbackInfo & info,JSRef<JSVal> arrowFunc,bool isNumber)644 void ParseNavBarWidthObject(const JSCallbackInfo& info, JSRef<JSVal> arrowFunc, bool isNumber)
645 {
646     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(arrowFunc));
647     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
648     auto onChangeEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
649                         node = targetNode, useNumber = isNumber](const Dimension& navBarWidth) {
650         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
651         ACE_SCORING_EVENT("Navigation.onNavBarWidthChangeEvent");
652         PipelineContext::SetCallBackNode(node);
653         auto newJSVal = useNumber ? JSRef<JSVal>::Make(ToJSValue(navBarWidth.ConvertToVp())) :
654             JSRef<JSVal>::Make(ToJSValue(navBarWidth.ToString()));
655         func->ExecuteJS(1, &newJSVal);
656     };
657     NavigationModel::GetInstance()->SetOnNavBarWidthChangeEvent(std::move(onChangeEvent));
658 }
659 
SetNavBarWidth(const JSCallbackInfo & info)660 void JSNavigation::SetNavBarWidth(const JSCallbackInfo& info)
661 {
662     if (info.Length() < 1) {
663         return;
664     }
665 
666     if (info[0]->IsObject()) {
667         JSRef<JSObject> callbackObj = JSRef<JSObject>::Cast(info[0]);
668         CalcDimension value;
669         auto navBarWidthValue = callbackObj->GetProperty("value");
670         auto navBarWidthCallbackValue = callbackObj->GetProperty("$value");
671         auto isValid = JSViewAbstract::ParseJsDimensionVpNG(navBarWidthValue, value);
672         if (value.Value() <= 0) {
673             value.SetValue(DEFAULT_NAV_BAR_WIDTH);
674         }
675         bool isNumber = navBarWidthValue->IsNumber();
676         if (isValid && navBarWidthCallbackValue->IsFunction()) {
677             NavigationModel::GetInstance()->SetNavBarWidth(value, true);
678             ParseNavBarWidthObject(info, navBarWidthCallbackValue, isNumber);
679             return;
680         }
681     }
682 
683     CalcDimension navBarWidth;
684     if (!ParseJsDimensionVp(info[0], navBarWidth)) {
685         return;
686     }
687 
688     if (navBarWidth.Value() <= 0) {
689         navBarWidth.SetValue(DEFAULT_NAV_BAR_WIDTH);
690     }
691 
692     NavigationModel::GetInstance()->SetNavBarWidth(navBarWidth);
693 }
694 
SetMinContentWidth(const JSCallbackInfo & info)695 void JSNavigation::SetMinContentWidth(const JSCallbackInfo& info)
696 {
697     if (info.Length() < 1) {
698         return;
699     }
700 
701     CalcDimension minContentWidth;
702     if (!ParseJsDimensionVp(info[0], minContentWidth)) {
703         NavigationModel::GetInstance()->SetMinContentWidth(DEFAULT_MIN_CONTENT_WIDTH);
704         return;
705     }
706 
707     if (LessNotEqual(minContentWidth.Value(), 0.0)) {
708         minContentWidth = DEFAULT_MIN_CONTENT_WIDTH;
709     }
710 
711     NavigationModel::GetInstance()->SetMinContentWidth(minContentWidth);
712 }
713 
SetNavBarWidthRange(const JSCallbackInfo & info)714 void JSNavigation::SetNavBarWidthRange(const JSCallbackInfo& info)
715 {
716     if (info.Length() < 1) {
717         return;
718     }
719     if (info[0]->IsNull() || info[0]->IsUndefined()) {
720         NavigationModel::GetInstance()->SetMinNavBarWidth(NG::DEFAULT_MIN_NAV_BAR_WIDTH);
721         NavigationModel::GetInstance()->SetMaxNavBarWidth(NG::DEFAULT_MAX_NAV_BAR_WIDTH);
722         return;
723     }
724     if (!info[0]->IsArray()) {
725         return;
726     }
727     auto rangeArray = JSRef<JSArray>::Cast(info[0]);
728     JSRef<JSVal> min = rangeArray->GetValueAt(0);
729     JSRef<JSVal> max = rangeArray->GetValueAt(1);
730 
731     CalcDimension minNavBarWidth;
732     CalcDimension maxNavBarWidth;
733     if (min->IsNull() || min->IsUndefined() || !ParseJsDimensionVp(min, minNavBarWidth)) {
734         minNavBarWidth = NG::DEFAULT_MIN_NAV_BAR_WIDTH;
735     }
736     if (LessNotEqual(minNavBarWidth.Value(), 0.0)) {
737         minNavBarWidth.SetValue(0);
738     }
739     NavigationModel::GetInstance()->SetMinNavBarWidth(minNavBarWidth);
740 
741     if (max->IsNull() || max->IsUndefined() || !ParseJsDimensionVp(max, maxNavBarWidth)) {
742         maxNavBarWidth = NG::DEFAULT_MAX_NAV_BAR_WIDTH;
743     }
744     if (LessNotEqual(maxNavBarWidth.Value(), 0.0)) {
745         maxNavBarWidth.SetValue(0);
746     }
747     NavigationModel::GetInstance()->SetMaxNavBarWidth(maxNavBarWidth);
748 }
749 
SetOnNavBarStateChange(const JSCallbackInfo & info)750 void JSNavigation::SetOnNavBarStateChange(const JSCallbackInfo& info)
751 {
752     if (info.Length() < 1) {
753         return;
754     }
755 
756     if (info[0]->IsFunction()) {
757         auto onNavBarStateChangeCallback =
758             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
759         auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
760         auto onNavBarStateChange = [execCtx = info.GetExecutionContext(), func = std::move(onNavBarStateChangeCallback),
761                                        node = targetNode](bool isVisible) {
762             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
763             ACE_SCORING_EVENT("OnNavBarStateChange");
764             PipelineContext::SetCallBackNode(node);
765             JSRef<JSVal> param = JSRef<JSVal>::Make(ToJSValue(isVisible));
766             func->ExecuteJS(1, &param);
767         };
768         NavigationModel::GetInstance()->SetOnNavBarStateChange(std::move(onNavBarStateChange));
769     }
770     info.ReturnSelf();
771 }
772 
SetNavDestination(const JSCallbackInfo & info)773 void JSNavigation::SetNavDestination(const JSCallbackInfo& info)
774 {
775     if (info.Length() < 1) {
776         return;
777     }
778 
779     if (!info[0]->IsObject()) {
780         return;
781     }
782 
783     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
784     auto builder = obj->GetProperty("builder");
785     if (!builder->IsFunction()) {
786         return;
787     }
788 
789     auto navigationStack = NavigationModel::GetInstance()->GetNavigationStack();
790     auto jsNavigationStack = AceType::DynamicCast<JSNavigationStack>(navigationStack);
791     if (jsNavigationStack) {
792         jsNavigationStack->SetNavDestBuilderFunc(JSRef<JSFunc>::Cast(builder));
793     }
794 }
795 
SetOnNavigationModeChange(const JSCallbackInfo & info)796 void JSNavigation::SetOnNavigationModeChange(const JSCallbackInfo& info)
797 {
798     if (info.Length() < 1) {
799         return;
800     }
801     if (!info[0]->IsFunction()) {
802         info.ReturnSelf();
803         return;
804     }
805     auto onModeChangeCallback = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
806     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
807     auto onModeChange = [execCtx = info.GetExecutionContext(), func = std::move(onModeChangeCallback),
808                             node = targetNode](NG::NavigationMode mode) {
809         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
810         ACE_SCORING_EVENT("OnNavigationModeChange");
811         PipelineContext::SetCallBackNode(node);
812         JSRef<JSVal> param = JSRef<JSVal>::Make(ToJSValue(static_cast<int8_t>(mode)));
813         func->ExecuteJS(1, &param);
814     };
815     NavigationModel::GetInstance()->SetOnNavigationModeChange(std::move(onModeChange));
816     info.ReturnSelf();
817 }
818 
SetCustomNavContentTransition(const JSCallbackInfo & info)819 void JSNavigation::SetCustomNavContentTransition(const JSCallbackInfo& info)
820 {
821     if (info.Length() == 0 || !info[0]->IsFunction()) {
822         NavigationModel::GetInstance()->SetIsCustomAnimation(false);
823         return;
824     }
825     RefPtr<JsNavigationFunction> jsNavigationFunction =
826         AceType::MakeRefPtr<JsNavigationFunction>(JSRef<JSFunc>::Cast(info[0]));
827     auto onNavigationAnimation = [execCtx = info.GetExecutionContext(), func = std::move(jsNavigationFunction)](
828                                      RefPtr<NG::NavDestinationContext> from, RefPtr<NG::NavDestinationContext> to,
829                                      NG::NavigationOperation operation) -> NG::NavigationTransition {
830         NG::NavigationTransition transition;
831         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, transition);
832         auto ret = func->Execute(from, to, operation);
833         if (!ret->IsObject()) {
834             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "custom transition is invalid, do default animation");
835             transition.isValid = false;
836             return transition;
837         }
838 
839         auto transitionObj = JSRef<JSObject>::Cast(ret);
840         JSRef<JSVal> interactive = transitionObj->GetProperty("isInteractive");
841         if (interactive->IsBoolean()) {
842             transition.interactive = interactive->ToBoolean();
843         } else {
844             transition.interactive = false;
845         }
846         int32_t timeout = -1;
847         JSRef<JSVal> time = transitionObj->GetProperty("timeout");
848         if (time->IsNumber()) {
849             timeout = time->ToNumber<int32_t>();
850         }
851         if (!transition.interactive) {
852             timeout = timeout < 0 ? NAVIGATION_ANIMATION_TIMEOUT : timeout;
853         }
854         transition.timeout = timeout;
855         JSRef<JSVal> transitionContext = transitionObj->GetProperty("transition");
856         if (!transitionContext->IsFunction()) {
857             return transition;
858         }
859         auto jsOnTransition = AceType::MakeRefPtr<JsNavigationFunction>(JSRef<JSFunc>::Cast(transitionContext));
860         if (transitionContext->IsFunction()) {
861             auto onTransition = [execCtx, func = std::move(jsOnTransition)](
862                                     const RefPtr<NG::NavigationTransitionProxy>& proxy) {
863                 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
864                 ACE_SCORING_EVENT("transition");
865                 func->Execute(proxy);
866             };
867             transition.transition = std::move(onTransition);
868         }
869         JSRef<JSVal> endCallback = transitionObj->GetProperty("onTransitionEnd");
870         if (endCallback->IsFunction()) {
871             auto onEndedCallback = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(endCallback));
872             auto onEndTransition = [execCtx, func = std::move(onEndedCallback)](bool isSuccess) {
873                 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
874                 ACE_SCORING_EVENT("onTransitionEnded");
875                 JSRef<JSVal> successVal = JSRef<JSVal>::Make(ToJSValue(isSuccess));
876                 func->ExecuteJS(1, &successVal);
877             };
878             transition.endCallback = std::move(onEndTransition);
879         }
880         return transition;
881     };
882     NavigationModel::GetInstance()->SetIsCustomAnimation(true);
883     NavigationModel::GetInstance()->SetCustomTransition(onNavigationAnimation);
884 }
885 
SetIgnoreLayoutSafeArea(const JSCallbackInfo & info)886 void JSNavigation::SetIgnoreLayoutSafeArea(const JSCallbackInfo& info)
887 {
888     NG::SafeAreaExpandOpts opts { .type = NG::SAFE_AREA_TYPE_SYSTEM, .edges = NG::SAFE_AREA_EDGE_ALL};
889     if (info.Length() >= PARAMETER_LENGTH_ONE && info[FIRST_INDEX]->IsArray()) {
890         auto paramArray = JSRef<JSArray>::Cast(info[0]);
891         uint32_t safeAreaType = NG::SAFE_AREA_TYPE_NONE;
892         for (size_t i = 0; i < paramArray->Length(); ++i) {
893             auto value = paramArray->GetValueAt(i);
894             if (!value->IsNumber() ||
895                 value->ToNumber<uint32_t>() >= SAFE_AREA_TYPE_LIMIT ||
896                 value->ToNumber<uint32_t>() == SAFE_AREA_EDGE_SYSTEM) {
897                 safeAreaType = NG::SAFE_AREA_TYPE_SYSTEM;
898                 break;
899             }
900         }
901         opts.type = safeAreaType;
902     }
903 
904     if (info.Length() >= PARAMETER_LENGTH_TWO && info[SECOND_INDEX]->IsArray()) {
905         auto paramArray = JSRef<JSArray>::Cast(info[1]);
906         uint32_t safeAreaEdge = NG::SAFE_AREA_EDGE_NONE;
907         for (size_t i = 0; i < paramArray->Length(); ++i) {
908             auto value = paramArray->GetValueAt(i);
909             if (!value->IsNumber() ||
910                 value->ToNumber<uint32_t>() >= SAFE_AREA_EDGE_LIMIT) {
911                 safeAreaEdge = NG::SAFE_AREA_EDGE_ALL;
912                 break;
913             }
914             if (value->ToNumber<uint32_t>() == SAFE_AREA_EDGE_TOP ||
915                 value->ToNumber<uint32_t>() == SAFE_AREA_EDGE_BOTTOM) {
916                     safeAreaEdge |= (1 << value->ToNumber<uint32_t>());
917                 }
918         }
919         opts.edges = safeAreaEdge;
920     }
921     NavigationModel::GetInstance()->SetIgnoreLayoutSafeArea(opts);
922 }
923 
SetSystemBarStyle(const JSCallbackInfo & info)924 void JSNavigation::SetSystemBarStyle(const JSCallbackInfo& info)
925 {
926     RefPtr<SystemBarStyle> style = nullptr;
927     if (info.Length() == 1 && info[0]->IsObject()) {
928         auto styleObj = JsConverter::ConvertJsValToNapiValue(info[0]);
929         auto env = GetCurrentEnv();
930         if (env) {
931             style = SystemBarStyle::CreateStyleFromJsObj(env, styleObj);
932         }
933     }
934     NavigationModel::GetInstance()->SetSystemBarStyle(style);
935 }
936 
SetRecoverable(const JSCallbackInfo & info)937 void JSNavigation::SetRecoverable(const JSCallbackInfo& info)
938 {
939     if (!info[0]->IsBoolean()) {
940         // the default value of navigation's recoverable is false
941         NavigationModel::GetInstance()->SetRecoverable(false);
942         return;
943     }
944     auto recoverable = info[0]->ToBoolean();
945     NavigationModel::GetInstance()->SetRecoverable(recoverable);
946 }
947 
SetEnableDragBar(const JSCallbackInfo & info)948 void JSNavigation::SetEnableDragBar(const JSCallbackInfo& info)
949 {
950     if (!info[0]->IsBoolean()) {
951         // the default value of navigation's drag bar is false
952         NavigationModel::GetInstance()->SetEnableDragBar(false);
953         return;
954     }
955     auto enableDragBar = info[0]->ToBoolean();
956     NavigationModel::GetInstance()->SetEnableDragBar(enableDragBar);
957 }
958 } // namespace OHOS::Ace::Framework
959