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