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