1 /*
2  * Copyright (c) 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_navdestination.h"
17 
18 #include "base/log/ace_scoring_log.h"
19 #include "base/memory/ace_type.h"
20 #include "base/utils/utils.h"
21 #include "base/system_bar/system_bar_style.h"
22 #include "bridge/declarative_frontend/engine/functions/js_function.h"
23 #include "bridge/declarative_frontend/engine/js_converter.h"
24 #include "bridge/declarative_frontend/engine/js_execution_scope_defines.h"
25 #include "bridge/declarative_frontend/engine/js_ref_ptr.h"
26 #include "bridge/declarative_frontend/engine/js_types.h"
27 #include "bridge/declarative_frontend/jsview/js_navdestination_context.h"
28 #include "bridge/declarative_frontend/jsview/js_navigation.h"
29 #include "bridge/declarative_frontend/jsview/js_navigation_utils.h"
30 #include "bridge/declarative_frontend/jsview/js_utils.h"
31 #include "core/components_ng/base/view_stack_model.h"
32 #include "core/components_ng/base/view_stack_processor.h"
33 #include "core/components_ng/pattern/navigation/navigation_options.h"
34 #include "core/components_ng/pattern/navrouter/navdestination_model_ng.h"
35 
36 namespace OHOS::Ace {
37 std::unique_ptr<NavDestinationModel> NavDestinationModel::instance_ = nullptr;
38 std::mutex NavDestinationModel::mutex_;
39 
GetInstance()40 NavDestinationModel* NavDestinationModel::GetInstance()
41 {
42     if (!instance_) {
43         std::lock_guard<std::mutex> lock(mutex_);
44         instance_.reset(new NG::NavDestinationModelNG());
45     }
46     return instance_.get();
47 }
48 
49 } // namespace OHOS::Ace
50 
51 namespace OHOS::Ace::Framework {
52 
53 namespace {
54 constexpr uint32_t SAFE_AREA_TYPE_LIMIT = 3;
55 constexpr uint32_t SAFE_AREA_EDGE_LIMIT = 4;
56 constexpr uint32_t SAFE_AREA_EDGE_SYSTEM = 0;
57 constexpr uint32_t SAFE_AREA_EDGE_TOP = 0;
58 constexpr uint32_t SAFE_AREA_EDGE_BOTTOM = 1;
59 constexpr int32_t PARAMATER_LENGTH_ONE = 1;
60 constexpr int32_t PARAMATER_LENGTH_TWO = 2;
61 constexpr uint32_t FIRST_INDEX = 0;
62 constexpr uint32_t SECOND_INDEX = 1;
63 
ParseCommonTitle(const JSRef<JSObject>& jsObj)64 bool ParseCommonTitle(const JSRef<JSObject>& jsObj)
65 {
66     JSRef<JSVal> subtitle = jsObj->GetProperty("sub");
67     JSRef<JSVal> title = jsObj->GetProperty("main");
68     std::string mainTitle;
69     std::string subTitle;
70     bool hasSub = JSViewAbstract::ParseJsString(subtitle, subTitle);
71     bool hasMain = JSViewAbstract::ParseJsString(title, mainTitle);
72     if (hasSub || hasMain) {
73         return NG::NavDestinationModelNG::GetInstance()->ParseCommonTitle(
74             hasSub, hasMain, subTitle, mainTitle);
75     }
76     return false;
77 }
78 
79 } // namespace
80 
Create()81 void JSNavDestination::Create()
82 {
83     NavDestinationModel::GetInstance()->Create();
84 }
85 
Create(const JSCallbackInfo& info)86 void JSNavDestination::Create(const JSCallbackInfo& info)
87 {
88     if (info.Length() <= 0) {
89         NavDestinationModel::GetInstance()->Create();
90         return;
91     }
92 
93     std::string moduleName;
94     std::string pagePath;
95     if (info.Length() == 1) {
96         // input format: builder/pathInfo
97         if (info[0]->IsFunction()) {
98             // first parameter = builder
99             auto builderFunctionJS = info[0];
100             auto builderFunc = [context = info.GetExecutionContext(), builder = std::move(builderFunctionJS)]() {
101                 JAVASCRIPT_EXECUTION_SCOPE(context)
102                 JSRef<JSFunc>::Cast(builder)->Call(JSRef<JSObject>());
103             };
104             auto ctx = AceType::MakeRefPtr<NG::NavDestinationContext>();
105             auto navPathInfo = AceType::MakeRefPtr<JSNavPathInfo>();
106             ctx->SetNavPathInfo(navPathInfo);
107             NavDestinationModel::GetInstance()->Create(std::move(builderFunc), std::move(ctx));
108             return;
109         } else if (info[0]->IsObject()) {
110             // first parameter = pathInfo{'moduleName': stringA, 'pagePath': stringB}
111             auto infoObj = JSRef<JSObject>::Cast(info[0]);
112             if (!infoObj->GetProperty(NG::NAVIGATION_MODULE_NAME)->IsString() ||
113                 !infoObj->GetProperty(NG::NAVIGATION_PAGE_PATH)->IsString()) {
114                 TAG_LOGE(AceLogTag::ACE_NAVIGATION, "navDestination current pageInfo is invalid");
115                 return;
116             }
117             moduleName = infoObj->GetProperty(NG::NAVIGATION_MODULE_NAME)->ToString();
118             pagePath = infoObj->GetProperty(NG::NAVIGATION_PAGE_PATH)->ToString();
119             NavDestinationModel::GetInstance()->Create();
120             NavDestinationModel::GetInstance()->SetNavDestinationPathInfo(moduleName, pagePath);
121             return;
122         }
123         TAG_LOGE(AceLogTag::ACE_NAVIGATION,
124             "current input info is neither buildFunction or navDestination usefulInfo");
125         return;
126     } else if (info.Length() == 2) {
127         // parameter = builder(maybe empty) + pathInfo
128         if (!info[0]->IsFunction() || !info[1]->IsObject()) {
129             TAG_LOGE(AceLogTag::ACE_NAVIGATION, "buider or pageInfo is invalid");
130             return;
131         }
132         auto builderFunctionJS = info[0];
133         auto builderFunc = [context = info.GetExecutionContext(), builder = std::move(builderFunctionJS)]() {
134             JAVASCRIPT_EXECUTION_SCOPE(context)
135             JSRef<JSFunc>::Cast(builder)->Call(JSRef<JSObject>());
136         };
137         auto ctx = AceType::MakeRefPtr<NG::NavDestinationContext>();
138         auto navPathInfo = AceType::MakeRefPtr<JSNavPathInfo>();
139         ctx->SetNavPathInfo(navPathInfo);
140 
141         auto infoObj = JSRef<JSObject>::Cast(info[1]);
142         if (!infoObj->GetProperty(NG::NAVIGATION_MODULE_NAME)->IsString() ||
143             !infoObj->GetProperty(NG::NAVIGATION_PAGE_PATH)->IsString()) {
144             TAG_LOGE(AceLogTag::ACE_NAVIGATION, "navDestination current pageInfo is invalid");
145             return;
146         }
147         moduleName = infoObj->GetProperty(NG::NAVIGATION_MODULE_NAME)->ToString();
148         pagePath = infoObj->GetProperty(NG::NAVIGATION_PAGE_PATH)->ToString();
149         NavDestinationModel::GetInstance()->Create(std::move(builderFunc), std::move(ctx));
150         NavDestinationModel::GetInstance()->SetNavDestinationPathInfo(moduleName, pagePath);
151     }
152 }
153 
SetHideTitleBar(const JSCallbackInfo& info)154 void JSNavDestination::SetHideTitleBar(const JSCallbackInfo& info)
155 {
156     bool isHide = false;
157     if (info.Length() > 0 && info[0]->IsBoolean()) {
158         isHide = info[0]->ToBoolean();
159     }
160     bool isAnimated = false;
161     if (info.Length() > 1 && info[1]->IsBoolean()) {
162         isAnimated = info[1]->ToBoolean();
163     }
164     NavDestinationModel::GetInstance()->SetHideTitleBar(isHide, isAnimated);
165 }
166 
SetTitle(const JSCallbackInfo& info)167 void JSNavDestination::SetTitle(const JSCallbackInfo& info)
168 {
169     // Resource and string type.
170     std::string title;
171     if (ParseJsString(info[0], title)) {
172         NavDestinationModel::GetInstance()->ParseCommonTitle(false, true, "", title);
173     } else if (info[0]->IsObject()) {
174         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
175         do {
176             // NavigationCommonTitle
177             if (ParseCommonTitle(jsObj)) {
178                 break;
179             }
180             // CustomBuilder | NavigationCustomTitle
181             CalcDimension titleHeight;
182             if (!jsObj->HasProperty("height")) {
183                 NavDestinationModel::GetInstance()->SetTitleHeight(titleHeight, false);
184                 break;
185             }
186             JSRef<JSVal> height = jsObj->GetProperty("height");
187             bool isValid = JSContainerBase::ParseJsDimensionVpNG(height, titleHeight);
188             if (height->IsString()) {
189                 std::string heightValue;
190                 ParseJsString(height, heightValue);
191                 if (heightValue == NG::TITLE_MAIN_WITH_SUB) {
192                     NavDestinationModel::GetInstance()->SetTitleHeight(NG::DOUBLE_LINE_TITLEBAR_HEIGHT);
193                     break;
194                 }
195                 if (heightValue == NG::TITLE_MAIN) {
196                     NavDestinationModel::GetInstance()->SetTitleHeight(NG::SINGLE_LINE_TITLEBAR_HEIGHT);
197                     break;
198                 }
199             }
200             if (!isValid || titleHeight.Value() < 0) {
201                 NavDestinationModel::GetInstance()->SetTitleHeight(Dimension(), true);
202                 break;
203             }
204             NavDestinationModel::GetInstance()->SetTitleHeight(titleHeight);
205         } while (0);
206         JSRef<JSVal> builderObject = jsObj->GetProperty("builder");
207         if (builderObject->IsFunction()) {
208             ViewStackModel::GetInstance()->NewScope();
209             JsFunction jsBuilderFunc(info.This(), JSRef<JSFunc>::Cast(builderObject));
210             ACE_SCORING_EVENT("Navdestination.title.builder");
211             jsBuilderFunc.Execute();
212             auto customNode = ViewStackModel::GetInstance()->Finish();
213             NavDestinationModel::GetInstance()->SetCustomTitle(customNode);
214         }
215     } else {
216         NavDestinationModel::GetInstance()->ParseCommonTitle(false, false, "", "");
217     }
218 
219     NG::NavigationTitlebarOptions options;
220     JSNavigationUtils::ParseTitleBarOptions(info, false, options);
221     NavDestinationModel::GetInstance()->SetTitlebarOptions(std::move(options));
222 }
223 
SetBackButtonIcon(const JSCallbackInfo& info)224 void JSNavDestination::SetBackButtonIcon(const JSCallbackInfo& info)
225 {
226     // srcType、pixmap、string
227     if (info.Length() < 1) {
228         return;
229     }
230     std::string src;
231     auto noPixMap = ParseJsMedia(info[0], src);
232 
233     RefPtr<PixelMap> pixMap = nullptr;
234     auto isValidImage = false;
235 #if defined(PIXEL_MAP_SUPPORTED)
236     if (!noPixMap) {
237         pixMap = CreatePixelMapFromNapiValue(info[0]);
238     }
239 #endif
240     if (noPixMap || pixMap != nullptr) {
241         isValidImage = true;
242     }
243     std::vector<std::string> nameList;
244     NG::ImageOption imageOption;
245     std::string bundleName;
246     std::string moduleName;
247     GetJsMediaBundleInfo(info[0], bundleName, moduleName);
248     nameList.emplace_back(bundleName);
249     nameList.emplace_back(moduleName);
250     imageOption.noPixMap = noPixMap;
251     imageOption.isValidImage = isValidImage;
252     std::function<void(WeakPtr<NG::FrameNode>)> iconSymbol = nullptr;
253     auto isSymbol = info[0]->IsObject() && src.empty() && pixMap == nullptr;
254     if (isSymbol) {
255         SetSymbolOptionApply(info, iconSymbol, info[0]);
256     }
257 
258     NavDestinationModel::GetInstance()->SetBackButtonIcon(iconSymbol, src, imageOption, pixMap, nameList);
259 }
260 
SetOnShown(const JSCallbackInfo& info)261 void JSNavDestination::SetOnShown(const JSCallbackInfo& info)
262 {
263     if (!info[0]->IsFunction()) {
264         return;
265     }
266 
267     auto onShownCallback = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
268     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
269     auto onShown = [execCtx = info.GetExecutionContext(), func = std::move(onShownCallback), node = targetNode]() {
270         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
271         ACE_SCORING_EVENT("NavDestination.onShown");
272         PipelineContext::SetCallBackNode(node);
273         JSRef<JSVal> params[1];
274         params[0] = JSRef<JSVal>::Make(ToJSValue("undefined"));
275         func->ExecuteJS(1, params);
276     };
277     NavDestinationModel::GetInstance()->SetOnShown(std::move(onShown));
278     info.ReturnSelf();
279 }
280 
SetOnHidden(const JSCallbackInfo& info)281 void JSNavDestination::SetOnHidden(const JSCallbackInfo& info)
282 {
283     if (!info[0]->IsFunction()) {
284         return;
285     }
286     auto onHiddenCallback = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
287     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
288     auto onHidden = [execCtx = info.GetExecutionContext(), func = std::move(onHiddenCallback), node = targetNode]() {
289         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
290         ACE_SCORING_EVENT("NavDestination.onHidden");
291         PipelineContext::SetCallBackNode(node);
292         func->ExecuteJS();
293     };
294     NavDestinationModel::GetInstance()->SetOnHidden(std::move(onHidden));
295     info.ReturnSelf();
296 }
297 
SetOnBackPressed(const JSCallbackInfo& info)298 void JSNavDestination::SetOnBackPressed(const JSCallbackInfo& info)
299 {
300     if (!info[0]->IsFunction()) {
301         return;
302     }
303     auto onBackPressedCallback = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
304     auto onBackPressed = [execCtx = info.GetExecutionContext(), func = std::move(onBackPressedCallback)]() -> bool {
305         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, false);
306         ACE_SCORING_EVENT("NavDestination.onBackPressed");
307         return (func->ExecuteJS())->ToBoolean();
308     };
309     NavDestinationModel::GetInstance()->SetOnBackPressed(std::move(onBackPressed));
310     info.ReturnSelf();
311 }
312 
SetOnReady(const JSCallbackInfo& info)313 void JSNavDestination::SetOnReady(const JSCallbackInfo& info)
314 {
315     if (!info[0]->IsFunction()) {
316         return;
317     }
318     auto onReadyCallback = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
319     auto onReady = [execCtx = info.GetExecutionContext(), func = std::move(onReadyCallback)](
320                        RefPtr<NG::NavDestinationContext> context) {
321         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
322         auto jsContext = JSClass<JSNavDestinationContext>::NewInstance();
323         auto jsNavDestinationContext = Referenced::Claim(jsContext->Unwrap<JSNavDestinationContext>());
324         CHECK_NULL_VOID(jsNavDestinationContext);
325         jsNavDestinationContext->SetNavDestinationContext(context);
326         ACE_SCORING_EVENT("NavDestination.onReady");
327         JSRef<JSVal> params[1];
328         params[0] = jsContext;
329         func->ExecuteJS(1, params);
330     };
331     NavDestinationModel::GetInstance()->SetOnReady(std::move(onReady));
332     info.ReturnSelf();
333 }
334 
SetMode(const JSCallbackInfo& info)335 void JSNavDestination::SetMode(const JSCallbackInfo& info)
336 {
337     if (!info[0]->IsNumber()) {
338         // set default back ground color
339         NavDestinationModel::GetInstance()->SetNavDestinationMode(NG::NavDestinationMode::STANDARD);
340         return;
341     }
342     auto mode = info[0]->ToNumber<int32_t>();
343     NavDestinationModel::GetInstance()->SetNavDestinationMode(static_cast<NG::NavDestinationMode>(mode));
344 }
345 
SetMenus(const JSCallbackInfo& info)346 void JSNavDestination::SetMenus(const JSCallbackInfo& info)
347 {
348     if (info.Length() < 1) {
349         return;
350     }
351 
352     if (info[0]->IsUndefined() || info[0]->IsArray()) {
353         std::vector<NG::BarItem> menuItems;
354         if (info[0]->IsUndefined()) {
355             menuItems = {};
356         } else {
357             auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
358             JSNavigationUtils::ParseBarItems(targetNode, info, JSRef<JSArray>::Cast(info[0]), menuItems);
359         }
360         NavDestinationModel::GetInstance()->SetMenuItems(std::move(menuItems));
361         return;
362     } else if (info[0]->IsObject()) {
363         auto builderObject = JSRef<JSObject>::Cast(info[0])->GetProperty("builder");
364         if (builderObject->IsFunction()) {
365             ViewStackModel::GetInstance()->NewScope();
366             JsFunction jsBuilderFunc(info.This(), JSRef<JSObject>::Cast(builderObject));
367             ACE_SCORING_EVENT("NavDestiNation.menu.builder");
368             jsBuilderFunc.Execute();
369             auto customNode = ViewStackModel::GetInstance()->Finish();
370             NavDestinationModel::GetInstance()->SetCustomMenu(customNode);
371         }
372     }
373 }
374 
SetBackgroundColor(const JSCallbackInfo& info)375 void JSNavDestination::SetBackgroundColor(const JSCallbackInfo& info)
376 {
377     Color backgroundColor;
378     bool isValid = ParseJsColor(info[0], backgroundColor);
379 
380     NavDestinationModel::GetInstance()->SetBackgroundColor(backgroundColor, isValid);
381 }
382 
SetWillAppear(const JSCallbackInfo& info)383 void JSNavDestination::SetWillAppear(const JSCallbackInfo& info)
384 {
385     if (!info[0]->IsFunction()) {
386         return;
387     }
388 
389     auto willAppear = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
390     auto onWillAppear = [execCtx = info.GetExecutionContext(), func = std::move(willAppear)]() {
391         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
392         ACE_SCORING_EVENT("NavDestination.WillAppear");
393         func->ExecuteJS();
394     };
395     NavDestinationModel::GetInstance()->SetOnWillAppear(std::move(onWillAppear));
396     info.ReturnSelf();
397 }
398 
SetWillHide(const JSCallbackInfo& info)399 void JSNavDestination::SetWillHide(const JSCallbackInfo& info)
400 {
401     if (!info[0]->IsFunction()) {
402         return;
403     }
404 
405     auto willHideCallback = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
406     auto onWillHide = [execCtx = info.GetExecutionContext(), func = std::move(willHideCallback)]() {
407         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
408         ACE_SCORING_EVENT("NavDestination.WillHide");
409         func->ExecuteJS();
410     };
411     NavDestinationModel::GetInstance()->SetOnWillHide(std::move(onWillHide));
412     info.ReturnSelf();
413 }
414 
SetWillShow(const JSCallbackInfo& info)415 void JSNavDestination::SetWillShow(const JSCallbackInfo& info)
416 {
417     if (!info[0]->IsFunction()) {
418         return;
419     }
420 
421     auto willShowCallback = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
422     auto onWillShow = [execCtx = info.GetExecutionContext(), func = std::move(willShowCallback)]() {
423         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
424         ACE_SCORING_EVENT("NavDestination.WillShow");
425         func->ExecuteJS();
426     };
427     NavDestinationModel::GetInstance()->SetOnWillShow(std::move(onWillShow));
428     info.ReturnSelf();
429 }
430 
SetWillDisAppear(const JSCallbackInfo& info)431 void JSNavDestination::SetWillDisAppear(const JSCallbackInfo& info)
432 {
433     if (!info[0]->IsFunction()) {
434         return;
435     }
436 
437     auto WillDisAppear = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
438     auto onWillDisAppear = [execCtx = info.GetExecutionContext(), func = std::move(WillDisAppear)]() {
439         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
440         ACE_SCORING_EVENT("NavDestination.WillDisAppear");
441         func->ExecuteJS();
442     };
443     NavDestinationModel::GetInstance()->SetOnWillDisAppear(std::move(onWillDisAppear));
444     info.ReturnSelf();
445 }
446 
SetIgnoreLayoutSafeArea(const JSCallbackInfo& info)447 void JSNavDestination::SetIgnoreLayoutSafeArea(const JSCallbackInfo& info)
448 {
449     NG::SafeAreaExpandOpts opts { .type = NG::SAFE_AREA_TYPE_SYSTEM, .edges = NG::SAFE_AREA_EDGE_ALL};
450     if (info.Length() >= PARAMATER_LENGTH_ONE && info[FIRST_INDEX]->IsArray()) {
451         auto paramArray = JSRef<JSArray>::Cast(info[0]);
452         uint32_t safeAreaType = NG::SAFE_AREA_TYPE_NONE;
453         for (size_t i = 0; i < paramArray->Length(); ++i) {
454             auto value = paramArray->GetValueAt(i);
455             if (!value->IsNumber() ||
456                 value->ToNumber<uint32_t>() >= SAFE_AREA_TYPE_LIMIT ||
457                 value->ToNumber<uint32_t>() == SAFE_AREA_EDGE_SYSTEM) {
458                 safeAreaType = NG::SAFE_AREA_TYPE_SYSTEM;
459                 break;
460             }
461         }
462         opts.type = safeAreaType;
463     }
464 
465     if (info.Length() >= PARAMATER_LENGTH_TWO && info[SECOND_INDEX]->IsArray()) {
466         auto paramArray = JSRef<JSArray>::Cast(info[1]);
467         uint32_t safeAreaEdge = NG::SAFE_AREA_EDGE_NONE;
468         for (size_t i = 0; i < paramArray->Length(); ++i) {
469             auto value = paramArray->GetValueAt(i);
470             if (!value->IsNumber() ||
471                 value->ToNumber<uint32_t>() >= SAFE_AREA_EDGE_LIMIT) {
472                 safeAreaEdge = NG::SAFE_AREA_EDGE_ALL;
473                 break;
474             }
475             if (value->ToNumber<uint32_t>() == SAFE_AREA_EDGE_TOP ||
476                 value->ToNumber<uint32_t>() == SAFE_AREA_EDGE_BOTTOM) {
477                     safeAreaEdge |= (1 << value->ToNumber<uint32_t>());
478                 }
479         }
480         opts.edges = safeAreaEdge;
481     }
482     NavDestinationModel::GetInstance()->SetIgnoreLayoutSafeArea(opts);
483 }
484 
SetRecoverable(const JSCallbackInfo& info)485 void JSNavDestination::SetRecoverable(const JSCallbackInfo& info)
486 {
487     if (!info[0]->IsBoolean()) {
488         // the default value of navDestination's recoverable is true
489         NavDestinationModel::GetInstance()->SetRecoverable(true);
490         return;
491     }
492     auto recoverable = info[0]->ToBoolean();
493     NavDestinationModel::GetInstance()->SetRecoverable(recoverable);
494 }
495 
SetToolBarConfiguration(const JSCallbackInfo& info)496 void JSNavDestination::SetToolBarConfiguration(const JSCallbackInfo& info)
497 {
498     if (info[0]->IsUndefined() || info[0]->IsArray()) {
499         std::vector<NG::BarItem> toolBarItems;
500         if (info[0]->IsArray()) {
501             auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
502             JSNavigationUtils::ParseToolbarItemsConfiguration(
503                 targetNode, info, JSRef<JSArray>::Cast(info[0]), toolBarItems);
504         }
505         NavDestinationModel::GetInstance()->SetToolbarConfiguration(std::move(toolBarItems));
506     } else if (info[0]->IsObject()) {
507         auto builderFuncParam = JSRef<JSObject>::Cast(info[0])->GetProperty("builder");
508         if (builderFuncParam->IsFunction()) {
509             ViewStackModel::GetInstance()->NewScope();
510             JsFunction jsBuilderFunc(builderFuncParam);
511             jsBuilderFunc.Execute();
512             auto customNode = ViewStackModel::GetInstance()->Finish();
513             NavDestinationModel::GetInstance()->SetCustomToolBar(customNode);
514         }
515     }
516     NG::NavigationToolbarOptions options;
517     JSNavigationUtils::ParseToolbarOptions(info, options);
518     NavDestinationModel::GetInstance()->SetToolBarOptions(std::move(options));
519 }
520 
SetHideToolBar(const JSCallbackInfo& info)521 void JSNavDestination::SetHideToolBar(const JSCallbackInfo& info)
522 {
523     bool isHide = false;
524     if (info.Length() > 0 && info[0]->IsBoolean()) {
525         isHide = info[0]->ToBoolean();
526     }
527     bool isAnimated = false;
528     if (info.Length() > 1 && info[1]->IsBoolean()) {
529         isAnimated = info[1]->ToBoolean();
530     }
531     NavDestinationModel::GetInstance()->SetHideToolBar(isHide, isAnimated);
532 }
533 
JSBind(BindingTarget globalObj)534 void JSNavDestination::JSBind(BindingTarget globalObj)
535 {
536     JSNavDestinationContext::JSBind(globalObj);
537     JSClass<JSNavDestination>::Declare("NavDestination");
538     JSClass<JSNavDestination>::StaticMethod("create", &JSNavDestination::Create);
539     JSClass<JSNavDestination>::StaticMethod("title", &JSNavDestination::SetTitle);
540     JSClass<JSNavDestination>::StaticMethod("hideTitleBar", &JSNavDestination::SetHideTitleBar);
541     JSClass<JSNavDestination>::StaticMethod("backButtonIcon", &JSNavDestination::SetBackButtonIcon);
542     JSClass<JSNavDestination>::StaticMethod("backgroundColor", &JSNavDestination::SetBackgroundColor);
543     JSClass<JSNavDestination>::StaticMethod("onShown", &JSNavDestination::SetOnShown);
544     JSClass<JSNavDestination>::StaticMethod("onHidden", &JSNavDestination::SetOnHidden);
545     JSClass<JSNavDestination>::StaticMethod("onBackPressed", &JSNavDestination::SetOnBackPressed);
546     JSClass<JSNavDestination>::StaticMethod("onReady", &JSNavDestination::SetOnReady);
547     JSClass<JSNavDestination>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
548     JSClass<JSNavDestination>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
549     JSClass<JSNavDestination>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
550     JSClass<JSNavDestination>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
551     JSClass<JSNavDestination>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
552     JSClass<JSNavDestination>::StaticMethod("id", &JSViewAbstract::JsId);
553     JSClass<JSNavDestination>::StaticMethod("mode", &JSNavDestination::SetMode);
554     JSClass<JSNavDestination>::StaticMethod("menus", &JSNavDestination::SetMenus);
555     JSClass<JSNavDestination>::StaticMethod("onWillAppear", &JSNavDestination::SetWillAppear);
556     JSClass<JSNavDestination>::StaticMethod("onWillShow", &JSNavDestination::SetWillShow);
557     JSClass<JSNavDestination>::StaticMethod("onWillHide", &JSNavDestination::SetWillHide);
558     JSClass<JSNavDestination>::StaticMethod("onWillDisappear", &JSNavDestination::SetWillDisAppear);
559     JSClass<JSNavDestination>::StaticMethod("ignoreLayoutSafeArea", &JSNavDestination::SetIgnoreLayoutSafeArea);
560     JSClass<JSNavDestination>::StaticMethod("systemBarStyle", &JSNavDestination::SetSystemBarStyle);
561     JSClass<JSNavDestination>::StaticMethod("recoverable", &JSNavDestination::SetRecoverable);
562     JSClass<JSNavDestination>::StaticMethod("toolbarConfiguration", &JSNavDestination::SetToolBarConfiguration);
563     JSClass<JSNavDestination>::StaticMethod("hideToolBar", &JSNavDestination::SetHideToolBar);
564     JSClass<JSNavDestination>::InheritAndBind<JSContainerBase>(globalObj);
565 }
566 
SetSystemBarStyle(const JSCallbackInfo& info)567 void JSNavDestination::SetSystemBarStyle(const JSCallbackInfo& info)
568 {
569     RefPtr<SystemBarStyle> style = nullptr;
570     if (info.Length() == 1 && info[0]->IsObject()) {
571         auto styleObj = JsConverter::ConvertJsValToNapiValue(info[0]);
572         auto env = GetCurrentEnv();
573         if (env) {
574             style = SystemBarStyle::CreateStyleFromJsObj(env, styleObj);
575         }
576     }
577     NavDestinationModel::GetInstance()->SetSystemBarStyle(style);
578 }
579 } // namespace OHOS::Ace::Framework
580