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