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, ¶m);
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, ¶m);
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