• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 "bridge/declarative_frontend/engine/functions/js_click_function.h"
23 #include "bridge/declarative_frontend/engine/js_ref_ptr.h"
24 #include "bridge/declarative_frontend/engine/js_types.h"
25 #include "bridge/declarative_frontend/jsview/js_navigation_stack.h"
26 #include "bridge/declarative_frontend/jsview/js_utils.h"
27 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
28 #include "bridge/declarative_frontend/jsview/models/navigation_model_impl.h"
29 #include "core/components_ng/base/view_stack_model.h"
30 #include "core/components_ng/pattern/navigation/navigation_model_data.h"
31 #include "core/components_ng/pattern/navigation/navigation_model_ng.h"
32 #include "core/components_ng/pattern/navigation/navigation_declaration.h"
33 
34 namespace OHOS::Ace {
35 std::unique_ptr<NavigationModel> NavigationModel::instance_ = nullptr;
36 std::mutex NavigationModel::mutex_;
37 
GetInstance()38 NavigationModel* NavigationModel::GetInstance()
39 {
40     if (!instance_) {
41         std::lock_guard<std::mutex> lock(mutex_);
42         if (!instance_) {
43 #ifdef NG_BUILD
44             instance_.reset(new NG::NavigationModelNG());
45 #else
46             if (Container::IsCurrentUseNewPipeline()) {
47                 instance_.reset(new NG::NavigationModelNG());
48             } else {
49                 instance_.reset(new Framework::NavigationModelImpl());
50             }
51 #endif
52         }
53     }
54     return instance_.get();
55 }
56 } // namespace OHOS::Ace
57 
58 namespace OHOS::Ace::Framework {
59 namespace {
60 constexpr int32_t TITLE_MODE_RANGE = 2;
61 constexpr int32_t NAVIGATION_MODE_RANGE = 2;
62 constexpr int32_t NAV_BAR_POSITION_RANGE = 1;
63 constexpr int32_t DEFAULT_NAV_BAR_WIDTH = 240;
64 constexpr Dimension DEFAULT_MIN_CONTENT_WIDTH = 360.0_vp;
65 
TitleModeChangeEventToJSValue(const NavigationTitleModeChangeEvent & eventInfo)66 JSRef<JSVal> TitleModeChangeEventToJSValue(const NavigationTitleModeChangeEvent& eventInfo)
67 {
68     return JSRef<JSVal>::Make(ToJSValue(eventInfo.IsMiniBar() ? static_cast<int32_t>(NavigationTitleMode::MINI)
69                                                               : static_cast<int32_t>(NavigationTitleMode::FULL)));
70 }
71 
72 } // namespace
73 
ParseToolBarItems(const JSRef<JSArray> & jsArray,std::list<RefPtr<AceType>> & items)74 void JSNavigation::ParseToolBarItems(const JSRef<JSArray>& jsArray, std::list<RefPtr<AceType>>& items)
75 {
76     auto length = jsArray->Length();
77     for (size_t i = 0; i < length; i++) {
78         auto item = jsArray->GetValueAt(i);
79         if (!item->IsObject()) {
80             LOGE("tool bar item is not object");
81             continue;
82         }
83 
84         auto itemObject = JSRef<JSObject>::Cast(item);
85         auto toolBarItem = AceType::MakeRefPtr<ToolBarItem>();
86         auto itemValueObject = itemObject->GetProperty("value");
87         if (itemValueObject->IsString()) {
88             toolBarItem->value = itemValueObject->ToString();
89         }
90 
91         auto itemIconObject = itemObject->GetProperty("icon");
92         std::string icon;
93         if (!ParseJsMedia(itemIconObject, icon)) {
94             LOGE("iconValue is null");
95         }
96         toolBarItem->icon = icon;
97 
98         auto itemActionValue = itemObject->GetProperty("action");
99         if (itemActionValue->IsFunction()) {
100             auto onClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(itemActionValue));
101             toolBarItem->action = EventMarker([func = std::move(onClickFunc)]() {
102                 ACE_SCORING_EVENT("Navigation.toolBarItemClick");
103                 func->Execute();
104             });
105             auto onClickWithParamFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(itemActionValue));
106             toolBarItem->actionWithParam =
107                 EventMarker([func = std::move(onClickWithParamFunc)](const BaseEventInfo* info) {
108                     ACE_SCORING_EVENT("Navigation.menuItemButtonClick");
109                     func->Execute();
110                 });
111         }
112         items.push_back(toolBarItem);
113     }
114 }
115 
ParseBarItems(const JSCallbackInfo & info,const JSRef<JSArray> & jsArray,std::vector<NG::BarItem> & items)116 void JSNavigation::ParseBarItems(
117     const JSCallbackInfo& info, const JSRef<JSArray>& jsArray, std::vector<NG::BarItem>& items)
118 {
119     auto length = jsArray->Length();
120     for (size_t i = 0; i < length; i++) {
121         auto item = jsArray->GetValueAt(i);
122         if (!item->IsObject()) {
123             LOGE("tool bar item is not object");
124             continue;
125         }
126         auto itemObject = JSRef<JSObject>::Cast(item);
127         NG::BarItem toolBarItem;
128         auto itemValueObject = itemObject->GetProperty("value");
129         if (itemValueObject->IsString()) {
130             toolBarItem.text = itemValueObject->ToString();
131         }
132 
133         auto itemIconObject = itemObject->GetProperty("icon");
134         if (itemIconObject->IsString()) {
135             toolBarItem.icon = itemIconObject->ToString();
136         }
137 
138         auto itemActionValue = itemObject->GetProperty("action");
139         if (itemActionValue->IsFunction()) {
140             RefPtr<JsFunction> onClickFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(itemActionValue));
141             auto onItemClick = [execCtx = info.GetExecutionContext(), func = std::move(onClickFunc)]() {
142                 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
143                 if (func) {
144                     func->ExecuteJS();
145                 }
146             };
147             toolBarItem.action = onItemClick;
148         }
149         items.push_back(toolBarItem);
150     }
151 }
152 
ParseToolbarItemsConfiguration(const JSCallbackInfo & info,const JSRef<JSArray> & jsArray,std::vector<NG::BarItem> & items)153 void JSNavigation::ParseToolbarItemsConfiguration(
154     const JSCallbackInfo& info, const JSRef<JSArray>& jsArray, std::vector<NG::BarItem>& items)
155 {
156     auto length = jsArray->Length();
157     for (size_t i = 0; i < length; i++) {
158         auto item = jsArray->GetValueAt(i);
159         if (!item->IsObject()) {
160             continue;
161         }
162         NG::BarItem toolBarItem;
163         std::string text;
164         std::string icon;
165         std::string activeIcon;
166 
167         auto itemObject = JSRef<JSObject>::Cast(item);
168         auto itemValueObject = itemObject->GetProperty("value");
169         if (ParseJsString(itemValueObject, text)) {
170             toolBarItem.text = text;
171         }
172 
173         auto itemIconObject = itemObject->GetProperty("icon");
174         if (ParseJsMedia(itemIconObject, icon)) {
175             toolBarItem.icon = icon;
176         }
177 
178         auto itemActionValue = itemObject->GetProperty("action");
179         if (itemActionValue->IsFunction()) {
180             RefPtr<JsFunction> onClickFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(itemActionValue));
181             auto onItemClick = [execCtx = info.GetExecutionContext(), func = std::move(onClickFunc)]() {
182                 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
183                 if (func) {
184                     func->ExecuteJS();
185                 }
186             };
187             toolBarItem.action = onItemClick;
188         }
189 
190         auto itemStatusValue = itemObject->GetProperty("status");
191         if (itemStatusValue->IsNumber()) {
192             toolBarItem.status = static_cast<NG::NavToolbarItemStatus>(itemStatusValue->ToNumber<int32_t>());
193         }
194 
195         auto itemActiveIconObject = itemObject->GetProperty("activeIcon");
196         if (ParseJsMedia(itemActiveIconObject, activeIcon)) {
197             toolBarItem.activeIcon = activeIcon;
198         }
199 
200         items.push_back(toolBarItem);
201     }
202 }
203 
ParseCommonTitle(const JSRef<JSVal> & jsValue)204 bool JSNavigation::ParseCommonTitle(const JSRef<JSVal>& jsValue)
205 {
206     bool isCommonTitle = false;
207     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
208     JSRef<JSVal> subtitle = jsObj->GetProperty("sub");
209     JSRef<JSVal> title = jsObj->GetProperty("main");
210     bool sub = subtitle->IsString();
211     bool main = title->IsString();
212     if (subtitle->IsString() || title->IsString()) {
213         NavigationModel::GetInstance()->ParseCommonTitle(
214             sub, main, subtitle->ToString(), title->ToString());
215     }
216     return isCommonTitle;
217 }
218 
Create(const JSCallbackInfo & info)219 void JSNavigation::Create(const JSCallbackInfo& info)
220 {
221     if (info.Length() <= 0) {
222         NavigationModel::GetInstance()->Create();
223         NavigationModel::GetInstance()->SetNavigationStack();
224         return;
225     }
226     if (!info[0]->IsObject()) {
227         return;
228     }
229     auto obj = JSRef<JSObject>::Cast(info[0]);
230     auto value = obj->GetProperty("type");
231     if (value->ToString() != "NavPathStack") {
232         return;
233     }
234 
235     NavigationModel::GetInstance()->Create();
236     auto navigationStack = AceType::MakeRefPtr<JSNavigationStack>();
237     navigationStack->SetDataSourceObj(obj);
238     NavigationModel::GetInstance()->SetNavigationStackProvided(true);
239     NavigationModel::GetInstance()->SetNavigationStack(std::move(navigationStack));
240 }
241 
JSBind(BindingTarget globalObj)242 void JSNavigation::JSBind(BindingTarget globalObj)
243 {
244     JSClass<JSNavigation>::Declare("Navigation");
245     MethodOptions opt = MethodOptions::NONE;
246     JSClass<JSNavigation>::StaticMethod("create", &JSNavigation::Create);
247     JSClass<JSNavigation>::StaticMethod("title", &JSNavigation::SetTitle, opt);
248     JSClass<JSNavigation>::StaticMethod("subTitle", &JSNavigation::SetSubTitle, opt);
249     JSClass<JSNavigation>::StaticMethod("titleMode", &JSNavigation::SetTitleMode, opt);
250     JSClass<JSNavigation>::StaticMethod("hideTitleBar", &JSNavigation::SetHideTitleBar, opt);
251     JSClass<JSNavigation>::StaticMethod("hideBackButton", &JSNavigation::SetHideBackButton, opt);
252     JSClass<JSNavigation>::StaticMethod("hideToolBar", &JSNavigation::SetHideToolBar, opt);
253     JSClass<JSNavigation>::StaticMethod("toolBar", &JSNavigation::SetToolBar);
254     JSClass<JSNavigation>::StaticMethod("toolbarConfiguration", &JSNavigation::SetToolbarConfiguration);
255     JSClass<JSNavigation>::StaticMethod("menus", &JSNavigation::SetMenus);
256     JSClass<JSNavigation>::StaticMethod("menuCount", &JSNavigation::SetMenuCount);
257     JSClass<JSNavigation>::StaticMethod("onTitleModeChange", &JSNavigation::SetOnTitleModeChanged);
258     JSClass<JSNavigation>::StaticMethod("mode", &JSNavigation::SetUsrNavigationMode);
259     JSClass<JSNavigation>::StaticMethod("navBarWidth", &JSNavigation::SetNavBarWidth);
260     JSClass<JSNavigation>::StaticMethod("minContentWidth", &JSNavigation::SetMinContentWidth);
261     JSClass<JSNavigation>::StaticMethod("navBarWidthRange", &JSNavigation::SetNavBarWidthRange);
262     JSClass<JSNavigation>::StaticMethod("navBarPosition", &JSNavigation::SetNavBarPosition);
263     JSClass<JSNavigation>::StaticMethod("hideNavBar", &JSNavigation::SetHideNavBar);
264     JSClass<JSNavigation>::StaticMethod("backButtonIcon", &JSNavigation::SetBackButtonIcon);
265     JSClass<JSNavigation>::StaticMethod("onNavBarStateChange", &JSNavigation::SetOnNavBarStateChange);
266     JSClass<JSNavigation>::StaticMethod("navDestination", &JSNavigation::SetNavDestination);
267     JSClass<JSNavigation>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
268     JSClass<JSNavigation>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
269     JSClass<JSNavigation>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
270     JSClass<JSNavigation>::InheritAndBind<JSContainerBase>(globalObj);
271 }
272 
SetTitle(const JSCallbackInfo & info)273 void JSNavigation::SetTitle(const JSCallbackInfo& info)
274 {
275     if (info.Length() < 1) {
276         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
277         return;
278     }
279     if (info[0]->IsString() || info[0]->IsUndefined()) {
280         std::string title;
281         if (info[0]->IsUndefined()) {
282             title = "";
283         } else {
284             title = info[0]->ToString();
285         }
286         NavigationModel::GetInstance()->SetTitle(title);
287     } else if (info[0]->IsObject()) {
288         if (ParseCommonTitle(info[0])) {
289             return;
290         }
291         std::string title;
292         if (ParseJsString(info[0], title)) {
293             NavigationModel::GetInstance()->SetTitle(title);
294         }
295         // CustomBuilder | NavigationCustomTitle
296         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
297         JSRef<JSVal> builderObject = jsObj->GetProperty("builder");
298         if (builderObject->IsFunction()) {
299             ViewStackModel::GetInstance()->NewScope();
300             JsFunction jsBuilderFunc(info.This(), JSRef<JSObject>::Cast(builderObject));
301             ACE_SCORING_EVENT("Navigation.title.builder");
302             jsBuilderFunc.Execute();
303             auto customNode = ViewStackModel::GetInstance()->Finish();
304             NavigationModel::GetInstance()->SetCustomTitle(customNode);
305         }
306 
307         JSRef<JSVal> height = jsObj->GetProperty("height");
308         if (height->IsNumber()) {
309             if (height->ToNumber<int32_t>() == 0) {
310                 NavigationModel::GetInstance()->SetTitleHeight(NG::FULL_SINGLE_LINE_TITLEBAR_HEIGHT);
311                 return;
312             }
313             if (height->ToNumber<int32_t>() == 1) {
314                 NavigationModel::GetInstance()->SetTitleHeight(NG::FULL_DOUBLE_LINE_TITLEBAR_HEIGHT);
315                 return;
316             }
317             CalcDimension titleHeight;
318             if (!JSContainerBase::ParseJsDimensionVp(height, titleHeight) || titleHeight.Value() < 0) {
319                 return;
320             }
321             NavigationModel::GetInstance()->SetTitleHeight(titleHeight);
322         } else {
323             CalcDimension titleHeight;
324             if (!JSContainerBase::ParseJsDimensionVp(height, titleHeight) || titleHeight.Value() <= 0) {
325                 return;
326             }
327             NavigationModel::GetInstance()->SetTitleHeight(titleHeight);
328         }
329     } else {
330         LOGE("arg is not [String|Function].");
331     }
332 }
333 
SetTitleMode(int32_t value)334 void JSNavigation::SetTitleMode(int32_t value)
335 {
336     if (value >= 0 && value <= TITLE_MODE_RANGE) {
337         NavigationModel::GetInstance()->SetTitleMode(static_cast<NG::NavigationTitleMode>(value));
338     } else {
339         LOGE("invalid value for titleMode");
340     }
341 }
342 
SetSubTitle(const std::string & subTitle)343 void JSNavigation::SetSubTitle(const std::string& subTitle)
344 {
345     NavigationModel::GetInstance()->SetSubtitle(subTitle);
346 }
347 
SetHideTitleBar(bool hide)348 void JSNavigation::SetHideTitleBar(bool hide)
349 {
350     NavigationModel::GetInstance()->SetHideTitleBar(hide);
351 }
352 
SetHideNavBar(bool hide)353 void JSNavigation::SetHideNavBar(bool hide)
354 {
355     NavigationModel::GetInstance()->SetHideNavBar(hide);
356 }
357 
SetBackButtonIcon(const JSCallbackInfo & info)358 void JSNavigation::SetBackButtonIcon(const JSCallbackInfo& info)
359 {
360     if (info.Length() < 1) {
361         LOGE("The arg is wrong, it is supposed to have at least 1 arguments");
362         return;
363     }
364     std::string src;
365     auto noPixMap = ParseJsMedia(info[0], src);
366 
367     RefPtr<PixelMap> pixMap = nullptr;
368 #if defined(PIXEL_MAP_SUPPORTED)
369     if (!noPixMap) {
370         pixMap = CreatePixelMapFromNapiValue(info[0]);
371     }
372 #endif
373     NavigationModel::GetInstance()->SetBackButtonIcon(src, noPixMap, pixMap);
374 }
375 
SetHideBackButton(bool hide)376 void JSNavigation::SetHideBackButton(bool hide)
377 {
378     NavigationModel::GetInstance()->SetHideBackButton(hide);
379 }
380 
SetHideToolBar(bool hide)381 void JSNavigation::SetHideToolBar(bool hide)
382 {
383     NavigationModel::GetInstance()->SetHideToolBar(hide);
384 }
385 
SetToolBar(const JSCallbackInfo & info)386 void JSNavigation::SetToolBar(const JSCallbackInfo& info)
387 {
388     if (info.Length() < 1) {
389         LOGE("The arg is wrong, it is supposed to have at least one argument");
390         return;
391     }
392     if (!info[0]->IsObject() && !info[0]->IsUndefined()) {
393         LOGE("arg is not a object or is not undefined.");
394         return;
395     }
396     if (info[0]->IsUndefined()) {
397         NavigationModel::GetInstance()->SetToolBarItems({});
398         return;
399     }
400     auto builderFuncParam = JSRef<JSObject>::Cast(info[0])->GetProperty("builder");
401     if (builderFuncParam->IsFunction()) {
402         ViewStackModel::GetInstance()->NewScope();
403         JsFunction jsBuilderFunc(builderFuncParam);
404         jsBuilderFunc.Execute();
405         auto customNode = ViewStackModel::GetInstance()->Finish();
406         NavigationModel::GetInstance()->SetCustomToolBar(customNode);
407     }
408 
409     auto itemsValue = JSRef<JSObject>::Cast(info[0])->GetProperty("items");
410     if (!itemsValue->IsObject() || !itemsValue->IsArray()) {
411         LOGE("arg format error: not find items");
412         return;
413     }
414     if (NavigationModel::GetInstance()->NeedSetItems()) {
415         std::vector<NG::BarItem> toolBarItems;
416         ParseBarItems(info, JSRef<JSArray>::Cast(itemsValue), toolBarItems);
417         NavigationModel::GetInstance()->SetToolBarItems(std::move(toolBarItems));
418         return;
419     }
420     std::list<RefPtr<AceType>> items;
421     NavigationModel::GetInstance()->GetToolBarItems(items);
422     ParseToolBarItems(JSRef<JSArray>::Cast(itemsValue), items);
423 }
424 
SetToolbarConfiguration(const JSCallbackInfo & info)425 void JSNavigation::SetToolbarConfiguration(const JSCallbackInfo& info)
426 {
427     if (info[0]->IsUndefined() || info[0]->IsArray()) {
428         if (NavigationModel::GetInstance()->NeedSetItems()) {
429             std::vector<NG::BarItem> toolbarItems;
430             if (info[0]->IsUndefined()) {
431                 toolbarItems = {};
432             } else {
433                 ParseToolbarItemsConfiguration(info, JSRef<JSArray>::Cast(info[0]), toolbarItems);
434             }
435             NavigationModel::GetInstance()->SetToolbarConfiguration(std::move(toolbarItems));
436             return;
437         }
438         std::list<RefPtr<AceType>> items;
439         NavigationModel::GetInstance()->GetToolBarItems(items);
440         ParseToolBarItems(JSRef<JSArray>::Cast(info[0]), items);
441     } else if (info[0]->IsObject()) {
442         auto builderFuncParam = JSRef<JSObject>::Cast(info[0])->GetProperty("builder");
443         if (builderFuncParam->IsFunction()) {
444             ViewStackModel::GetInstance()->NewScope();
445             JsFunction jsBuilderFunc(builderFuncParam);
446             jsBuilderFunc.Execute();
447             auto customNode = ViewStackModel::GetInstance()->Finish();
448             NavigationModel::GetInstance()->SetCustomToolBar(customNode);
449         }
450     }
451 }
452 
SetMenus(const JSCallbackInfo & info)453 void JSNavigation::SetMenus(const JSCallbackInfo& info)
454 {
455     if (info.Length() < 1) {
456         LOGE("The arg is wrong, it is supposed to have at least one argument");
457         return;
458     }
459 
460     if (info[0]->IsUndefined() || info[0]->IsArray()) {
461         if (NavigationModel::GetInstance()->NeedSetItems()) {
462             std::vector<NG::BarItem> menuItems;
463             if (info[0]->IsUndefined()) {
464                 menuItems = {};
465             } else {
466                 ParseBarItems(info, JSRef<JSArray>::Cast(info[0]), menuItems);
467             }
468             NavigationModel::GetInstance()->SetMenuItems(std::move(menuItems));
469             return;
470         }
471         std::list<RefPtr<AceType>> items;
472         NavigationModel::GetInstance()->GetMenuItems(items);
473         ParseToolBarItems(JSRef<JSArray>::Cast(info[0]), items);
474     } else if (info[0]->IsObject()) {
475         auto builderObject = JSRef<JSObject>::Cast(info[0])->GetProperty("builder");
476         if (builderObject->IsFunction()) {
477             ViewStackModel::GetInstance()->NewScope();
478             JsFunction jsBuilderFunc(info.This(), JSRef<JSObject>::Cast(builderObject));
479             ACE_SCORING_EVENT("Navigation.menu.builder");
480             jsBuilderFunc.Execute();
481             auto customNode = ViewStackModel::GetInstance()->Finish();
482             NavigationModel::GetInstance()->SetCustomMenu(customNode);
483         }
484     } else {
485         LOGE("arg is not [String|Function].");
486     }
487 }
488 
SetMenuCount(int32_t menuCount)489 void JSNavigation::SetMenuCount(int32_t menuCount)
490 {
491     NavigationModel::GetInstance()->SetMenuCount(menuCount);
492 }
493 
SetOnTitleModeChanged(const JSCallbackInfo & info)494 void JSNavigation::SetOnTitleModeChanged(const JSCallbackInfo& info)
495 {
496     if (info.Length() < 1) {
497         LOGE("The arg is wrong, it is supposed to have at least one argument");
498         return;
499     }
500     if (info[0]->IsFunction()) {
501         auto onTitleModeChangeCallback =
502             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
503         auto onTitleModeChange = [execCtx = info.GetExecutionContext(), func = std::move(onTitleModeChangeCallback)](
504             NG::NavigationTitleMode mode) {
505             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
506             ACE_SCORING_EVENT("OnTitleModeChange");
507             JSRef<JSVal> param = JSRef<JSVal>::Make(ToJSValue(mode));
508             func->ExecuteJS(1, &param);
509         };
510         auto changeHandler = AceType::MakeRefPtr<JsEventFunction<NavigationTitleModeChangeEvent, 1>>(
511             JSRef<JSFunc>::Cast(info[0]), TitleModeChangeEventToJSValue);
512         auto eventInfo = [executionContext = info.GetExecutionContext(), func = std::move(changeHandler)](
513             const BaseEventInfo* baseInfo) {
514             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
515             auto eventInfo = TypeInfoHelper::DynamicCast<NavigationTitleModeChangeEvent>(baseInfo);
516             if (!eventInfo) {
517                 LOGE("HandleChangeEvent eventInfo == nullptr");
518                 return;
519             }
520             ACE_SCORING_EVENT("Navigation.onTitleModeChanged");
521             func->Execute(*eventInfo);
522         };
523         NavigationModel::GetInstance()->SetOnTitleModeChange(std::move(onTitleModeChange), std::move(eventInfo));
524     }
525     info.ReturnSelf();
526 }
527 
SetUsrNavigationMode(int32_t value)528 void JSNavigation::SetUsrNavigationMode(int32_t value)
529 {
530     if (value >= 0 && value <= NAVIGATION_MODE_RANGE) {
531         NavigationModel::GetInstance()->SetUsrNavigationMode(static_cast<NG::NavigationMode>(value));
532     } else {
533         LOGE("invalid value for navigationMode");
534     }
535 }
536 
SetNavBarPosition(int32_t value)537 void JSNavigation::SetNavBarPosition(int32_t value)
538 {
539     if (value >= 0 && value <= NAV_BAR_POSITION_RANGE) {
540         NavigationModel::GetInstance()->SetNavBarPosition(static_cast<NG::NavBarPosition>(value));
541     } else {
542         LOGE("invalid value for navBarPosition");
543     }
544 }
545 
SetNavBarWidth(const JSCallbackInfo & info)546 void JSNavigation::SetNavBarWidth(const JSCallbackInfo& info)
547 {
548     if (info.Length() < 1) {
549         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
550         return;
551     }
552 
553     CalcDimension navBarWidth;
554     if (!ParseJsDimensionVp(info[0], navBarWidth)) {
555         return;
556     }
557 
558     if (navBarWidth.Value() <= 0) {
559         navBarWidth.SetValue(DEFAULT_NAV_BAR_WIDTH);
560     }
561 
562     NavigationModel::GetInstance()->SetNavBarWidth(navBarWidth);
563 }
564 
SetMinContentWidth(const JSCallbackInfo & info)565 void JSNavigation::SetMinContentWidth(const JSCallbackInfo& info)
566 {
567     if (info.Length() < 1) {
568         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
569         return;
570     }
571 
572     CalcDimension minContentWidth;
573     if (!ParseJsDimensionVp(info[0], minContentWidth)) {
574         NavigationModel::GetInstance()->SetMinContentWidth(DEFAULT_MIN_CONTENT_WIDTH);
575         return;
576     }
577 
578     if (LessNotEqual(minContentWidth.Value(), 0.0)) {
579         minContentWidth = DEFAULT_MIN_CONTENT_WIDTH;
580     }
581 
582     NavigationModel::GetInstance()->SetMinContentWidth(minContentWidth);
583 }
584 
SetNavBarWidthRange(const JSCallbackInfo & info)585 void JSNavigation::SetNavBarWidthRange(const JSCallbackInfo& info)
586 {
587 
588     if (info.Length() < 1) {
589         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
590         return;
591     }
592     if (!info[0]->IsArray()) {
593         return;
594     }
595     auto rangeArray = JSRef<JSArray>::Cast(info[0]);
596     JSRef<JSVal> min = rangeArray->GetValueAt(0);
597     JSRef<JSVal> max = rangeArray->GetValueAt(1);
598 
599     CalcDimension minNavBarWidth;
600 
601     CalcDimension maxNavBarWidth;
602     ParseJsDimensionVp(min, minNavBarWidth);
603     ParseJsDimensionVp(max, maxNavBarWidth);
604 
605     if (LessNotEqual(minNavBarWidth.Value(), 0.0)) {
606         minNavBarWidth.SetValue(0);
607     }
608     NavigationModel::GetInstance()->SetMinNavBarWidth(minNavBarWidth);
609 
610     if (LessNotEqual(maxNavBarWidth.Value(), 0.0)) {
611         maxNavBarWidth.SetValue(0);
612     }
613     NavigationModel::GetInstance()->SetMaxNavBarWidth(maxNavBarWidth);
614 
615 }
616 
SetOnNavBarStateChange(const JSCallbackInfo & info)617 void JSNavigation::SetOnNavBarStateChange(const JSCallbackInfo& info)
618 {
619     if (info.Length() < 1) {
620         LOGE("The arg is wrong, it is supposed to have at least one argument");
621         return;
622     }
623 
624     if (info[0]->IsFunction()) {
625         auto onNavBarStateChangeCallback =
626             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
627         auto onNavBarStateChange = [execCtx = info.GetExecutionContext(),
628             func = std::move(onNavBarStateChangeCallback)](bool isVisible) {
629             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
630             ACE_SCORING_EVENT("OnNavBarStateChange");
631             JSRef<JSVal> param = JSRef<JSVal>::Make(ToJSValue(isVisible));
632             func->ExecuteJS(1, &param);
633         };
634         NavigationModel::GetInstance()->SetOnNavBarStateChange(std::move(onNavBarStateChange));
635     }
636     info.ReturnSelf();
637 }
638 
SetNavDestination(const JSCallbackInfo & info)639 void JSNavigation::SetNavDestination(const JSCallbackInfo& info)
640 {
641     if (info.Length() < 1) {
642         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
643         return;
644     }
645 
646     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
647     auto builder = obj->GetProperty("builder");
648     if (!builder->IsFunction()) {
649         LOGE("JSNavigation::SetNavDestination builder param is not a function.");
650         return;
651     }
652 
653     auto navigationStack = NavigationModel::GetInstance()->GetNavigationStack();
654     auto jsNavigationStack = AceType::DynamicCast<JSNavigationStack>(navigationStack);
655     if (jsNavigationStack) {
656         jsNavigationStack->SetJSExecutionContext(info.GetExecutionContext());
657         jsNavigationStack->SetNavDestBuilderFunc(JSRef<JSFunc>::Cast(builder));
658     }
659 }
660 } // namespace OHOS::Ace::Framework
661