• 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 "core/components_ng/pattern/navigation/navigation_pattern.h"
17 
18 #include "base/log/dump_log.h"
19 #include "base/log/event_report.h"
20 #include "base/perfmonitor/perf_constants.h"
21 #include "base/ressched/ressched_report.h"
22 #include "core/common/ime/input_method_manager.h"
23 #include "core/components_ng/manager/avoid_info/avoid_info_manager.h"
24 #include "core/components_ng/pattern/navigation/nav_bar_node.h"
25 #include "core/components_ng/pattern/navigation/nav_bar_pattern.h"
26 #include "core/components_ng/pattern/navigation/navigation_drag_bar_pattern.h"
27 #include "core/components_ng/pattern/navigation/navigation_model_data.h"
28 #include "core/components_ng/pattern/navigation/navigation_title_util.h"
29 #include "core/components_ng/pattern/navigation/title_bar_pattern.h"
30 #include "core/components_ng/pattern/navigation/tool_bar_node.h"
31 #include "core/components_ng/pattern/navigation/tool_bar_pattern.h"
32 #include "core/components_ng/pattern/divider/divider_render_property.h"
33 
34 #ifdef WINDOW_SCENE_SUPPORTED
35 #include "core/components_ng/pattern/window_scene/helper/window_scene_helper.h"
36 #endif
37 namespace OHOS::Ace::NG {
38 
39 constexpr int32_t NAVIMODE_CHANGE_ANIMATION_DURATION = 250;
40 constexpr int32_t OPACITY_ANIMATION_DURATION_APPEAR = 150;
41 constexpr int32_t OPACITY_ANIMATION_DURATION_DISAPPEAR = 250;
42 constexpr int32_t EMPTY_DESTINATION_CHILD_SIZE = 1;
43 constexpr Dimension DEFAULT_DRAG_REGION = 12.0_vp;
44 constexpr Dimension DEFAULT_DRAG_BAR_HOT_ZONE = 12.0_vp;
45 constexpr float DEFAULT_HALF = 2.0f;
46 const Color MASK_COLOR = Color::FromARGB(25, 0, 0, 0);
47 constexpr int32_t PAGE_NODES = 1000;
48 constexpr int32_t PAGE_DEPTH = 300;
49 constexpr int32_t HALF_POSITION = 50;
50 constexpr int32_t END_POSITION = 100;
51 constexpr Dimension DRAG_BAR_RADIUS = 6.0_vp;
52 constexpr Dimension DRAG_BAR_BLUR_RADIUS = 20.0_vp;
53 constexpr Dimension DRAG_BAR_ITEM_RADIUS = 1.0_vp;
54 constexpr int32_t SECOND_ZINDEX_VALUE = 2;
55 constexpr int32_t INVALID_ANIMATION_ID = -1;
56 namespace {
57 constexpr int32_t MODE_SWITCH_ANIMATION_DURATION = 500; // ms
58 const RefPtr<CubicCurve> MODE_SWITCH_CURVE = AceType::MakeRefPtr<CubicCurve>(0.2f, 0.2f, 0.1f, 1.0f);
59 
CreatePercentGradientColor(int32_t percent,Color color)60 GradientColor CreatePercentGradientColor(int32_t percent, Color color)
61 {
62     NG::GradientColor gredient = GradientColor(color);
63     gredient.SetDimension(CalcDimension(percent, DimensionUnit::PERCENT));
64     return gredient;
65 }
66 
BuildNavDestinationInfoFromContext(const std::string & navigationId,NavDestinationState state,const RefPtr<NavDestinationContext> & context,bool isFrom,std::optional<NavDestinationInfo> & info)67 void BuildNavDestinationInfoFromContext(const std::string& navigationId, NavDestinationState state,
68     const RefPtr<NavDestinationContext>& context, bool isFrom, std::optional<NavDestinationInfo>& info)
69 {
70     if (!context) {
71         info.reset();
72         return;
73     }
74 
75     int32_t index = isFrom ? context->GetPreIndex() : context->GetIndex();
76     std::string navDestinationId = std::to_string(context->GetNavDestinationId());
77     std::string name;
78     napi_value param = nullptr;
79     auto pathInfo = context->GetNavPathInfo();
80     if (pathInfo) {
81         name = pathInfo->GetName();
82         param = pathInfo->GetParamObj();
83     }
84     NavDestinationMode mode = context->GetMode();
85     int32_t uniqueId = context->GetUniqueId();
86     info = std::make_optional<NavDestinationInfo>(navigationId, name, state, index, param,
87         navDestinationId, mode, uniqueId);
88 }
89 
LogCustomAnimationStart(const RefPtr<NavDestinationGroupNode> & preTopDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,NavigationOperation operation)90 void LogCustomAnimationStart(const RefPtr<NavDestinationGroupNode>& preTopDestination,
91     const RefPtr<NavDestinationGroupNode>& newTopNavDestination, NavigationOperation operation)
92 {
93     RefPtr<NavDestinationPattern> prePattern =
94         preTopDestination ? preTopDestination->GetPattern<NavDestinationPattern>() : nullptr;
95     RefPtr<NavDestinationPattern> newPattern =
96         newTopNavDestination ? newTopNavDestination->GetPattern<NavDestinationPattern>() : nullptr;
97     TAG_LOGI(AceLogTag::ACE_NAVIGATION,
98         "custom animation start: operation: %{public}d, pre name: %{public}s, id: %{public}s."
99         "top name: %{public}s, id: %{public}s",
100         operation, prePattern ? prePattern->GetName().c_str() : "null",
101         prePattern ? std::to_string(prePattern->GetNavDestinationId()).c_str() : "null",
102         newPattern ? newPattern->GetName().c_str() : "null",
103         newPattern ? std::to_string(newPattern->GetNavDestinationId()).c_str() : "null");
104 }
105 
TriggerNavDestinationTransition(const RefPtr<NavDestinationGroupNode> & navDestination,NavigationOperation operation,bool isEnter)106 int32_t TriggerNavDestinationTransition(const RefPtr<NavDestinationGroupNode>& navDestination,
107     NavigationOperation operation, bool isEnter)
108 {
109     CHECK_NULL_RETURN(navDestination, INVALID_ANIMATION_ID);
110     return navDestination->DoTransition(operation, isEnter);
111 }
112 } // namespace
113 
NavigationPattern()114 NavigationPattern::NavigationPattern()
115 {
116     navigationController_ = std::make_shared<InnerNavigationController>(WeakClaim(this), Container::CurrentId());
117 }
118 
GetTitleBarRenderContext()119 RefPtr<RenderContext> NavigationPattern::GetTitleBarRenderContext()
120 {
121     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
122     CHECK_NULL_RETURN(hostNode, nullptr);
123     auto layoutProperty = GetLayoutProperty<NavigationLayoutProperty>();
124     CHECK_NULL_RETURN(layoutProperty, nullptr);
125     auto contentNode = AceType::DynamicCast<FrameNode>(hostNode->GetContentNode());
126     CHECK_NULL_RETURN(contentNode, nullptr);
127     if (contentNode->FindChildNodeOfClass<NavDestinationGroupNode>()) {
128         auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
129         CHECK_NULL_RETURN(navBarNode, nullptr);
130         auto renderContext = navBarNode->GetRenderContext();
131         return renderContext;
132     } else {
133         auto renderContext = contentNode->GetRenderContext();
134         return renderContext;
135     }
136 }
137 
DoAnimation(NavigationMode usrNavigationMode)138 void NavigationPattern::DoAnimation(NavigationMode usrNavigationMode)
139 {
140     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
141     CHECK_NULL_VOID(hostNode);
142     auto layoutProperty = GetLayoutProperty<NavigationLayoutProperty>();
143     CHECK_NULL_VOID(layoutProperty);
144 
145     auto context = PipelineContext::GetCurrentContext();
146     CHECK_NULL_VOID(context);
147     layoutProperty->UpdateNavigationMode(navigationMode_);
148     hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
149     AnimationOption option = AnimationOption();
150     option.SetDuration(NAVIMODE_CHANGE_ANIMATION_DURATION);
151     option.SetCurve(Curves::FRICTION);
152     option.SetFillMode(FillMode::FORWARDS);
153     AnimationOption optionAlpha = AnimationOption();
154     optionAlpha.SetCurve(Curves::SHARP);
155     optionAlpha.SetFillMode(FillMode::FORWARDS);
156     auto renderContext = GetTitleBarRenderContext();
157     CHECK_NULL_VOID(renderContext);
158 
159     std::function<void()> finishCallback = [optionAlpha, renderContext, hostNode]() {
160         renderContext->OpacityAnimation(optionAlpha, 0, 1);
161         hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
162     };
163 
164     context->OpenImplicitAnimation(option, option.GetCurve(), finishCallback);
165     layoutProperty->UpdateNavigationMode(usrNavigationMode);
166     hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
167     context->FlushUITasks();
168     if (usrNavigationMode == NavigationMode::STACK || navigationMode_ == NavigationMode::SPLIT) {
169         optionAlpha.SetDuration(OPACITY_ANIMATION_DURATION_DISAPPEAR);
170         renderContext->OpacityAnimation(optionAlpha, 1, 0);
171     } else if (usrNavigationMode == NavigationMode::SPLIT || navigationMode_ == NavigationMode::STACK) {
172         optionAlpha.SetDuration(OPACITY_ANIMATION_DURATION_APPEAR);
173         renderContext->OpacityAnimation(optionAlpha, 0, 1);
174     }
175     context->CloseImplicitAnimation();
176     navigationMode_ = usrNavigationMode;
177 }
178 
OnAttachToFrameNode()179 void NavigationPattern::OnAttachToFrameNode()
180 {
181     auto host = GetHost();
182     CHECK_NULL_VOID(host);
183     auto pipelineContext = PipelineContext::GetCurrentContext();
184     CHECK_NULL_VOID(pipelineContext);
185     pipelineContext->AddWindowStateChangedCallback(host->GetId());
186     pipelineContext->AddWindowSizeChangeCallback(host->GetId());
187 
188     auto theme = NavigationGetTheme();
189     if (theme && theme->GetNavBarUnfocusEffectEnable()) {
190         pipelineContext->AddWindowFocusChangedCallback(host->GetId());
191     }
192     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
193         SafeAreaExpandOpts opts = { .type = SAFE_AREA_TYPE_ALL, .edges = SAFE_AREA_EDGE_ALL };
194         host->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
195     }
196 }
197 
OnDetachFromFrameNode(FrameNode * frameNode)198 void NavigationPattern::OnDetachFromFrameNode(FrameNode* frameNode)
199 {
200     auto id = frameNode->GetId();
201     auto pipeline = AceType::DynamicCast<PipelineContext>(PipelineBase::GetCurrentContext());
202     CHECK_NULL_VOID(pipeline);
203     pipeline->RemoveWindowStateChangedCallback(id);
204     pipeline->RemoveWindowSizeChangeCallback(id);
205 }
206 
207 
DoNavbarHideAnimation(const RefPtr<NavigationGroupNode> & hostNode)208 void NavigationPattern::DoNavbarHideAnimation(const RefPtr<NavigationGroupNode>& hostNode)
209 {
210     AnimationOption option;
211     option.SetCurve(MODE_SWITCH_CURVE);
212     option.SetFillMode(FillMode::FORWARDS);
213     option.SetDuration(MODE_SWITCH_ANIMATION_DURATION);
214     AnimationUtils::Animate(option, [weakHost = WeakPtr<NavigationGroupNode>(hostNode)]() {
215         auto hostNode = weakHost.Upgrade();
216         CHECK_NULL_VOID(hostNode);
217         auto layoutProperty = AceType::DynamicCast<NavigationLayoutProperty>(hostNode->GetLayoutProperty());
218         CHECK_NULL_VOID(layoutProperty);
219         bool hideNavBar = layoutProperty->GetHideNavBarValue(false);
220         auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
221         CHECK_NULL_VOID(navBarNode);
222         auto navBarLayoutProperty = navBarNode->GetLayoutProperty();
223         CHECK_NULL_VOID(navBarLayoutProperty);
224         navBarLayoutProperty->UpdateVisibility(hideNavBar ? VisibleType::INVISIBLE : VisibleType::VISIBLE, true);
225         hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
226         hostNode->GetContext()->FlushUITasks();
227     });
228 }
229 
InitDragBarEvent()230 void NavigationPattern::InitDragBarEvent()
231 {
232     auto dragBarNode = AceType::DynamicCast<FrameNode>(GetDragBarNode());
233     CHECK_NULL_VOID(dragBarNode);
234     auto dragGestureHub = dragBarNode->GetOrCreateGestureEventHub();
235     CHECK_NULL_VOID(dragGestureHub);
236     InitDragBarPanEvent(dragGestureHub);
237     InitTouchEvent(dragGestureHub);
238 
239     // clear divider hover and pan event
240     auto dividerNode = GetDividerNode();
241     CHECK_NULL_VOID(dividerNode);
242     auto dividerGestureHub = dividerNode->GetOrCreateGestureEventHub();
243     CHECK_NULL_VOID(dividerGestureHub);
244     auto dividerInputHub = dividerNode->GetOrCreateInputEventHub();
245     CHECK_NULL_VOID(dividerInputHub);
246     if (hoverEvent_) {
247         dividerInputHub->RemoveOnHoverEvent(hoverEvent_);
248         hoverEvent_.Reset();
249     }
250     if (panEvent_) {
251         dividerGestureHub->RemovePanEvent(panEvent_);
252         panEvent_.Reset();
253     }
254 }
255 
ClearDragBarEvent()256 void NavigationPattern::ClearDragBarEvent()
257 {
258     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
259     CHECK_NULL_VOID(hostNode);
260     auto dragBarNode = AceType::DynamicCast<FrameNode>(GetDragBarNode());
261     CHECK_NULL_VOID(dragBarNode);
262     auto dragGestureHub = dragBarNode->GetOrCreateGestureEventHub();
263     CHECK_NULL_VOID(dragGestureHub);
264 
265     // clear drag bar touch and pan event
266     if (touchEvent_) {
267         dragGestureHub->RemoveTouchEvent(touchEvent_);
268         touchEvent_.Reset();
269     }
270     if (dragBarPanEvent_) {
271         dragGestureHub->RemovePanEvent(dragBarPanEvent_);
272         dragBarPanEvent_.Reset();
273     }
274 
275     hostNode->RemoveChild(dragBarNode);
276     hostNode->SetDragBarNode(nullptr);
277 }
278 
BuildDragBar()279 void NavigationPattern::BuildDragBar()
280 {
281     if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TEN)) {
282         return;
283     }
284     if (enableDragBar_) {
285         if (GetDragBarNode()) {
286             // if dragBar is already in navigation, do nothing
287             return;
288         }
289         // create drag bar and init drag bar gesture event
290         auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
291         CHECK_NULL_VOID(hostNode);
292         CreateDragBarNode(hostNode);
293         InitDragBarEvent();
294         return;
295     }
296     auto dividerNode = GetDividerNode();
297     CHECK_NULL_VOID(dividerNode);
298     auto dividerGestureHub = dividerNode->GetOrCreateGestureEventHub();
299     CHECK_NULL_VOID(dividerGestureHub);
300     auto dividerInputHub = dividerNode->GetOrCreateInputEventHub();
301     CHECK_NULL_VOID(dividerInputHub);
302     InitDividerPanEvent(dividerGestureHub);
303     InitDividerMouseEvent(dividerInputHub);
304     if (GetDragBarNode()) {
305         // clear drag bar gesture event and remove dragBar
306         ClearDragBarEvent();
307     }
308 }
309 
OnModifyDone()310 void NavigationPattern::OnModifyDone()
311 {
312     // !!! Do not add operations about NavPathStack here, see @SyncWithJsStackIfNeeded
313     Pattern::OnModifyDone();
314     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
315     CHECK_NULL_VOID(hostNode);
316     auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
317     CHECK_NULL_VOID(navBarNode);
318     navBarNode->MarkModifyDone();
319     isRightToLeft_ = AceApplicationInfo::GetInstance().IsRightToLeft();
320 
321     auto pipeline = PipelineContext::GetCurrentContext();
322     CHECK_NULL_VOID(pipeline);
323     BuildDragBar();
324 
325     auto layoutProperty = hostNode->GetLayoutProperty<NavigationLayoutProperty>();
326     CHECK_NULL_VOID(layoutProperty);
327     auto curNavBarPosition = layoutProperty->GetNavBarPositionValue(NavBarPosition::START);
328     if (preNavBarPosition_.has_value() && preNavBarPosition_.value() != curNavBarPosition) {
329         MarkAllNavDestinationDirtyIfNeeded(hostNode);
330     }
331     preNavBarPosition_ = curNavBarPosition;
332 
333     auto&& opts = layoutProperty->GetSafeAreaExpandOpts();
334     if (opts) {
335         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "Navigation SafArea expand as %{public}s", opts->ToString().c_str());
336         uint8_t ignoreExpandKeyboard = 0x11;
337         SafeAreaExpandOpts optsExceptKeyboard = { .type = opts->type & ignoreExpandKeyboard,
338             .edges = opts->edges };
339         navBarNode->GetLayoutProperty()->UpdateSafeAreaExpandOpts(optsExceptKeyboard);
340         navBarNode->MarkModifyDone();
341 
342         auto navigationContentNode = AceType::DynamicCast<FrameNode>(hostNode->GetContentNode());
343         CHECK_NULL_VOID(navigationContentNode);
344         navigationContentNode->GetLayoutProperty()->UpdateSafeAreaExpandOpts(optsExceptKeyboard);
345         navigationContentNode->MarkModifyDone();
346 
347         auto dividerNode = AceType::DynamicCast<FrameNode>(hostNode->GetDividerNode());
348         CHECK_NULL_VOID(dividerNode);
349         dividerNode->GetLayoutProperty()->UpdateSafeAreaExpandOpts(optsExceptKeyboard);
350         dividerNode->MarkModifyDone();
351     }
352 
353     bool enableModeChangeAnimation = layoutProperty->GetEnableModeChangeAnimation().value_or(true);
354     if (enableModeChangeAnimation && GetNavigationMode() == NavigationMode::SPLIT && GetNavBarVisibilityChange()) {
355         DoNavbarHideAnimation(hostNode);
356     }
357 
358     // AddRecoverableNavigation function will check inside whether current navigation can be recovered
359     pipeline->GetNavigationManager()->AddRecoverableNavigation(hostNode->GetCurId(), hostNode);
360     RestoreJsStackIfNeeded();
361     UpdateToobarFocusColor();
362     UpdateDividerBackgroundColor();
363 }
364 
SetSystemBarStyle(const RefPtr<SystemBarStyle> & style)365 void NavigationPattern::SetSystemBarStyle(const RefPtr<SystemBarStyle>& style)
366 {
367     auto host = GetHost();
368     CHECK_NULL_VOID(host);
369     auto pipeline = host->GetContext();
370     CHECK_NULL_VOID(pipeline);
371     auto windowManager = pipeline->GetWindowManager();
372     CHECK_NULL_VOID(windowManager);
373     if (!backupStyle_.has_value()) {
374         backupStyle_ = windowManager->GetSystemBarStyle();
375     }
376     currStyle_ = style;
377 
378     // The systemBarStyle may only take effect when navigation fills the entire page.
379     if (!isFullPageNavigation_) {
380         return;
381     }
382 
383     // When there is NavDestination in the stack, the systemBarStyle set for Navigation does not take effect.
384     do {
385         if (!navigationStack_) {
386             break;
387         }
388         auto topPath = navigationStack_->GetTopNavPath();
389         if (!topPath.has_value()) {
390             break;
391         }
392         auto topNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(
393             NavigationGroupNode::GetNavDestinationNode(topPath->second));
394         if (topNavDestination) {
395             return;
396         }
397     } while (false);
398 
399     /**
400      * When developers provide a valid style to systemBarStyle, we should set the style to window;
401      * when 'undefined' was provided, we should restore the style.
402      */
403     if (currStyle_.value() != nullptr) {
404         windowManager->SetSystemBarStyle(currStyle_.value());
405     } else {
406         TryRestoreSystemBarStyle(windowManager);
407     }
408 }
409 
OnAttachToMainTree()410 void NavigationPattern::OnAttachToMainTree()
411 {
412     auto host = GetHost();
413     CHECK_NULL_VOID(host);
414     InitPageNode(host);
415     InitFoldState();
416     RegisterAvoidInfoChangeListener(host);
417 }
418 
InitFoldState()419 void NavigationPattern::InitFoldState()
420 {
421     auto container = Container::Current();
422     CHECK_NULL_VOID(container);
423     container->InitIsFoldable();
424     if (container->IsFoldable()) {
425         currentFoldStatus_ = container->GetCurrentFoldStatus();
426     }
427 }
428 
OnDetachFromMainTree()429 void NavigationPattern::OnDetachFromMainTree()
430 {
431     isFullPageNavigation_ = false;
432     auto host = GetHost();
433     CHECK_NULL_VOID(host);
434     UnregisterAvoidInfoChangeListener(host);
435     auto pipeline = host->GetContext();
436     CHECK_NULL_VOID(pipeline);
437     auto windowManager = pipeline->GetWindowManager();
438     CHECK_NULL_VOID(windowManager);
439     TryRestoreSystemBarStyle(windowManager);
440     backupStyle_.reset();
441     currStyle_.reset();
442     pageNode_ = nullptr;
443 }
444 
IsTopNavDestination(const RefPtr<UINode> & node) const445 bool NavigationPattern::IsTopNavDestination(const RefPtr<UINode>& node) const
446 {
447     if (!navigationStack_) {
448         return false;
449     }
450     auto topPath = navigationStack_->GetTopNavPath();
451     if (!topPath.has_value()) {
452         return false;
453     }
454     auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(
455         NavigationGroupNode::GetNavDestinationNode(topPath->second));
456     return navDestination == node;
457 }
458 
JudgeFoldStateChangeAndUpdateState()459 bool NavigationPattern::JudgeFoldStateChangeAndUpdateState()
460 {
461     auto container = Container::Current();
462     CHECK_NULL_RETURN(container, false);
463     auto foldStatus = container->GetCurrentFoldStatus();
464     TAG_LOGI(AceLogTag::ACE_NAVIGATION, "newFoldStatus: %{public}d, currentFoldStatus: %{public}d.",
465         static_cast<int32_t>(foldStatus), static_cast<int32_t>(currentFoldStatus_));
466     if (foldStatus != currentFoldStatus_) {
467         currentFoldStatus_ = foldStatus;
468         return true;
469     }
470     return false;
471 }
472 
UpdateIsFullPageNavigation(const RefPtr<FrameNode> & host)473 void NavigationPattern::UpdateIsFullPageNavigation(const RefPtr<FrameNode>& host)
474 {
475     CHECK_NULL_VOID(host);
476     auto geometryNode = host->GetGeometryNode();
477     CHECK_NULL_VOID(geometryNode);
478     auto frame = geometryNode->GetFrameRect();
479     auto pipeline = host->GetContext();
480     CHECK_NULL_VOID(pipeline);
481     auto windowManager = pipeline->GetWindowManager();
482     CHECK_NULL_VOID(windowManager);
483 
484     bool isFullPage = false;
485     auto pageNode = pageNode_.Upgrade();
486     if (pageNode) {
487         auto pageNodeGeometryNode = pageNode->GetGeometryNode();
488         if (pageNodeGeometryNode) {
489             auto pageFrame = pageNodeGeometryNode->GetFrameRect();
490             isFullPage = pageFrame.GetSize() == frame.GetSize();
491         }
492     }
493     pageNode = nullptr;
494 
495     if (isFullPage == isFullPageNavigation_) {
496         return;
497     }
498 
499     isFullPageNavigation_ = isFullPage;
500     TAG_LOGI(AceLogTag::ACE_NAVIGATION, "Navigation[%{public}d] change to %{public}s",
501         host->GetId(), isFullPageNavigation_ ? "FullPage" : "PartialPage");
502     MarkAllNavDestinationDirtyIfNeeded(host);
503     UpdateSystemBarStyleOnFullPageStateChange(windowManager);
504     if (isFullPageNavigation_) {
505         RegisterPageVisibilityChangeCallback();
506     }
507 }
508 
UpdateSystemBarStyleOnFullPageStateChange(const RefPtr<WindowManager> & windowManager)509 void NavigationPattern::UpdateSystemBarStyleOnFullPageStateChange(const RefPtr<WindowManager>& windowManager)
510 {
511     // full page -> partial page
512     if (!isFullPageNavigation_) {
513         TryRestoreSystemBarStyle(windowManager);
514         return;
515     }
516 
517     // partial page -> full page
518     auto topPath = navigationStack_->GetTopNavPath();
519     UpdateSystemBarStyleWithTopNavPath(windowManager, topPath);
520 }
521 
UpdateSystemBarStyleOnTopNavPathChange(const std::optional<std::pair<std::string,RefPtr<UINode>>> & newTopNavPath)522 void NavigationPattern::UpdateSystemBarStyleOnTopNavPathChange(
523     const std::optional<std::pair<std::string, RefPtr<UINode>>>& newTopNavPath)
524 {
525     if (!isFullPageNavigation_) {
526         return;
527     }
528 
529     auto host = GetHost();
530     CHECK_NULL_VOID(host);
531     auto pipeline = host->GetContext();
532     CHECK_NULL_VOID(pipeline);
533     auto windowManager = pipeline->GetWindowManager();
534     CHECK_NULL_VOID(windowManager);
535     UpdateSystemBarStyleWithTopNavPath(windowManager, newTopNavPath);
536 }
537 
UpdateSystemBarStyleWithTopNavPath(const RefPtr<WindowManager> & windowManager,const std::optional<std::pair<std::string,RefPtr<UINode>>> & topNavPath)538 void NavigationPattern::UpdateSystemBarStyleWithTopNavPath(const RefPtr<WindowManager>& windowManager,
539     const std::optional<std::pair<std::string, RefPtr<UINode>>>& topNavPath)
540 {
541     if (ApplyTopNavPathSystemBarStyleOrRestore(windowManager, topNavPath)) {
542         return;
543     }
544 
545     if (currStyle_.has_value() && currStyle_.value() != nullptr) {
546         windowManager->SetSystemBarStyle(currStyle_.value());
547     } else {
548         TryRestoreSystemBarStyle(windowManager);
549     }
550 }
551 
TryRestoreSystemBarStyle(const RefPtr<WindowManager> & windowManager)552 void NavigationPattern::TryRestoreSystemBarStyle(const RefPtr<WindowManager>& windowManager)
553 {
554     if (backupStyle_.has_value()) {
555         windowManager->SetSystemBarStyle(backupStyle_.value());
556     }
557 }
558 
UpdateSystemBarStyleOnPageVisibilityChange(bool show)559 void NavigationPattern::UpdateSystemBarStyleOnPageVisibilityChange(bool show)
560 {
561     if (!isFullPageNavigation_) {
562         return;
563     }
564 
565     CHECK_NULL_VOID(navigationStack_);
566     auto host = GetHost();
567     CHECK_NULL_VOID(host);
568     auto pipeline = host->GetContext();
569     CHECK_NULL_VOID(pipeline);
570     auto windowManager = pipeline->GetWindowManager();
571     CHECK_NULL_VOID(windowManager);
572     if (show) {
573         // page containing Navigation, hide -> show
574         auto topPath = navigationStack_->GetTopNavPath();
575         UpdateSystemBarStyleWithTopNavPath(windowManager, topPath);
576     } else {
577         // page containing Navigation, show -> hide
578         TryRestoreSystemBarStyle(windowManager);
579     }
580 }
581 
RegisterPageVisibilityChangeCallback()582 void NavigationPattern::RegisterPageVisibilityChangeCallback()
583 {
584     auto pageNode = pageNode_.Upgrade();
585     CHECK_NULL_VOID(pageNode);
586     RefPtr<PagePattern> pagePattern = pageNode->GetPattern<PagePattern>();
587     CHECK_NULL_VOID(pagePattern);
588     auto callback = [weak = WeakClaim(this)](bool show) {
589         auto pattern = weak.Upgrade();
590         CHECK_NULL_VOID(pattern);
591         // we need update the "systemBarStyle" at the beginning of the transition animation on the router page
592         pattern->UpdateSystemBarStyleOnPageVisibilityChange(show);
593     };
594     pagePattern->SetPageVisibilityChangeCallback(std::move(callback));
595 }
596 
ApplyTopNavPathSystemBarStyleOrRestore(const RefPtr<WindowManager> & windowManager,const std::optional<std::pair<std::string,RefPtr<UINode>>> & topNavPath)597 bool NavigationPattern::ApplyTopNavPathSystemBarStyleOrRestore(
598     const RefPtr<WindowManager>& windowManager,
599     const std::optional<std::pair<std::string, RefPtr<UINode>>>& topNavPath)
600 {
601     if (!topNavPath.has_value()) {
602         return false;
603     }
604 
605     auto topNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(
606         NavigationGroupNode::GetNavDestinationNode(topNavPath->second));
607     if (!topNavDestination) {
608         return false;
609     }
610 
611     auto navDestinationPattern = topNavDestination->GetPattern<NavDestinationPattern>();
612     if (!navDestinationPattern) {
613         return false;
614     }
615     /**
616      * Backup is only performed when the developer sets the "systemBarStyle" attribute,
617      * and the entire Navigation is only backed up once.
618      * Therefore, when developer only set the "systemBarStyle" attribute to NavDestination, we need to
619      * save the attribute to Navigation.
620      */
621     auto backupFromNavDestination = navDestinationPattern->GetBackupStyle();
622     if (!backupStyle_.has_value() && backupFromNavDestination.has_value()) {
623         backupStyle_ = backupFromNavDestination;
624     }
625 
626     auto destCurrStyle = navDestinationPattern->GetCurrentStyle();
627     if (destCurrStyle.has_value() && destCurrStyle.value() != nullptr) {
628         windowManager->SetSystemBarStyle(destCurrStyle.value());
629     } else {
630         TryRestoreSystemBarStyle(windowManager);
631     }
632     return true;
633 }
634 
InitPageNode(const RefPtr<FrameNode> & host)635 void NavigationPattern::InitPageNode(const RefPtr<FrameNode>& host)
636 {
637     CHECK_NULL_VOID(host);
638     auto parent = host->GetParent();
639     CHECK_NULL_VOID(parent);
640     RefPtr<FrameNode> pageNode = nullptr;
641     while (parent) {
642         if (parent->GetTag() == V2::PAGE_ETS_TAG) {
643             pageNode = AceType::DynamicCast<FrameNode>(parent);
644             break;
645         }
646         parent = parent->GetParent();
647     }
648     if (!pageNode) {
649         TAG_LOGE(AceLogTag::ACE_NAVIGATION, "Failed to find PageNode of Navigation");
650     } else {
651         pageNode_ = WeakPtr<FrameNode>(pageNode);
652     }
653 }
654 
OnLanguageConfigurationUpdate()655 void NavigationPattern::OnLanguageConfigurationUpdate()
656 {
657     bool isRightToLeft = AceApplicationInfo::GetInstance().IsRightToLeft();
658     if (isRightToLeft != isRightToLeft_) {
659         auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
660         CHECK_NULL_VOID(hostNode);
661         hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
662         isRightToLeft_ = isRightToLeft;
663     }
664 }
665 
SyncWithJsStackIfNeeded()666 void NavigationPattern::SyncWithJsStackIfNeeded()
667 {
668     if (!needSyncWithJsStack_) {
669         TAG_LOGI(AceLogTag::ACE_NAVIGATION,
670             "not need SyncWithJsStack, needSyncWithJsStack_ %{public}d", needSyncWithJsStack_);
671         return;
672     }
673     CHECK_NULL_VOID(navigationStack_);
674     needSyncWithJsStack_ = false;
675     if (!isFinishInteractiveAnimation_) {
676         TAG_LOGI(AceLogTag::ACE_NAVIGATION,
677             "not need SyncWithJsStack, interactive animation: %{public}d", isFinishInteractiveAnimation_);
678         return;
679     }
680     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
681     CHECK_NULL_VOID(hostNode);
682     TAG_LOGI(AceLogTag::ACE_NAVIGATION,
683         "sync with js stack, id: %{public}s, UINodeId: %{public}d, preStackSize: %{public}d, newStackSize: %{public}d",
684         hostNode->GetCurId().c_str(), hostNode->GetId(), navigationStack_->PreSize(),
685         static_cast<int32_t>(navigationStack_->GetAllPathName().size()));
686     preTopNavPath_ = navigationStack_->GetPreTopNavPath();
687     preStackSize_ = navigationStack_->PreSize();
688     preContext_ = nullptr;
689     if (preTopNavPath_.has_value()) {
690         auto preDestination = AceType::DynamicCast<NavDestinationGroupNode>(
691             NavigationGroupNode::GetNavDestinationNode(preTopNavPath_->second));
692         if (preDestination) {
693             auto pattern = AceType::DynamicCast<NavDestinationPattern>(preDestination->GetPattern());
694             preContext_ = pattern->GetNavDestinationContext();
695             if (preContext_) {
696                 preContext_->SetPreIndex(preStackSize_ - 1);
697             }
698         }
699     }
700     if (isCustomAnimation_) {
701         navigationStack_->UpdateRecoveryList();
702     }
703     navigationStack_->SavePreNavList();
704     UpdateNavPathList();
705     auto newTopNavPath = navigationStack_->GetTopNavPath();
706     auto replaceValue = navigationStack_->GetReplaceValue();
707     if (preTopNavPath_ != newTopNavPath || replaceValue == 1) {
708         isReplace_ = replaceValue != 0;
709         UpdateIsAnimation(preTopNavPath_);
710         lastPreIndex_ = 0;
711         if (preTopNavPath_.has_value()) {
712             lastPreIndex_ = navigationStack_->FindIndex(preTopNavPath_->first, preTopNavPath_->second, true);
713         }
714         FireInterceptionEvent(true, newTopNavPath);
715         if (needSyncWithJsStack_) {
716             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "sync with js stack in before interception");
717             UpdateNavPathList();
718             needSyncWithJsStack_ = false;
719         }
720     }
721     RefreshNavDestination();
722 }
723 
UpdateNavPathList()724 void NavigationPattern::UpdateNavPathList()
725 {
726     CHECK_NULL_VOID(navigationStack_);
727     auto pathNames = navigationStack_->GetAllPathName();
728     auto indexes = navigationStack_->GetAllPathIndex();
729     topFromSingletonMoved_ = navigationStack_->IsTopFromSingletonMoved();
730     navigationStack_->ResetSingletonMoved();
731     navigationStack_->InitNavPathIndex(pathNames);
732     auto cacheNodes = navigationStack_->GetAllCacheNodes();
733     NavPathList navPathList;
734     int32_t pathListSize = static_cast<int32_t>(pathNames.size());
735     isCurTopNewInstance_ = false;
736     // lastRecoveredStandardIndex will be only used in recovery case
737     int32_t lastRecoveredStandardIndex = 0;
738     int32_t removeSize = 0; // push destination failed size
739     bool isCurForceSetList = false;
740     for (int32_t index = 0; index < pathListSize; ++index) {
741         auto pathName = pathNames[index];
742         RefPtr<UINode> uiNode = nullptr;
743         int32_t arrayIndex = index - removeSize;
744         if (navigationStack_->IsFromRecovery(arrayIndex)) {
745             if (navigationStack_->GetRecoveredDestinationMode(arrayIndex) ==
746                 static_cast<int32_t>(NavDestinationMode::STANDARD)) {
747                 lastRecoveredStandardIndex = arrayIndex;
748             }
749             navPathList.emplace_back(std::make_pair(pathName, uiNode));
750             // only create recovery node when it is at top
751             if (index == pathListSize - 1) {
752                 removeSize += GenerateUINodeFromRecovery(lastRecoveredStandardIndex, navPathList);
753             }
754             continue;
755         }
756         auto pathIndex = indexes[index];
757         if (navigationStack_->NeedBuildNewInstance(arrayIndex)) {
758             // if marked NEW_INSTANCE when push/replace in frontend, build a new instance anyway
759             if (!GenerateUINodeByIndex(arrayIndex, uiNode)) {
760                 removeSize++;
761                 continue;
762             }
763             navPathList.emplace_back(std::make_pair(pathName, uiNode));
764             navigationStack_->SetNeedBuildNewInstance(arrayIndex, false);
765             if (index == pathListSize - 1) {
766                 isCurTopNewInstance_ = true;
767             }
768             continue;
769         }
770         bool isPageForceSet = navigationStack_->GetIsForceSet(arrayIndex);
771         if (isPageForceSet) {
772             isCurForceSetList = true;
773         }
774         auto navDestinationId = navigationStack_->GetNavDestinationIdInt(arrayIndex);
775         if (index == pathListSize - 1 && addByNavRouter_) {
776             addByNavRouter_ = false;
777             uiNode = navigationStack_->Get();
778         } else if (isPageForceSet && navDestinationId != -1) {
779             uiNode = FindNavDestinationNodeInPreList(navDestinationId);
780         } else {
781             uiNode = navigationStack_->Get(pathIndex);
782         }
783         if (uiNode) {
784             TAG_LOGD(AceLogTag::ACE_NAVIGATION, "find in list, navigation stack reserve node, "
785                 "old index: %{public}d, index: %{public}d, removeSize: %{public}d, name: %{public}s.",
786                 pathIndex, index, removeSize, pathName.c_str());
787             /**
788              * If we call the function pushPath/pushDestination with singleton mode(
789              * LaunchMode == MOVE_TO_TOP_SINGLETON/POP_TO_SINGLETON), and the top NavDestination of stack
790              * is the NavDestination which we need to push(NavDestination's name == NavPathInfo's name),
791              * then wee need to update the NavDestination's parameters.
792              */
793             navigationStack_->UpdatePathInfoIfNeeded(uiNode, arrayIndex);
794             auto navDestinationGroupNode = AceType::DynamicCast<NavDestinationGroupNode>(
795                 NavigationGroupNode::GetNavDestinationNode(uiNode));
796             if (navDestinationGroupNode && navDestinationGroupNode->GetCanReused()) {
797                 navigationStack_->ResetIsForceSetFlag(arrayIndex);
798                 navPathList.emplace_back(std::make_pair(pathName, uiNode));
799                 continue;
800             }
801         }
802         uiNode = navigationStack_->GetFromCacheNode(cacheNodes, pathName);
803         if (uiNode) {
804             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "find in cached node, navigation stack reserve node, "
805                 "index: %{public}d, removeSize: %{public}d, name: %{public}s.", index, removeSize, pathName.c_str());
806             navPathList.emplace_back(std::make_pair(pathName, uiNode));
807             navigationStack_->RemoveCacheNode(cacheNodes, pathName, uiNode);
808             auto navDestination =
809                 DynamicCast<NavDestinationGroupNode>(NavigationGroupNode::GetNavDestinationNode(uiNode));
810             if (navDestination) {
811                 navDestination->SetInCurrentStack(true);
812                 auto eventHub = navDestination->GetEventHub<EventHub>();
813                 CHECK_NULL_VOID(eventHub);
814                 eventHub->SetEnabledInternal(true);
815                 navigationStack_->ResetIsForceSetFlag(arrayIndex);
816             }
817             continue;
818         }
819         if (isPageForceSet) {
820             navPathList.emplace_back(std::make_pair(pathName, uiNode));
821             continue;
822         }
823         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "find in nowhere, navigation stack create new node, "
824             "index: %{public}d, removeSize: %{public}d, name: %{public}s.", index, removeSize, pathName.c_str());
825         if (!GenerateUINodeByIndex(arrayIndex, uiNode)) {
826             std::string replacedName = "";
827             int32_t replacedIndex = -1;
828             if (navigationStack_->CheckIsReplacedDestination(arrayIndex, replacedName, replacedIndex)) {
829                 navigationStack_->SetRecoveryFromReplaceDestination(arrayIndex, false);
830                 pathNames[index] = replacedName;
831                 indexes[index] = replacedIndex;
832                 index--;
833                 continue;
834             }
835             removeSize++;
836             continue;
837         }
838         navPathList.emplace_back(std::make_pair(pathName, uiNode));
839     }
840     if (isCurForceSetList) {
841         GenerateLastStandardPage(navPathList);
842     }
843     navigationStack_->SetNavPathList(navPathList);
844     navigationStack_->SetIsCurForceSetList(isCurForceSetList);
845 }
846 
RefreshNavDestination()847 void NavigationPattern::RefreshNavDestination()
848 {
849     isChanged_ = false;
850     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
851     CHECK_NULL_VOID(hostNode);
852     auto pipeline = PipelineContext::GetCurrentContext();
853     CHECK_NULL_VOID(pipeline);
854     auto preTopNavPath = std::move(preTopNavPath_);
855     auto preLastStandardIndex = hostNode->GetLastStandardIndex();
856     auto& navPathList = navigationStack_->GetAllNavDestinationNodes();
857     hostNode->UpdateNavDestinationNodeWithoutMarkDirty(
858         preTopNavPath.has_value() ? preTopNavPath->second : nullptr, navigationModeChange_);
859     auto newTopNavPath = navigationStack_->GetTopNavPath();
860 #if defined(ENABLE_NAV_SPLIT_MODE)
861     isBackPage_ = newTopNavPath.has_value() ?
862         navigationStack_->isLastListContains(newTopNavPath->first, newTopNavPath->second) : false;
863 #endif
864     if (topFromSingletonMoved_) {
865         FireOnNewParam(newTopNavPath.has_value() ? newTopNavPath->second : nullptr);
866     }
867     CheckTopNavPathChange(preTopNavPath, newTopNavPath, preLastStandardIndex);
868 
869     // close keyboard
870 #if defined(ENABLE_STANDARD_INPUT)
871     RefPtr<FrameNode> targetNode = newTopNavPath.has_value() ? AceType::DynamicCast<FrameNode>(
872             NavigationGroupNode::GetNavDestinationNode(newTopNavPath->second)) :
873             AceType::DynamicCast<FrameNode>(hostNode->GetNavBarNode());
874     if (isChanged_ && GetIsFocusable(targetNode)) {
875         InputMethodManager::GetInstance()->CloseKeyboard();
876     }
877 #endif
878 
879 #if defined(ENABLE_NAV_SPLIT_MODE)
880     navigationStack_->SetLastNavPathList(navPathList);
881 #endif
882 
883     /* if first navDestination is removed, the new one will be refreshed */
884     if (!navPathList.empty()) {
885         auto firstNavDesNode = AceType::DynamicCast<NavDestinationGroupNode>(
886             NavigationGroupNode::GetNavDestinationNode(navPathList.front().second));
887         CHECK_NULL_VOID(firstNavDesNode);
888         firstNavDesNode->MarkModifyDone();
889     }
890 
891     std::string navDestinationName = newTopNavPath.has_value() ? newTopNavPath->first : "";
892     pipeline->AddPredictTask([weak = WeakClaim(this), weakNode = WeakPtr<FrameNode>(hostNode),
893         navDestinationName](int64_t deadline, bool canUseLongPredictTask) {
894             auto navigationPattern = weak.Upgrade();
895             CHECK_NULL_VOID(navigationPattern);
896             auto navigationNode = weakNode.Upgrade();
897             CHECK_NULL_VOID(navigationNode);
898             int32_t count = 0;
899             int32_t depth = 0;
900             navigationNode->GetPageNodeCountAndDepth(&count, &depth);
901             navigationPattern->PerformanceEventReport(count, depth, navDestinationName);
902         });
903 }
904 
CheckTopNavPathChange(const std::optional<std::pair<std::string,RefPtr<UINode>>> & preTopNavPath,const std::optional<std::pair<std::string,RefPtr<UINode>>> & newTopNavPath,int32_t preLastStandardIndex)905 void NavigationPattern::CheckTopNavPathChange(
906     const std::optional<std::pair<std::string, RefPtr<UINode>>>& preTopNavPath,
907     const std::optional<std::pair<std::string, RefPtr<UINode>>>& newTopNavPath,
908     int32_t preLastStandardIndex)
909 {
910     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
911     CHECK_NULL_VOID(hostNode);
912     if (preTopNavPath != newTopNavPath) {
913         UpdateSystemBarStyleOnTopNavPathChange(newTopNavPath);
914     }
915     auto replaceValue = navigationStack_->GetReplaceValue();
916     if (preTopNavPath == newTopNavPath) {
917         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "page is not change. don't transition");
918         auto currentProxy = GetTopNavigationProxy();
919         if (currentProxy) {
920             currentProxy->SetIsSuccess(false);
921         }
922         hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_WILL_HIDE);
923         NotifyDialogChange(NavDestinationLifecycle::ON_WILL_SHOW, true);
924         auto pipeline = PipelineContext::GetCurrentContext();
925         CHECK_NULL_VOID(pipeline);
926         pipeline->AddAfterLayoutTask([weakPattern = WeakClaim(this)]() {
927             auto pattern = weakPattern.Upgrade();
928             CHECK_NULL_VOID(pattern);
929             auto hostNode = AceType::DynamicCast<NavigationGroupNode>(pattern->GetHost());
930             CHECK_NULL_VOID(hostNode);
931             hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_HIDE);
932             hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_WILL_DISAPPEAR);
933             pattern->NotifyDialogChange(NavDestinationLifecycle::ON_SHOW, true);
934             hostNode->RemoveDialogDestination();
935         });
936         ClearRecoveryList();
937         return;
938     }
939 
940     isChanged_ = true;
941     UpdateIsAnimation(preTopNavPath);
942     isReplace_ = replaceValue != 0;
943     if (replaceValue == 1) {
944         const int32_t replaceAnimation = 2;
945         navigationStack_->UpdateReplaceValue(replaceAnimation);
946     }
947     auto context = PipelineContext::GetCurrentContext();
948     CHECK_NULL_VOID(context);
949     // close the text selection menu before transition.
950     auto selectOverlayManager = context->GetSelectOverlayManager();
951     if (selectOverlayManager) {
952         selectOverlayManager->ResetSelectionAndDestroySelectOverlay();
953     }
954     // fire onHidden and lostFocus event
955     RefPtr<NavDestinationGroupNode> preTopNavDestination;
956     int32_t lastPreIndex = -1;
957     bool isPopPage = false;
958     if (preTopNavPath.has_value()) {
959         // pre page is not in the current stack
960         lastPreIndex = navigationStack_->FindIndex(preTopNavPath->first, preTopNavPath->second, true);
961         isPopPage |= lastPreIndex == -1;
962         preTopNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(
963             NavigationGroupNode::GetNavDestinationNode(preTopNavPath->second));
964     }
965     if (isCurTopNewInstance_) {
966         isPopPage = false;
967     }
968     RefPtr<NavDestinationGroupNode> newTopNavDestination;
969     if (newTopNavPath.has_value()) {
970         newTopNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(
971             NavigationGroupNode::GetNavDestinationNode(newTopNavPath->second));
972         do {
973             if (!newTopNavDestination) {
974                 break;
975             }
976             if (!GetIsFocusable(newTopNavDestination)) {
977                 break;
978             }
979             auto navDestinationPattern = newTopNavDestination->GetPattern<NavDestinationPattern>();
980             auto navDestinationFocusView = AceType::DynamicCast<FocusView>(navDestinationPattern);
981             CHECK_NULL_VOID(navDestinationFocusView);
982             if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TWELVE)) {
983                 navDestinationFocusView->SetIsViewRootScopeFocused(false);
984             }
985             navDestinationFocusView->FocusViewShow();
986         } while (0);
987     } else {
988         // back to navBar case
989         auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
990         CHECK_NULL_VOID(navBarNode);
991         auto navigationLayoutProperty = AceType::DynamicCast<NavigationLayoutProperty>(hostNode->GetLayoutProperty());
992         if (!navigationLayoutProperty->GetHideNavBarValue(false)) {
993             navBarNode->GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE);
994             navBarNode->SetJSViewActive(true);
995         }
996         ProcessPageShowEvent();
997         navBarNode->GetEventHub<EventHub>()->SetEnabledInternal(true);
998         if (GetIsFocusable(navBarNode)) {
999             auto navBarFocusView = navBarNode->GetPattern<FocusView>();
1000             CHECK_NULL_VOID(navBarFocusView);
1001             if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1002                 navBarFocusView->SetIsViewRootScopeFocused(false);
1003             }
1004             navBarFocusView->FocusViewShow();
1005         }
1006     }
1007     bool isShow = false;
1008     bool isDialog =
1009         (preTopNavDestination && preTopNavDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG) ||
1010         (newTopNavDestination && newTopNavDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG);
1011     if (preTopNavDestination && isDialog) {
1012         auto lastStandardIndex = hostNode->GetLastStandardIndex();
1013         isShow = (lastPreIndex != -1) && (lastPreIndex >= lastStandardIndex);
1014         hostNode->SetNeedSetInvisible(lastStandardIndex >= 0);
1015         if (lastStandardIndex < 0) {
1016             auto navBarNode = AceType::DynamicCast<FrameNode>(hostNode->GetNavBarNode());
1017             auto layoutProperty = navBarNode->GetLayoutProperty();
1018             layoutProperty->UpdateVisibility(VisibleType::VISIBLE, true);
1019             navBarNode->SetJSViewActive(true);
1020         }
1021     }
1022     bool disableAllAnimation = navigationStack_->GetDisableAnimation();
1023     bool animated = navigationStack_->GetAnimatedValue();
1024     TAG_LOGI(AceLogTag::ACE_NAVIGATION,
1025         "transition start, disableAllAnimation: %{public}d, animated: %{public}d, isPopPage: %{public}d, isDialog: "
1026         "%{public}d, isReplace: %{public}d, isCustomAnimation: %{public}d",
1027         disableAllAnimation, animated, isPopPage, isDialog, isReplace_, isCustomAnimation_);
1028     if (disableAllAnimation || !animated) {
1029         // transition without animation need to run before layout for geometryTransition.
1030         StartTransition(preTopNavDestination, newTopNavDestination, false, isPopPage, isShow);
1031         navigationStack_->UpdateAnimatedValue(true);
1032         hostNode->GetLayoutProperty()->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
1033         return;
1034     }
1035     if (isDialog && !isCustomAnimation_) {
1036         bool isNeedAnimation =
1037             AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_THIRTEEN) ?
1038             true : false;
1039         StartTransition(preTopNavDestination, newTopNavDestination, isNeedAnimation, isPopPage, isShow);
1040         hostNode->GetLayoutProperty()->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
1041         return;
1042     }
1043 
1044     // before the animation of navDes replacing, update the zIndex of the previous navDes node
1045     UpdatePreNavDesZIndex(preTopNavDestination, newTopNavDestination, preLastStandardIndex);
1046     // transition with animation need to run after layout task
1047     StartTransition(preTopNavDestination, newTopNavDestination, true, isPopPage, isShow);
1048     hostNode->GetLayoutProperty()->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
1049 }
1050 
FireNavDestinationStateChange(NavDestinationLifecycle lifecycle)1051 int32_t NavigationPattern::FireNavDestinationStateChange(NavDestinationLifecycle lifecycle)
1052 {
1053     const auto& navDestinationNodes = navigationStack_->GetAllNavDestinationNodes();
1054     auto errIndex = static_cast<int32_t>(navDestinationNodes.size());
1055     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1056     CHECK_NULL_RETURN(hostNode, errIndex);
1057     NotifyDialogChange(lifecycle, true);
1058     return hostNode->GetLastStandardIndex();
1059 }
1060 
FireNavigationStateChange(const RefPtr<UINode> & node,bool isShow)1061 void NavigationPattern::FireNavigationStateChange(const RefPtr<UINode>& node, bool isShow)
1062 {
1063     if (isShow) {
1064         NavigationPattern::FireNavigationLifecycleChange(node, NavDestinationLifecycle::ON_SHOW);
1065         return;
1066     }
1067     NavigationPattern::FireNavigationLifecycleChange(node, NavDestinationLifecycle::ON_HIDE);
1068 }
1069 
CheckParentDestinationIsOnhide(const RefPtr<NavDestinationGroupNode> & destinationNode)1070 bool NavigationPattern::CheckParentDestinationIsOnhide(const RefPtr<NavDestinationGroupNode>& destinationNode)
1071 {
1072     CHECK_NULL_RETURN(destinationNode, false);
1073     auto destinationNodePattern = destinationNode->GetPattern<NavDestinationPattern>();
1074     CHECK_NULL_RETURN(destinationNodePattern, false);
1075     return !destinationNodePattern->GetIsOnShow();
1076 }
1077 
CheckParentDestinationInactive()1078 bool NavigationPattern::CheckParentDestinationInactive()
1079 {
1080     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1081     CHECK_NULL_RETURN(hostNode, false);
1082     auto parentDestination = hostNode->GetParentDestinationNode().Upgrade();
1083     CHECK_NULL_RETURN(parentDestination, false);
1084     auto pattern = parentDestination->GetPattern<NavDestinationPattern>();
1085     CHECK_NULL_RETURN(pattern, false);
1086     return !pattern->IsActive();
1087 }
1088 
CheckDestinationIsPush(const RefPtr<NavDestinationGroupNode> & destinationNode)1089 bool NavigationPattern::CheckDestinationIsPush(const RefPtr<NavDestinationGroupNode>& destinationNode)
1090 {
1091     CHECK_NULL_RETURN(destinationNode, false);
1092     return destinationNode->GetIndex() != -1 || destinationNode->GetNavDestinationCustomNode();
1093 }
1094 
FireNavigationInner(const RefPtr<UINode> & node,bool isOnShow)1095 void NavigationPattern::FireNavigationInner(const RefPtr<UINode>& node, bool isOnShow)
1096 {
1097     CHECK_NULL_VOID(node);
1098     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(node);
1099     if (!navigationNode) {
1100         NavigationPattern::FireNavigationChange(node, isOnShow, false);
1101         return;
1102     }
1103     auto navigationPattern = navigationNode->GetPattern<NavigationPattern>();
1104     CHECK_NULL_VOID(navigationPattern);
1105     CHECK_NULL_VOID(navigationPattern->navigationStack_);
1106     const auto& navDestinationNodes = navigationPattern->navigationStack_->GetAllNavDestinationNodes();
1107     auto lastStandardIndex = navigationNode->GetLastStandardIndex();
1108     int32_t standardIndex = lastStandardIndex >= 0 ? lastStandardIndex : 0;
1109     int32_t start = standardIndex;
1110     int32_t end = navigationPattern->navigationStack_->Size();
1111     auto pipeline = PipelineContext::GetCurrentContext();
1112     CHECK_NULL_VOID(pipeline);
1113     auto overlayManager = pipeline->GetOverlayManager();
1114     if (isOnShow) {
1115         if (overlayManager && overlayManager->HasModalPage()) {
1116             return;
1117         }
1118         for (int32_t index = start; index < end; index++) {
1119             const auto& curPath = navDestinationNodes[index];
1120             auto curDestination = AceType::DynamicCast<NavDestinationGroupNode>(
1121                 navigationNode->GetNavDestinationNode(curPath.second));
1122             if (!curDestination || !curDestination->GetLayoutProperty()) {
1123                 continue;
1124             }
1125             auto navDestinationPattern = curDestination->GetPattern<NavDestinationPattern>();
1126             CHECK_NULL_VOID(navDestinationPattern);
1127             auto property = curDestination->GetLayoutProperty();
1128             if (property->GetVisibilityValue(VisibleType::VISIBLE) != VisibleType::VISIBLE ||
1129                 !curDestination->IsActive() || navDestinationPattern->GetIsOnShow() == isOnShow) {
1130                 continue;
1131             }
1132             auto eventHub = curDestination->GetEventHub<NavDestinationEventHub>();
1133             CHECK_NULL_VOID(eventHub);
1134             auto param = Recorder::EventRecorder::Get().IsPageParamRecordEnable() ?
1135                 navigationPattern->navigationStack_->GetRouteParam() : "";
1136             eventHub->FireOnShownEvent(navDestinationPattern->GetName(), param);
1137             navDestinationPattern->SetIsOnShow(true);
1138             NavigationPattern::FireNavigationChange(curDestination, true, false);
1139             NavigationPattern::NotifyPerfMonitorPageMsg(navDestinationPattern->GetName());
1140         }
1141         return;
1142     }
1143     for (int32_t index = end - 1; index >= 0 && index >= start; index--) {
1144         const auto& curPath = navDestinationNodes[index];
1145         auto curDestination = AceType::DynamicCast<NavDestinationGroupNode>(
1146             navigationNode->GetNavDestinationNode(curPath.second));
1147         if (!curDestination || !curDestination->GetLayoutProperty()) {
1148             continue;
1149         }
1150         auto navDestinationPattern = curDestination->GetPattern<NavDestinationPattern>();
1151         CHECK_NULL_VOID(navDestinationPattern);
1152         auto property = curDestination->GetLayoutProperty();
1153         if (property->GetVisibilityValue(VisibleType::VISIBLE) != VisibleType::VISIBLE ||
1154             !curDestination->IsActive() || navDestinationPattern->GetIsOnShow() == isOnShow) {
1155             continue;
1156         }
1157         auto eventHub = curDestination->GetEventHub<NavDestinationEventHub>();
1158         CHECK_NULL_VOID(eventHub);
1159         eventHub->FireOnHiddenEvent(navDestinationPattern->GetName());
1160         navDestinationPattern->SetIsOnShow(false);
1161         NavigationPattern::FireNavigationChange(curDestination, false, false);
1162     }
1163 }
1164 
FireNavigationChange(const RefPtr<UINode> & node,bool isOnShow,bool isFirst)1165 void NavigationPattern::FireNavigationChange(const RefPtr<UINode>& node, bool isOnShow, bool isFirst)
1166 {
1167     CHECK_NULL_VOID(node);
1168     if (isFirst) {
1169         FireNavigationInner(node, isOnShow);
1170         return;
1171     }
1172     const auto children = node->GetChildren();
1173     for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
1174         auto& child = *iter;
1175         FireNavigationInner(child, isOnShow);
1176     }
1177 }
1178 
FireNavigationLifecycleChange(const RefPtr<UINode> & node,NavDestinationLifecycle lifecycle)1179 void NavigationPattern::FireNavigationLifecycleChange(const RefPtr<UINode>& node, NavDestinationLifecycle lifecycle)
1180 {
1181     CHECK_NULL_VOID(node);
1182     const auto children = node->GetChildren(true);
1183     for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
1184         auto& child = *iter;
1185         auto navigation = AceType::DynamicCast<NavigationGroupNode>(child);
1186         if (navigation) {
1187             auto destinationNode = navigation->GetParentDestinationNode().Upgrade();
1188             if ((lifecycle == NavDestinationLifecycle::ON_SHOW) && CheckParentDestinationIsOnhide(destinationNode) &&
1189                 CheckDestinationIsPush(destinationNode)) {
1190                 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation parent is onhide");
1191                 continue;
1192             }
1193             auto navigationPattern = AceType::DynamicCast<NavigationPattern>(navigation->GetPattern());
1194             CHECK_NULL_VOID(navigationPattern);
1195             navigationPattern->FireNavDestinationStateChange(lifecycle);
1196         } else {
1197             NavigationPattern::FireNavigationLifecycleChange(child, lifecycle);
1198         }
1199     }
1200 }
1201 
NotifyPageHide(const std::string & pageName)1202 void NavigationPattern::NotifyPageHide(const std::string& pageName)
1203 {
1204     auto container = Container::Current();
1205     CHECK_NULL_VOID(container);
1206     auto pageUrlChecker = container->GetPageUrlChecker();
1207     CHECK_NULL_VOID(pageUrlChecker);
1208     pageUrlChecker->NotifyPageHide(pageName);
1209 }
1210 
NotifyPageShow(const std::string & pageName)1211 void NavigationPattern::NotifyPageShow(const std::string& pageName)
1212 {
1213     auto container = Container::Current();
1214     CHECK_NULL_VOID(container);
1215     auto pageUrlChecker = container->GetPageUrlChecker();
1216     CHECK_NULL_VOID(pageUrlChecker);
1217     pageUrlChecker->NotifyPageShow(pageName);
1218     if (PerfMonitor::GetPerfMonitor() != nullptr) {
1219         PerfMonitor::GetPerfMonitor()->SetPageName(pageName);
1220     }
1221 }
1222 
ProcessPageShowEvent()1223 void NavigationPattern::ProcessPageShowEvent()
1224 {
1225     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1226     CHECK_NULL_VOID(hostNode);
1227     auto context = hostNode->GetContext();
1228     CHECK_NULL_VOID(context);
1229     auto stageManager = context->GetStageManager();
1230     if (stageManager) {
1231         RefPtr<FrameNode> pageNode = stageManager->GetLastPage();
1232         CHECK_NULL_VOID(pageNode);
1233         auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
1234         CHECK_NULL_VOID(pagePattern);
1235         auto pageInfo = pagePattern->GetPageInfo();
1236         CHECK_NULL_VOID(pageInfo);
1237         NotifyPageShow(pageInfo->GetPageUrl());
1238     }
1239 }
1240 
ReplaceAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination)1241 void NavigationPattern::ReplaceAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
1242     const RefPtr<NavDestinationGroupNode>& newTopNavDestination)
1243 {
1244     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1245     CHECK_NULL_VOID(navigationNode);
1246     auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationNode->GetNavBarNode());
1247     CHECK_NULL_VOID(navBarNode);
1248     bool preUseCustomTransition = TriggerNavDestinationTransition(
1249         preTopNavDestination, NavigationOperation::REPLACE, false) != INVALID_ANIMATION_ID;
1250     TriggerNavDestinationTransition(newTopNavDestination, NavigationOperation::REPLACE, true);
1251     if (newTopNavDestination && preTopNavDestination && !preUseCustomTransition) {
1252         navigationNode->DealNavigationExit(preTopNavDestination, false, false);
1253     } else if (newTopNavDestination && navigationMode_ == NavigationMode::STACK) {
1254         navigationNode->DealNavigationExit(navBarNode, true, false);
1255     }
1256     navigationNode->RemoveDialogDestination();
1257     auto id = navigationNode->GetTopDestination() ? navigationNode->GetTopDestination()->GetAccessibilityId() : -1;
1258     navigationNode->OnAccessibilityEvent(
1259         AccessibilityEventType::PAGE_CHANGE, id, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID);
1260     navigationStack_->UpdateReplaceValue(0);
1261 }
1262 
TransitionWithOutAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage,bool needVisible)1263 void NavigationPattern::TransitionWithOutAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
1264     const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage, bool needVisible)
1265 {
1266     ClearRecoveryList();
1267     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1268     CHECK_NULL_VOID(navigationNode);
1269     auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationNode->GetNavBarNode());
1270     CHECK_NULL_VOID(navBarNode);
1271 
1272     // replace
1273     auto replaceVal = navigationStack_->GetReplaceValue();
1274     if (replaceVal != 0) {
1275         ReplaceAnimation(preTopNavDestination, newTopNavDestination);
1276         return;
1277     }
1278 
1279     // navDestination push/pop navDestination
1280     if (newTopNavDestination && preTopNavDestination) {
1281         if (isPopPage) {
1282             newTopNavDestination->SetTransitionType(PageTransitionType::ENTER_POP);
1283             preTopNavDestination->CleanContent(false, true);
1284             auto parent = preTopNavDestination->GetParent();
1285             CHECK_NULL_VOID(parent);
1286             parent->RemoveChild(preTopNavDestination, true);
1287             parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1288         } else {
1289             preTopNavDestination->GetRenderContext()->RemoveClipWithRRect();
1290             preTopNavDestination->SetTransitionType(PageTransitionType::EXIT_PUSH);
1291             newTopNavDestination->SetTransitionType(PageTransitionType::ENTER_PUSH);
1292             DealTransitionVisibility(preTopNavDestination, needVisible, false);
1293             if (preTopNavDestination->NeedRemoveInPush()) {
1294                 preTopNavDestination->CleanContent(false, true);
1295                 auto parent = preTopNavDestination->GetParent();
1296                 CHECK_NULL_VOID(parent);
1297                 parent->RemoveChild(preTopNavDestination, true);
1298                 parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1299             }
1300         }
1301         navigationNode->RemoveDialogDestination();
1302         auto id = navigationNode->GetTopDestination() ? navigationNode->GetTopDestination()->GetAccessibilityId() : -1;
1303         navigationNode->OnAccessibilityEvent(
1304             AccessibilityEventType::PAGE_CHANGE, id, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID);
1305         return;
1306     }
1307 
1308     // navBar push navDestination
1309     if (newTopNavDestination && newTopNavDestination->GetNavDestinationMode() == NavDestinationMode::STANDARD) {
1310         newTopNavDestination->SetTransitionType(PageTransitionType::ENTER_PUSH);
1311         auto navBar = AceType::DynamicCast<NavBarNode>(navBarNode);
1312         // current mode is stack, set navBar invisible
1313         if (navigationMode_ == NavigationMode::STACK && navBar) {
1314             navBar->SetTransitionType(PageTransitionType::EXIT_PUSH);
1315             DealTransitionVisibility(navBarNode, false, true);
1316         }
1317         // if current mode is auto, need set navBar need set invisible true
1318         navigationNode->SetNeedSetInvisible(true);
1319     }
1320 
1321     // navDestination pop to navBar
1322     if (preTopNavDestination) {
1323         preTopNavDestination->CleanContent(false, true);
1324         auto parent = preTopNavDestination->GetParent();
1325         CHECK_NULL_VOID(parent);
1326         parent->RemoveChild(preTopNavDestination, true);
1327         navigationNode->SetNeedSetInvisible(false);
1328         auto navBar = AceType::DynamicCast<NavBarNode>(navBarNode);
1329         if (navBar) {
1330             navBar->SetTransitionType(PageTransitionType::ENTER_POP);
1331         }
1332         parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1333     }
1334     navigationNode->RemoveDialogDestination();
1335     auto id = navigationNode->GetTopDestination() ? navigationNode->GetTopDestination()->GetAccessibilityId() : -1;
1336     navigationNode->OnAccessibilityEvent(
1337         AccessibilityEventType::PAGE_CHANGE, id, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID);
1338 }
1339 
TransitionWithAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage,bool isNeedVisible)1340 void NavigationPattern::TransitionWithAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
1341     const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage, bool isNeedVisible)
1342 {
1343     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1344     CHECK_NULL_VOID(navigationNode);
1345     auto layoutProperty = navigationNode->GetLayoutProperty<NavigationLayoutProperty>();
1346     CHECK_NULL_VOID(layoutProperty);
1347     if (layoutProperty->GetHideNavBarValue(false) && (!newTopNavDestination || !preTopNavDestination)) {
1348         // hide navBarNode and need to do animation with navBarNode
1349         if (preTopNavDestination) {
1350             // remove preTopNavDestination node in pop
1351             auto parent = preTopNavDestination->GetParent();
1352             CHECK_NULL_VOID(parent);
1353             preTopNavDestination->CleanContent();
1354             parent->RemoveChild(preTopNavDestination);
1355             parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1356         }
1357         navigationNode->RemoveDialogDestination();
1358         ClearRecoveryList();
1359         return;
1360     }
1361     if (isCustomAnimation_ && TriggerCustomAnimation(preTopNavDestination, newTopNavDestination, isPopPage)) {
1362         auto operation = NavigationOperation::REPLACE;
1363         if (navigationStack_->GetReplaceValue() == 0) {
1364             operation = isPopPage ? NavigationOperation::POP : NavigationOperation::PUSH;
1365         }
1366         TriggerNavDestinationTransition(preTopNavDestination, operation, false);
1367         TriggerNavDestinationTransition(newTopNavDestination, operation, true);
1368         return;
1369     }
1370     StartDefaultAnimation(preTopNavDestination, newTopNavDestination, isPopPage, isNeedVisible);
1371 }
1372 
DialogAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage,bool isNeedVisible)1373 void NavigationPattern::DialogAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
1374     const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage, bool isNeedVisible)
1375 {
1376     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_THIRTEEN)) {
1377         TransitionWithDialogAnimation(preTopNavDestination, newTopNavDestination, isPopPage);
1378     } else {
1379         TransitionWithOutAnimation(preTopNavDestination, newTopNavDestination, isPopPage, isNeedVisible);
1380     }
1381 }
1382 
StartDefaultAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage,bool isNeedVisible)1383 void NavigationPattern::StartDefaultAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
1384     const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage, bool isNeedVisible)
1385 {
1386     auto currentProxy = GetTopNavigationProxy();
1387     if (currentProxy) {
1388         currentProxy->SetIsFinished(true);
1389     }
1390     ClearRecoveryList();
1391     bool isPreDialog = preTopNavDestination &&
1392         preTopNavDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG;
1393     bool isNewDialog = newTopNavDestination &&
1394         newTopNavDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG;
1395     if (isPreDialog || isNewDialog) {
1396         DialogAnimation(preTopNavDestination, newTopNavDestination, isPopPage, isNeedVisible);
1397         return;
1398     }
1399     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1400     CHECK_NULL_VOID(navigationNode);
1401     auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationNode->GetNavBarNode());
1402     CHECK_NULL_VOID(navBarNode);
1403     // replace
1404     auto replaceValue = navigationStack_->GetReplaceValue();
1405     if (replaceValue != 0) {
1406         if (newTopNavDestination && preTopNavDestination) {
1407             navigationNode->TransitionWithReplace(preTopNavDestination, newTopNavDestination, false);
1408         } else if (newTopNavDestination && navigationMode_ == NavigationMode::STACK) {
1409             navigationNode->TransitionWithReplace(navBarNode, newTopNavDestination, true);
1410         }
1411         navigationStack_->UpdateReplaceValue(0);
1412         return;
1413     }
1414     // navDestination push/pop navDestination
1415     if (newTopNavDestination && preTopNavDestination) {
1416         if (isPopPage) {
1417             navigationNode->TransitionWithPop(preTopNavDestination, newTopNavDestination);
1418         } else {
1419             navigationNode->TransitionWithPush(preTopNavDestination, newTopNavDestination);
1420         }
1421         return;
1422     }
1423     // navBar push navDestination
1424     if (newTopNavDestination && navigationMode_ == NavigationMode::STACK) {
1425         navigationNode->TransitionWithPush(navBarNode, newTopNavDestination, true);
1426         return;
1427     }
1428     // navDestination pop to navBar
1429     if (preTopNavDestination) {
1430         if (navigationMode_ == NavigationMode::SPLIT) {
1431             navigationNode->TransitionWithPop(preTopNavDestination, nullptr);
1432         }
1433         if (navigationMode_ == NavigationMode::STACK) {
1434             navigationNode->TransitionWithPop(preTopNavDestination, navBarNode, true);
1435         }
1436     }
1437 }
1438 
OnVisibleChange(bool isVisible)1439 void NavigationPattern::OnVisibleChange(bool isVisible)
1440 {
1441     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1442     CHECK_NULL_VOID(hostNode);
1443     auto eventHub = hostNode->GetEventHub<NavigationEventHub>();
1444     CHECK_NULL_VOID(eventHub);
1445     eventHub->FireNavBarStateChangeEvent(isVisible);
1446 }
1447 
OnNavBarStateChange(bool modeChange)1448 void NavigationPattern::OnNavBarStateChange(bool modeChange)
1449 {
1450     auto layoutProperty = GetLayoutProperty<NavigationLayoutProperty>();
1451     CHECK_NULL_VOID(layoutProperty);
1452     auto visibilityValue = layoutProperty->GetVisibilityValue(VisibleType::VISIBLE);
1453     if (visibilityValue != VisibleType::VISIBLE) {
1454         return;
1455     }
1456 
1457     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1458     CHECK_NULL_VOID(hostNode);
1459     auto eventHub = hostNode->GetEventHub<NavigationEventHub>();
1460     CHECK_NULL_VOID(eventHub);
1461     auto currentNavigationMode = GetNavigationMode();
1462 
1463     auto lastStandardIndex = hostNode->GetLastStandardIndex();
1464     if (modeChange) {
1465         bool navbarIsHidden = (currentNavigationMode == NavigationMode::STACK && lastStandardIndex >= 0) ||
1466                               layoutProperty->GetHideNavBar().value_or(false);
1467         eventHub->FireNavBarStateChangeEvent(!navbarIsHidden);
1468         SetNavBarVisibilityChange(false);
1469         return;
1470     }
1471 
1472     if (GetNavBarVisibilityChange()) {
1473         if (!layoutProperty->GetHideNavBarValue(false)) {
1474             eventHub->FireNavBarStateChangeEvent(true);
1475         } else {
1476             eventHub->FireNavBarStateChangeEvent(false);
1477         }
1478         SetNavBarVisibilityChange(false);
1479         return;
1480     }
1481 
1482     if (currentNavigationMode == NavigationMode::STACK) {
1483         bool navbarIsHidden = (lastStandardIndex >= 0) || layoutProperty->GetHideNavBar().value_or(false);
1484         eventHub->FireNavBarStateChangeEvent(!navbarIsHidden);
1485     }
1486 }
1487 
OnNavigationModeChange(bool modeChange)1488 void NavigationPattern::OnNavigationModeChange(bool modeChange)
1489 {
1490     if (!modeChange) {
1491         return;
1492     }
1493     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1494     CHECK_NULL_VOID(hostNode);
1495     auto eventHub = hostNode->GetEventHub<NavigationEventHub>();
1496     CHECK_NULL_VOID(eventHub);
1497     eventHub->FireNavigationModeChangeEvent(navigationMode_);
1498     // fire navigation stack navigation mode change event
1499     navigationStack_->FireNavigationModeChange(navigationMode_);
1500 }
1501 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)1502 bool NavigationPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
1503 {
1504     if (config.skipMeasure && config.skipLayout) {
1505         return false;
1506     }
1507     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1508     CHECK_NULL_RETURN(hostNode, false);
1509     UpdateIsFullPageNavigation(hostNode);
1510     if (navigationModeChange_) {
1511         if (NavigationMode::STACK == navigationMode_) {
1512             // Set focus on navDestination when mode changes to STACK
1513             RefreshFocusToDestination();
1514         }
1515         AbortAnimation(hostNode);
1516     }
1517     auto context = PipelineContext::GetCurrentContext();
1518     if (context) {
1519         context->GetTaskExecutor()->PostTask(
1520             [weak = WeakClaim(this), navigationStackWeak = WeakPtr<NavigationStack>(navigationStack_),
1521                 navigationWeak = WeakPtr<NavigationGroupNode>(hostNode)] {
1522                 auto pattern = weak.Upgrade();
1523                 CHECK_NULL_VOID(pattern);
1524                 auto navigationGroupNode = navigationWeak.Upgrade();
1525                 CHECK_NULL_VOID(navigationGroupNode);
1526                 auto navigationLayoutProperty =
1527                     AceType::DynamicCast<NavigationLayoutProperty>(navigationGroupNode->GetLayoutProperty());
1528                 CHECK_NULL_VOID(navigationLayoutProperty);
1529                 auto navigationStack = navigationStackWeak.Upgrade();
1530                 CHECK_NULL_VOID(navigationStack);
1531                 auto curTopNavPath = navigationStack->GetTopNavPath();
1532                 if (curTopNavPath.has_value()) {
1533                     // considering backButton visibility
1534                     auto curTopNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(
1535                         NavigationGroupNode::GetNavDestinationNode(curTopNavPath->second));
1536                     pattern->UpdateContextRect(curTopNavDestination, navigationGroupNode);
1537                 }
1538                 // considering navBar visibility
1539                 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationGroupNode->GetNavBarNode());
1540                 CHECK_NULL_VOID(navBarNode);
1541                 auto navBarLayoutProperty = navBarNode->GetLayoutProperty<NavBarLayoutProperty>();
1542                 CHECK_NULL_VOID(navBarLayoutProperty);
1543                 auto lastStandardIndex = navigationGroupNode->GetLastStandardIndex();
1544                 bool isSetInvisible = navigationGroupNode->GetNeedSetInvisible() && navigationStack->Size() != 0 &&
1545                     lastStandardIndex >= 0;
1546                 if (navigationLayoutProperty->GetHideNavBar().value_or(false) ||
1547                     (pattern->GetNavigationMode() == NavigationMode::STACK && isSetInvisible)) {
1548                     navBarLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
1549                     navBarNode->SetJSViewActive(false);
1550                 } else {
1551                     navBarNode->GetRenderContext()->UpdateOpacity(1.0f);
1552                     navBarLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
1553                     navBarNode->SetJSViewActive(true);
1554                 }
1555                 auto navigationContentNode = AceType::DynamicCast<FrameNode>(navigationGroupNode->GetContentNode());
1556                 CHECK_NULL_VOID(navigationContentNode);
1557                 auto navDestinationNode =
1558                     AceType::DynamicCast<NavDestinationGroupNode>(navigationContentNode->GetLastChild());
1559                 CHECK_NULL_VOID(navDestinationNode);
1560                 auto navDestinationPattern = navDestinationNode->GetPattern<NavDestinationPattern>();
1561                 auto navDestinationFocusHub = navDestinationNode->GetFocusHub();
1562                 CHECK_NULL_VOID(navDestinationFocusHub);
1563                 auto defaultFocusHub = navDestinationFocusHub->GetChildFocusNodeByType(FocusNodeType::DEFAULT);
1564                 if (!defaultFocusHub && navDestinationNode->GetChildren(true).size() <= EMPTY_DESTINATION_CHILD_SIZE &&
1565                     navDestinationPattern->GetBackButtonState()) {
1566                     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navDestinationNode->GetTitleBarNode());
1567                     CHECK_NULL_VOID(titleBarNode);
1568                     auto backButtonNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetBackButton());
1569                     backButtonNode->GetOrCreateFocusHub()->SetIsDefaultFocus(true);
1570                     auto navigation = pattern->GetHost();
1571                     CHECK_NULL_VOID(navigation);
1572                     auto navigationFocusHub = navigation->GetFocusHub();
1573                     CHECK_NULL_VOID(navigationFocusHub);
1574                     auto navDestinationFocusView = navDestinationNode->GetPattern<FocusView>();
1575                     if (navigationFocusHub->IsCurrentFocus() && navDestinationFocusView) {
1576                         if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1577                             navDestinationFocusView->SetIsViewRootScopeFocused(false);
1578                         }
1579                         navDestinationFocusView->FocusViewShow();
1580                     }
1581                 }
1582             },
1583             TaskExecutor::TaskType::UI, "ArkUINavigationDirtyLayoutWrapperSwap",
1584             TaskExecutor::GetPriorityTypeWithCheck(PriorityType::VIP));
1585     }
1586     auto navigationLayoutProperty = AceType::DynamicCast<NavigationLayoutProperty>(hostNode->GetLayoutProperty());
1587     CHECK_NULL_RETURN(navigationLayoutProperty, false);
1588     UpdateTitleModeChangeEventHub(hostNode);
1589     FireNavBarWidthChangeEvent(dirty);
1590     AddDragBarHotZoneRect();
1591     AddDividerHotZoneRect();
1592     ifNeedInit_ = false;
1593     return false;
1594 }
1595 
AbortAnimation(RefPtr<NavigationGroupNode> & hostNode)1596 void NavigationPattern::AbortAnimation(RefPtr<NavigationGroupNode>& hostNode)
1597 {
1598     TAG_LOGD(AceLogTag::ACE_NAVIGATION, "Aborting navigation animations");
1599     if (!hostNode->GetPushAnimations().empty()) {
1600         auto pushAnimations = hostNode->GetPushAnimations();
1601         for (const auto& animation : pushAnimations) {
1602             if (animation) {
1603                 AnimationUtils::StopAnimation(animation);
1604             }
1605         }
1606     }
1607     if (!hostNode->GetPopAnimations().empty()) {
1608         auto popAnimations = hostNode->GetPopAnimations();
1609         for (const auto& animation : popAnimations) {
1610             if (animation) {
1611                 AnimationUtils::StopAnimation(animation);
1612             }
1613         }
1614     }
1615     hostNode->CleanPushAnimations();
1616     hostNode->CleanPopAnimations();
1617 }
1618 
UpdateContextRect(const RefPtr<NavDestinationGroupNode> & curDestination,const RefPtr<NavigationGroupNode> & hostNode)1619 void NavigationPattern::UpdateContextRect(
1620     const RefPtr<NavDestinationGroupNode>& curDestination, const RefPtr<NavigationGroupNode>& hostNode)
1621 {
1622     CHECK_NULL_VOID(curDestination);
1623     CHECK_NULL_VOID(hostNode);
1624     auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
1625     CHECK_NULL_VOID(navBarNode);
1626     auto navigationPattern = AceType::DynamicCast<NavigationPattern>(hostNode->GetPattern());
1627     CHECK_NULL_VOID(navigationPattern);
1628 
1629     if (navigationPattern->GetNavigationMode() == NavigationMode::STACK) {
1630         curDestination->GetRenderContext()->SetActualForegroundColor(Color::TRANSPARENT);
1631         return;
1632     }
1633     auto navigationLayoutProperty = hostNode->GetLayoutProperty<NavigationLayoutProperty>();
1634     CHECK_NULL_VOID(navigationLayoutProperty);
1635     auto navBarProperty = navBarNode->GetLayoutProperty();
1636     navBarProperty->UpdateVisibility(VisibleType::VISIBLE);
1637     navBarNode->SetJSViewActive(true);
1638     if (!curDestination->IsOnAnimation()) {
1639         curDestination->GetRenderContext()->UpdateTranslateInXY(OffsetF { 0.0f, 0.0f });
1640         curDestination->GetRenderContext()->SetActualForegroundColor(Color::TRANSPARENT);
1641         navBarNode->GetEventHub<EventHub>()->SetEnabledInternal(true);
1642         auto titleBarNode = DynamicCast<TitleBarNode>(navBarNode->GetTitleBarNode());
1643         CHECK_NULL_VOID(titleBarNode);
1644         auto titleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
1645         CHECK_NULL_VOID(titleNode);
1646         titleNode->GetRenderContext()->UpdateTranslateInXY(OffsetF { 0.0f, 0.0f });
1647     }
1648 }
1649 
UpdateTitleModeChangeEventHub(const RefPtr<NavigationGroupNode> & hostNode)1650 bool NavigationPattern::UpdateTitleModeChangeEventHub(const RefPtr<NavigationGroupNode>& hostNode)
1651 {
1652     auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
1653     CHECK_NULL_RETURN(navBarNode, false);
1654     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navBarNode->GetTitleBarNode());
1655     CHECK_NULL_RETURN(titleBarNode, false);
1656     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
1657     CHECK_NULL_RETURN(titleBarLayoutProperty, false);
1658     auto eventHub = hostNode->GetEventHub<NavigationEventHub>();
1659     CHECK_NULL_RETURN(eventHub, false);
1660     if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) == NavigationTitleMode::FREE) {
1661         auto titleBarPattern = AceType::DynamicCast<TitleBarPattern>(titleBarNode->GetPattern());
1662         CHECK_NULL_RETURN(titleBarPattern, false);
1663         NavigationTitleMode titleMode = titleBarPattern->GetNavigationTitleMode();
1664         if (titleMode != NavigationTitleMode::FREE && titleMode_ != titleMode) {
1665             NavigationTitleModeChangeEvent navigationTitleModeChange(titleMode == NavigationTitleMode::MINI);
1666             eventHub->FireChangeEvent(&navigationTitleModeChange);
1667             titleMode_ = titleMode;
1668         }
1669     }
1670     return true;
1671 }
1672 
FireNavBarWidthChangeEvent(const RefPtr<LayoutWrapper> & layoutWrapper)1673 void NavigationPattern::FireNavBarWidthChangeEvent(const RefPtr<LayoutWrapper>& layoutWrapper)
1674 {
1675     auto host = GetHost();
1676     CHECK_NULL_VOID(host);
1677     auto geometryNode = host->GetGeometryNode();
1678     CHECK_NULL_VOID(geometryNode);
1679     auto frameSize = geometryNode->GetFrameSize();
1680     auto frameWidth = frameSize.Width();
1681     auto navigationLayoutProperty = GetLayoutProperty<NavigationLayoutProperty>();
1682     CHECK_NULL_VOID(navigationLayoutProperty);
1683     auto userSetDimensionUnit = navigationLayoutProperty->GetNavBarWidthValue(DEFAULT_NAV_BAR_WIDTH).Unit();
1684     CHECK_NULL_VOID(layoutWrapper);
1685     auto layoutAlgorithm = layoutWrapper->GetLayoutAlgorithm();
1686     CHECK_NULL_VOID(layoutAlgorithm);
1687     auto navigationLayoutAlgorithm = AceType::DynamicCast<NavigationLayoutAlgorithm>(
1688         layoutAlgorithm->GetLayoutAlgorithm());
1689     CHECK_NULL_VOID(navigationLayoutAlgorithm);
1690     auto realBavBarWidth = navigationLayoutAlgorithm->GetRealNavBarWidth();
1691     auto realNavBarWidthDimension = Dimension(realBavBarWidth, DimensionUnit::PX);
1692     Dimension usrSetUnitWidth = Dimension(0.0, userSetDimensionUnit);
1693     if (!NearZero(frameWidth)) {
1694         usrSetUnitWidth = DimensionUnit::PERCENT == userSetDimensionUnit ?
1695             Dimension(realBavBarWidth / frameWidth, DimensionUnit::PERCENT) :
1696             Dimension(realNavBarWidthDimension.GetNativeValue(userSetDimensionUnit), userSetDimensionUnit);
1697     }
1698     auto eventHub = host->GetEventHub<NavigationEventHub>();
1699     CHECK_NULL_VOID(eventHub);
1700     eventHub->FireNavBarWidthChangeEvent(usrSetUnitWidth);
1701 }
1702 
GenerateUINodeFromRecovery(int32_t lastStandardIndex,NavPathList & navPathList)1703 int32_t NavigationPattern::GenerateUINodeFromRecovery(int32_t lastStandardIndex, NavPathList& navPathList)
1704 {
1705     /**
1706      * In case several pages at the top of stack are dialog pages.
1707      * We need to recovery node until a standard page created.
1708      * And the creation process should be bottom-up to satisfy the order of life-cycle.
1709      */
1710     int32_t jsStackSize = static_cast<int32_t>(navPathList.size());
1711     int32_t removeSize = 0;
1712     for (int32_t index = lastStandardIndex; index < jsStackSize; ++ index) {
1713         if (navPathList[index].second || !navigationStack_->IsFromRecovery(index)) {
1714             continue;
1715         }
1716         if (!GenerateUINodeByIndex(index - removeSize, navPathList[index].second)) {
1717             removeSize++;
1718             continue;
1719         }
1720         navigationStack_->SetFromRecovery(index, false);
1721         auto navdestination = AceType::DynamicCast<NavDestinationGroupNode>(
1722             NavigationGroupNode::GetNavDestinationNode(navPathList[index].second));
1723         navdestination->SetNeedAppearFromRecovery(true);
1724     }
1725     return removeSize;
1726 }
1727 
GenerateUINodeByIndex(int32_t index,RefPtr<UINode> & node)1728 bool NavigationPattern::GenerateUINodeByIndex(int32_t index, RefPtr<UINode>& node)
1729 {
1730     auto host = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1731     do {
1732         if (parentNode_.Upgrade() || !host) {
1733             break;
1734         }
1735         auto context = host->GetContext();
1736         // Avoid the loading problem of atomicservice on the home page
1737         if ((context && !context->GetInstallationFree()) || !context) {
1738             break;
1739         }
1740         RefPtr<UINode> parentCustomNode;
1741         auto curNode = host->GetParent();
1742         while (curNode) {
1743             auto curTag = curNode->GetTag();
1744             if (curTag == V2::JS_VIEW_ETS_TAG) {
1745                 parentCustomNode = curNode;
1746                 break;
1747             }
1748             curNode = curNode->GetParent();
1749         }
1750         auto pattern = host->GetPattern<NavigationPattern>();
1751         if (pattern && parentCustomNode) {
1752             pattern->SetParentCustomNode(parentCustomNode);
1753         }
1754     } while (false);
1755     bool isCreate = navigationStack_->CreateNodeByIndex(index, parentNode_, node);
1756     if (node) {
1757         node->SetFreeze(true, true);
1758     }
1759     auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(
1760         NavigationGroupNode::GetNavDestinationNode(node));
1761     CHECK_NULL_RETURN(navDestinationNode, isCreate);
1762     // set navigation id
1763     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1764     auto navDestinationPattern = AceType::DynamicCast<NavDestinationPattern>(navDestinationNode->GetPattern());
1765     if (navigationNode && navDestinationPattern) {
1766         navDestinationPattern->SetNavigationNode(navigationNode);
1767         navDestinationPattern->SetNavigationId(navigationNode->GetInspectorId().value_or(""));
1768     }
1769     auto eventHub = navDestinationNode->GetEventHub<NavDestinationEventHub>();
1770     CHECK_NULL_RETURN(eventHub, isCreate);
1771     eventHub->FireOnWillAppear();
1772     return isCreate;
1773 }
1774 
InitDividerMouseEvent(const RefPtr<InputEventHub> & inputHub)1775 void NavigationPattern::InitDividerMouseEvent(const RefPtr<InputEventHub>& inputHub)
1776 {
1777     CHECK_NULL_VOID(inputHub);
1778     CHECK_NULL_VOID(!hoverEvent_);
1779 
1780     auto hoverTask = [weak = WeakClaim(this)](bool isHover) {
1781         auto pattern = weak.Upgrade();
1782         if (pattern) {
1783             pattern->OnHover(isHover);
1784         }
1785     };
1786     hoverEvent_ = MakeRefPtr<InputEvent>(std::move(hoverTask));
1787     inputHub->AddOnHoverEvent(hoverEvent_);
1788 }
1789 
HandleDragStart()1790 void NavigationPattern::HandleDragStart()
1791 {
1792     preNavBarWidth_ = realNavBarWidth_;
1793     if (!isDividerDraggable_) {
1794         return;
1795     }
1796     isInDividerDrag_ = true;
1797     if (!enableDragBar_) {
1798         SetMouseStyle(MouseFormat::RESIZE_LEFT_RIGHT);
1799     }
1800 }
1801 
HandleDragUpdate(float xOffset)1802 void NavigationPattern::HandleDragUpdate(float xOffset)
1803 {
1804     auto navigationLayoutProperty = GetLayoutProperty<NavigationLayoutProperty>();
1805     CHECK_NULL_VOID(navigationLayoutProperty);
1806     auto host = GetHost();
1807     CHECK_NULL_VOID(host);
1808     auto geometryNode = host->GetGeometryNode();
1809     CHECK_NULL_VOID(geometryNode);
1810     auto frameSize = geometryNode->GetFrameSize();
1811     auto frameWidth = frameSize.Width();
1812     auto constraint = navigationLayoutProperty->GetLayoutConstraint();
1813     auto parentSize = CreateIdealSize(constraint.value(), Axis::HORIZONTAL, MeasureType::MATCH_PARENT);
1814 
1815     float minNavBarWidthPx = minNavBarWidthValue_.ConvertToPxWithSize(parentSize.Width().value_or(0.0f));
1816     float maxNavBarWidthPx = maxNavBarWidthValue_.ConvertToPxWithSize(parentSize.Width().value_or(0.0f));
1817     float minContentWidthPx = minContentWidthValue_.ConvertToPxWithSize(parentSize.Width().value_or(0.0f));
1818     auto dividerWidth = static_cast<float>(DIVIDER_WIDTH.ConvertToPx());
1819 
1820     auto navigationPosition = navigationLayoutProperty->GetNavBarPosition().value_or(NavBarPosition::START);
1821     bool isNavBarStart = navigationPosition == NavBarPosition::START;
1822     auto navBarLine = isRightToLeft_ ? preNavBarWidth_ + (isNavBarStart ? -xOffset : xOffset)
1823                                      : preNavBarWidth_ + (isNavBarStart ? xOffset : -xOffset);
1824     float currentNavBarWidth = realNavBarWidth_;
1825 
1826     if (maxNavBarWidthPx + dividerWidth + minContentWidthPx > frameWidth) {
1827         maxNavBarWidthPx = frameWidth - minContentWidthPx - dividerWidth;
1828     }
1829     navBarLine = std::min(navBarLine, maxNavBarWidthPx);
1830 
1831     if (userSetMinContentFlag_ && !userSetNavBarRangeFlag_) {
1832         if (minContentWidthPx >= frameWidth) {
1833             realNavBarWidth_ = 0.0f;
1834         } else if (navBarLine + dividerWidth + minContentWidthPx <= frameWidth) {
1835             realNavBarWidth_ = navBarLine;
1836         } else {
1837             realNavBarWidth_ = frameWidth - minContentWidthPx - dividerWidth;
1838         }
1839     } else {
1840         realDividerWidth_ = dividerWidth;
1841         float remainingSpace = frameWidth - navBarLine - dividerWidth;
1842         if (remainingSpace >= minContentWidthPx) {
1843             realNavBarWidth_ = navBarLine;
1844         } else if (remainingSpace < minContentWidthPx && navBarLine > minNavBarWidthPx) {
1845             realNavBarWidth_ = frameWidth - minContentWidthPx - dividerWidth;
1846         } else {
1847             realNavBarWidth_ = minNavBarWidthPx;
1848         }
1849     }
1850     realNavBarWidth_ = std::min(realNavBarWidth_, frameWidth);
1851     realNavBarWidth_ = std::min(realNavBarWidth_, maxNavBarWidthPx);
1852     realNavBarWidth_ = std::max(realNavBarWidth_, minNavBarWidthPx);
1853     // MEASURE
1854     if (realNavBarWidth_ != currentNavBarWidth) {
1855         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
1856     }
1857 }
1858 
HandleDragEnd()1859 void NavigationPattern::HandleDragEnd()
1860 {
1861     preNavBarWidth_ = realNavBarWidth_;
1862     if (!isDividerDraggable_) {
1863         return;
1864     }
1865     isInDividerDrag_ = false;
1866     SetMouseStyle(MouseFormat::DEFAULT);
1867 }
1868 
InitDividerPanEvent(const RefPtr<GestureEventHub> & gestureHub)1869 void NavigationPattern::InitDividerPanEvent(const RefPtr<GestureEventHub>& gestureHub)
1870 {
1871     CHECK_NULL_VOID(!panEvent_);
1872     auto actionStartTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1873         auto pattern = weak.Upgrade();
1874         CHECK_NULL_VOID(pattern);
1875         pattern->HandleDragStart();
1876     };
1877     auto actionUpdateTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1878         auto pattern = weak.Upgrade();
1879         CHECK_NULL_VOID(pattern);
1880         pattern->HandleDragUpdate(static_cast<float>(info.GetOffsetX()));
1881     };
1882     auto actionEndTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1883         auto pattern = weak.Upgrade();
1884         CHECK_NULL_VOID(pattern);
1885         pattern->HandleDragEnd();
1886     };
1887     auto actionCancelTask = [weak = WeakClaim(this)]() {
1888         auto pattern = weak.Upgrade();
1889         CHECK_NULL_VOID(pattern);
1890         pattern->HandleDragEnd();
1891     };
1892     panEvent_ = MakeRefPtr<PanEvent>(
1893         std::move(actionStartTask), std::move(actionUpdateTask), std::move(actionEndTask), std::move(actionCancelTask));
1894     PanDirection panDirection = { .type = PanDirection::HORIZONTAL };
1895     gestureHub->AddPanEvent(panEvent_, panDirection, DEFAULT_PAN_FINGER, DEFAULT_PAN_DISTANCE);
1896 }
1897 
InitDragBarPanEvent(const RefPtr<GestureEventHub> & gestureHub)1898 void NavigationPattern::InitDragBarPanEvent(const RefPtr<GestureEventHub>& gestureHub)
1899 {
1900     CHECK_NULL_VOID(!dragBarPanEvent_);
1901     auto actionStartTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1902         auto pattern = weak.Upgrade();
1903         CHECK_NULL_VOID(pattern);
1904         pattern->HandleDragStart();
1905     };
1906     auto actionUpdateTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1907         auto pattern = weak.Upgrade();
1908         CHECK_NULL_VOID(pattern);
1909         pattern->HandleDragUpdate(static_cast<float>(info.GetOffsetX()));
1910     };
1911     auto actionEndTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1912         auto pattern = weak.Upgrade();
1913         CHECK_NULL_VOID(pattern);
1914         pattern->HandleDragEnd();
1915     };
1916     auto actionCancelTask = [weak = WeakClaim(this)]() {
1917         auto pattern = weak.Upgrade();
1918         CHECK_NULL_VOID(pattern);
1919         pattern->HandleDragEnd();
1920     };
1921     dragBarPanEvent_ = MakeRefPtr<PanEvent>(
1922         std::move(actionStartTask), std::move(actionUpdateTask), std::move(actionEndTask), std::move(actionCancelTask));
1923     PanDirection panDirection = { .type = PanDirection::HORIZONTAL };
1924     gestureHub->AddPanEvent(dragBarPanEvent_, panDirection, DEFAULT_PAN_FINGER, DEFAULT_PAN_DISTANCE);
1925 }
1926 
OnHover(bool isHover)1927 void NavigationPattern::OnHover(bool isHover)
1928 {
1929     if (isInDividerDrag_) {
1930         return;
1931     }
1932     auto layoutProperty = GetLayoutProperty<NavigationLayoutProperty>();
1933     CHECK_NULL_VOID(layoutProperty);
1934     auto userSetMinNavBarWidthValue = layoutProperty->GetMinNavBarWidthValue(Dimension(0.0));
1935     auto userSetMaxNavBarWidthValue = layoutProperty->GetMaxNavBarWidthValue(Dimension(0.0));
1936     bool navBarWidthRangeEqual = userSetMinNavBarWidthValue.Value() >= userSetMaxNavBarWidthValue.Value();
1937     if ((userSetNavBarWidthFlag_ && !userSetNavBarRangeFlag_) || (userSetNavBarRangeFlag_ && navBarWidthRangeEqual)) {
1938         isDividerDraggable_ = false;
1939         return;
1940     }
1941     isDividerDraggable_ = true;
1942     MouseFormat format = isHover ? MouseFormat::RESIZE_LEFT_RIGHT : MouseFormat::DEFAULT;
1943     SetMouseStyle(format);
1944 }
1945 
GetDividerNode() const1946 RefPtr<FrameNode> NavigationPattern::GetDividerNode() const
1947 {
1948     auto host = GetHost();
1949     CHECK_NULL_RETURN(host, nullptr);
1950     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(host);
1951     CHECK_NULL_RETURN(navigationNode, nullptr);
1952     auto dividerFrameNode = AceType::DynamicCast<FrameNode>(navigationNode->GetDividerNode());
1953     CHECK_NULL_RETURN(dividerFrameNode, nullptr);
1954     return dividerFrameNode;
1955 }
1956 
GetDragBarNode() const1957 RefPtr<FrameNode> NavigationPattern::GetDragBarNode() const
1958 {
1959     auto host = GetHost();
1960     CHECK_NULL_RETURN(host, nullptr);
1961     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(host);
1962     CHECK_NULL_RETURN(navigationNode, nullptr);
1963     auto dragBarNode = AceType::DynamicCast<FrameNode>(navigationNode->GetDragBarNode());
1964     CHECK_NULL_RETURN(dragBarNode, nullptr);
1965     return dragBarNode;
1966 }
1967 
BeforeSyncGeometryProperties(const DirtySwapConfig &)1968 void NavigationPattern::BeforeSyncGeometryProperties(const DirtySwapConfig& /* config */)
1969 {
1970     AddDividerHotZoneRect();
1971 }
1972 
AddDividerHotZoneRect()1973 void NavigationPattern::AddDividerHotZoneRect()
1974 {
1975     if (NearZero(realDividerWidth_)) {
1976         return;
1977     }
1978     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1979     CHECK_NULL_VOID(hostNode);
1980     auto navBarNode = AceType::DynamicCast<FrameNode>(hostNode->GetNavBarNode());
1981     CHECK_NULL_VOID(navBarNode);
1982     auto geometryNode = navBarNode->GetGeometryNode();
1983     CHECK_NULL_VOID(geometryNode);
1984 
1985     OffsetF hotZoneOffset;
1986     hotZoneOffset.SetX(-DEFAULT_DIVIDER_HOT_ZONE_HORIZONTAL_PADDING.ConvertToPx());
1987     hotZoneOffset.SetY(DEFAULT_DIVIDER_START_MARGIN.ConvertToPx());
1988     SizeF hotZoneSize;
1989     hotZoneSize.SetWidth(realDividerWidth_ + DIVIDER_HOT_ZONE_HORIZONTAL_PADDING_NUM *
1990                                                  DEFAULT_DIVIDER_HOT_ZONE_HORIZONTAL_PADDING.ConvertToPx());
1991     hotZoneSize.SetHeight(geometryNode->GetFrameSize().Height());
1992     DimensionRect hotZoneRegion;
1993     auto paintHeight = GetPaintRectHeight(navBarNode);
1994     if (navigationMode_ == NavigationMode::STACK || enableDragBar_) {
1995         hotZoneRegion.SetSize(DimensionSize(Dimension(0.0f), Dimension(0.0f)));
1996     } else {
1997         hotZoneRegion.SetSize(DimensionSize(
1998             Dimension(hotZoneSize.Width()), Dimension(NearZero(paintHeight) ? hotZoneSize.Height() : paintHeight)));
1999     }
2000     hotZoneRegion.SetOffset(DimensionOffset(Dimension(hotZoneOffset.GetX()), Dimension(hotZoneOffset.GetY())));
2001 
2002     std::vector<DimensionRect> mouseRegion;
2003     mouseRegion.emplace_back(hotZoneRegion);
2004 
2005     auto dividerFrameNode = GetDividerNode();
2006     CHECK_NULL_VOID(dividerFrameNode);
2007     auto dividerGestureHub = dividerFrameNode->GetOrCreateGestureEventHub();
2008     CHECK_NULL_VOID(dividerGestureHub);
2009     dividerGestureHub->SetMouseResponseRegion(mouseRegion);
2010 
2011     auto dragRectOffset = geometryNode->GetMarginFrameOffset();
2012     dragRectOffset.SetX(-DEFAULT_DRAG_REGION.ConvertToPx());
2013     dragRect_.SetOffset(dragRectOffset);
2014     if (navigationMode_ == NavigationMode::STACK || enableDragBar_) {
2015         dragRect_.SetSize(SizeF(0.0f, 0.0f));
2016     } else {
2017         dragRect_.SetSize(SizeF(DEFAULT_DRAG_REGION.ConvertToPx() * DEFAULT_HALF + realDividerWidth_,
2018             NearZero(paintHeight) ? geometryNode->GetFrameSize().Height() : paintHeight));
2019     }
2020 
2021     std::vector<DimensionRect> responseRegion;
2022     DimensionOffset responseOffset(dragRectOffset);
2023     DimensionRect responseRect(Dimension(dragRect_.Width(), DimensionUnit::PX),
2024         Dimension(dragRect_.Height(), DimensionUnit::PX), responseOffset);
2025     responseRegion.emplace_back(responseRect);
2026     dividerGestureHub->SetResponseRegion(responseRegion);
2027 }
2028 
AddDragBarHotZoneRect()2029 void NavigationPattern::AddDragBarHotZoneRect()
2030 {
2031     if (NearZero(realDividerWidth_)) {
2032         return;
2033     }
2034     auto dargBarNode = GetDragBarNode();
2035     CHECK_NULL_VOID(dargBarNode);
2036     auto geometryNode = dargBarNode->GetGeometryNode();
2037     CHECK_NULL_VOID(geometryNode);
2038     auto dragBarGestureHub = dargBarNode->GetOrCreateGestureEventHub();
2039     CHECK_NULL_VOID(dragBarGestureHub);
2040 
2041     auto dragRectOffset = geometryNode->GetMarginFrameOffset();
2042     dragRectOffset.SetX(-DEFAULT_DRAG_BAR_HOT_ZONE.ConvertToPx());
2043     dragRectOffset.SetY(0.0f);
2044     dragBarRect_.SetOffset(dragRectOffset);
2045     if (navigationMode_ == NavigationMode::STACK) {
2046         dragBarRect_.SetSize(SizeF(0.0f, 0.0f));
2047     } else {
2048         dragBarRect_.SetSize(SizeF(DEFAULT_DRAG_BAR_HOT_ZONE.ConvertToPx() * DEFAULT_HALF +
2049             geometryNode->GetFrameSize().Width(), geometryNode->GetFrameSize().Height()));
2050     }
2051     std::vector<DimensionRect> responseRegion;
2052     DimensionOffset responseOffset(dragRectOffset);
2053     DimensionRect responseRect(Dimension(dragBarRect_.Width(), DimensionUnit::PX),
2054         Dimension(dragBarRect_.Height(), DimensionUnit::PX), responseOffset);
2055     responseRegion.emplace_back(responseRect);
2056     dragBarGestureHub->SetResponseRegion(responseRegion);
2057 }
2058 
NotifyDialogChange(NavDestinationLifecycle lifecycle,bool isFromStandardIndex)2059 void NavigationPattern::NotifyDialogChange(NavDestinationLifecycle lifecycle, bool isFromStandardIndex)
2060 {
2061     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2062     CHECK_NULL_VOID(hostNode);
2063     const auto& navDestinationNodes = navigationStack_->GetAllNavDestinationNodes();
2064     int32_t lastStandardIndex = hostNode->GetLastStandardIndex();
2065     int32_t standardIndex = lastStandardIndex >= 0 ? lastStandardIndex : 0;
2066     int32_t start = isFromStandardIndex ? standardIndex : 0;
2067     int32_t end = isFromStandardIndex ? navigationStack_->Size() : standardIndex;
2068     bool isShow = (lifecycle == NavDestinationLifecycle::ON_SHOW)
2069         || (lifecycle == NavDestinationLifecycle::ON_WILL_SHOW);
2070     if (isShow) {
2071         for (int32_t index = start; index < end; index++) {
2072             NotifyDestinationLifecycle(navDestinationNodes[index].second, lifecycle);
2073         }
2074     } else {
2075         for (int32_t index = end - 1; index >= 0 && index >= start; index--) {
2076             NotifyDestinationLifecycle(navDestinationNodes[index].second, lifecycle);
2077         }
2078     }
2079 }
2080 
DumpInfo()2081 void NavigationPattern::DumpInfo()
2082 {
2083     if (!navigationStack_) {
2084         return;
2085     }
2086     DumpLog::GetInstance().AddDesc(std::string("size").append(std::to_string(navigationStack_->Size())));
2087 }
2088 
TriggerCustomAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage)2089 bool NavigationPattern::TriggerCustomAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
2090     const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage)
2091 {
2092     TAG_LOGI(AceLogTag::ACE_NAVIGATION, "will trigger navigation custom animation");
2093     if ((!preTopNavDestination && !newTopNavDestination) || !onTransition_) {
2094         return false;
2095     }
2096     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2097     CHECK_NULL_RETURN(hostNode, false);
2098     hostNode->SetIsOnAnimation(true);
2099     if (!newTopNavDestination) {
2100         // pop animation with top navDestination, recover navBar visible tag
2101         hostNode->SetNeedSetInvisible(false);
2102     }
2103     auto proxy = AceType::MakeRefPtr<NavigationTransitionProxy>();
2104     proxy->SetPreDestination(preTopNavDestination);
2105     proxy->SetTopDestination(newTopNavDestination);
2106     auto proxyId = proxy->GetProxyId();
2107     proxyList_.emplace_back(proxy);
2108     auto navigationTransition = ExecuteTransition(preTopNavDestination, newTopNavDestination, isPopPage);
2109     if (!navigationTransition.isValid) {
2110         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "custom transition value is invalid, do default animation");
2111         return false;
2112     }
2113     ExecuteAddAnimation(preTopNavDestination, newTopNavDestination, isPopPage, proxy, navigationTransition);
2114     ACE_SCOPED_TRACE_COMMERCIAL("Navigation page custom transition start");
2115     if (navigationTransition.interactive) {
2116         PerfMonitor::GetPerfMonitor()->Start(PerfConstants::ABILITY_OR_PAGE_SWITCH_INTERACTIVE,
2117             PerfActionType::FIRST_MOVE, "");
2118         auto finishCallback = [weakNavigation = WeakClaim(this),
2119                                   weakPreNavDestination = WeakPtr<NavDestinationGroupNode>(preTopNavDestination),
2120                                   weakNewNavDestination = WeakPtr<NavDestinationGroupNode>(newTopNavDestination),
2121                                   isPopPage, proxyId]() {
2122             auto pattern = weakNavigation.Upgrade();
2123             CHECK_NULL_VOID(pattern);
2124             auto proxy = pattern->GetProxyById(proxyId);
2125             if (proxy == nullptr) {
2126                 return;
2127             }
2128             if (!proxy->GetInteractive()) {
2129                 pattern->RemoveProxyById(proxyId);
2130                 return;
2131             }
2132             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "interactive animation is finish: %{public}d", proxy->GetIsSuccess());
2133             pattern->isFinishInteractiveAnimation_ = true;
2134             auto preDestination = weakPreNavDestination.Upgrade();
2135             auto topDestination = weakNewNavDestination.Upgrade();
2136             proxy->SetIsFinished(true);
2137             // this flag will be update in cancelTransition or finishTransition
2138             ACE_SCOPED_TRACE_COMMERCIAL("navigation page custom transition end");
2139             PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH_INTERACTIVE, true);
2140             if (proxy->GetIsSuccess()) {
2141                 pattern->ClearRecoveryList();
2142                 pattern->OnCustomAnimationFinish(preDestination, topDestination, isPopPage);
2143             } else {
2144                 // fire page cancel transition
2145                 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "interactive animation canceled");
2146                 pattern->RecoveryToLastStack(preDestination, topDestination);
2147                 pattern->SyncWithJsStackIfNeeded();
2148             }
2149             proxy->FireEndCallback();
2150             pattern->RemoveProxyById(proxyId);
2151         };
2152         auto pipelineContext = hostNode->GetContext();
2153         CHECK_NULL_RETURN(pipelineContext, false);
2154         auto navigationManager = pipelineContext->GetNavigationManager();
2155         CHECK_NULL_RETURN(navigationManager, false);
2156         navigationManager->SetInteractive(hostNode->GetId());
2157         proxy->SetInteractiveAnimation(AnimationUtils::CreateInteractiveAnimation(
2158             nullptr, finishCallback), finishCallback);
2159         navigationTransition.transition(proxy);
2160         isFinishInteractiveAnimation_ = false;
2161         navigationManager->FinishInteractiveAnimation();
2162         proxy->StartAnimation();
2163     } else {
2164         PerfMonitor::GetPerfMonitor()->Start(PerfConstants::ABILITY_OR_PAGE_SWITCH, PerfActionType::LAST_UP, "");
2165         ClearRecoveryList();
2166         navigationTransition.transition(proxy);
2167         // enable render group for text node during custom animation to reduce
2168         // unnecessary redrawing
2169         if (isPopPage && preTopNavDestination) {
2170             preTopNavDestination->UpdateTextNodeListAsRenderGroup(isPopPage, proxy);
2171         }
2172         if (!isPopPage && newTopNavDestination) {
2173             newTopNavDestination->UpdateTextNodeListAsRenderGroup(isPopPage, proxy);
2174         }
2175     }
2176 
2177     RefPtr<EventHub> eventHub;
2178     if (!preTopNavDestination && navigationMode_ == NavigationMode::STACK) {
2179         auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2180         CHECK_NULL_RETURN(hostNode, true);
2181         auto navBarNode = AceType::DynamicCast<FrameNode>(hostNode->GetNavBarNode());
2182         CHECK_NULL_RETURN(navBarNode, true);
2183         eventHub = navBarNode->GetEventHub<EventHub>();
2184     }
2185     if (preTopNavDestination) {
2186         eventHub = preTopNavDestination->GetEventHub<EventHub>();
2187     }
2188     CHECK_NULL_RETURN(eventHub, true);
2189     eventHub->SetEnabledInternal(false);
2190     return true;
2191 }
2192 
OnCustomAnimationFinish(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage)2193 void NavigationPattern::OnCustomAnimationFinish(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
2194     const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage)
2195 {
2196     if (!preTopNavDestination && !newTopNavDestination) {
2197         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "preDestination and topDestination is invalid");
2198         return;
2199     }
2200     ACE_SCOPED_TRACE_COMMERCIAL("Navigation page custom transition end");
2201     PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH, true);
2202     auto replaceValue = navigationStack_->GetReplaceValue();
2203     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2204     CHECK_NULL_VOID(hostNode);
2205     hostNode->SetIsOnAnimation(false);
2206     auto id = hostNode->GetTopDestination() ? hostNode->GetTopDestination()->GetAccessibilityId() : -1;
2207     hostNode->OnAccessibilityEvent(
2208         AccessibilityEventType::PAGE_CHANGE, id, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID);
2209     do {
2210         if (replaceValue != 0) {
2211             if (preTopNavDestination) {
2212                 preTopNavDestination->SetIsOnAnimation(false);
2213             }
2214             if (newTopNavDestination) {
2215                 newTopNavDestination->SetIsOnAnimation(false);
2216             }
2217             hostNode->DealNavigationExit(preTopNavDestination, preTopNavDestination == nullptr);
2218             navigationStack_->UpdateReplaceValue(0);
2219             break;
2220         }
2221         if ((newTopNavDestination && preTopNavDestination && isPopPage) ||
2222             (preTopNavDestination && !newTopNavDestination)) {
2223             PageTransitionType preNodeTransitionType = preTopNavDestination->GetTransitionType();
2224             if (preNodeTransitionType != PageTransitionType::EXIT_POP) {
2225                 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "previous destination node is executing another transition");
2226                 return;
2227             }
2228             preTopNavDestination->SetIsOnAnimation(false);
2229             if (newTopNavDestination && newTopNavDestination->GetTransitionType() == PageTransitionType::ENTER_POP) {
2230                 newTopNavDestination->SetIsOnAnimation(false);
2231             }
2232             auto preDestinationPattern = preTopNavDestination->GetPattern<NavDestinationPattern>();
2233             CHECK_NULL_VOID(preDestinationPattern);
2234             auto shallowBuilder = preDestinationPattern->GetShallowBuilder();
2235             if (shallowBuilder) {
2236                 shallowBuilder->MarkIsExecuteDeepRenderDone(false);
2237             }
2238             auto parent = preTopNavDestination->GetParent();
2239             CHECK_NULL_VOID(parent);
2240             parent->RemoveChild(preTopNavDestination);
2241             parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
2242             break;
2243         }
2244         if ((newTopNavDestination && preTopNavDestination && !isPopPage) ||
2245             (!preTopNavDestination && newTopNavDestination && navigationMode_ == NavigationMode::STACK)) {
2246             hostNode->SetNeedSetInvisible(true);
2247             RefPtr<FrameNode> node;
2248             PageTransitionType preNodeTransitionType;
2249             if (preTopNavDestination) {
2250                 preNodeTransitionType = preTopNavDestination->GetTransitionType();
2251                 node = preTopNavDestination;
2252             } else {
2253                 // pre destination is nullptr, preNode is navBarNode
2254                 auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
2255                 CHECK_NULL_VOID(navBarNode);
2256                 preNodeTransitionType = navBarNode->GetTransitionType();
2257                 node = AceType::DynamicCast<FrameNode>(hostNode->GetNavBarNode());
2258                 CHECK_NULL_VOID(node);
2259             }
2260             if (newTopNavDestination && newTopNavDestination->GetTransitionType() == PageTransitionType::ENTER_PUSH) {
2261                 newTopNavDestination->SetIsOnAnimation(false);
2262             }
2263             if (preNodeTransitionType != PageTransitionType::EXIT_PUSH) {
2264                 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "previous destination node is executing another transition");
2265                 return;
2266             }
2267             if (preTopNavDestination) {
2268                 preTopNavDestination->SetIsOnAnimation(false);
2269             }
2270             // recover event hub
2271             auto eventHub = node->GetEventHub<EventHub>();
2272             if (eventHub) {
2273                 eventHub->SetEnabledInternal(true);
2274             }
2275             bool isDialog = newTopNavDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG;
2276             if (isDialog) {
2277                 return;
2278             }
2279             auto property = node->GetLayoutProperty();
2280             property->UpdateVisibility(VisibleType::INVISIBLE);
2281             node->SetJSViewActive(false);
2282             if (!preTopNavDestination) {
2283                 hostNode->NotifyPageHide();
2284             }
2285         }
2286     } while (0);
2287     hostNode->RemoveDialogDestination();
2288     auto context = PipelineContext::GetCurrentContext();
2289     CHECK_NULL_VOID(context);
2290     context->MarkNeedFlushMouseEvent();
2291 }
2292 
ExecuteTransition(const RefPtr<NavDestinationGroupNode> & preTopDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage)2293 NavigationTransition NavigationPattern::ExecuteTransition(const RefPtr<NavDestinationGroupNode>& preTopDestination,
2294     const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage)
2295 {
2296     NavigationTransition navigationTransition;
2297     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2298     CHECK_NULL_RETURN(hostNode, navigationTransition);
2299     NavigationOperation operation;
2300     auto currentProxy = GetTopNavigationProxy();
2301     auto preInfo = currentProxy->GetPreDestinationContext();
2302     auto topInfo = currentProxy->GetTopDestinationContext();
2303     auto replaceValue = navigationStack_->GetReplaceValue();
2304     if (replaceValue != 0) {
2305         operation = NavigationOperation::REPLACE;
2306     } else if (!preTopDestination) {
2307         operation = NavigationOperation::PUSH;
2308         // if animated with navBarNode, recover navBar visibility
2309         hostNode->SetNeedSetInvisible(false);
2310     } else {
2311         operation = (!newTopNavDestination || isPopPage) ? NavigationOperation::POP : NavigationOperation::PUSH;
2312     }
2313     /* set transition animation flag fro navBarNode or navDestinationNode */
2314     if (operation == NavigationOperation::PUSH) {
2315         if (preTopDestination != nullptr) {
2316             preTopDestination->SetTransitionType(PageTransitionType::EXIT_PUSH);
2317         } else {
2318             // preTopDestination is nullptr, previous node is navBar node
2319             auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
2320             CHECK_NULL_RETURN(navBarNode, navigationTransition);
2321             navBarNode->SetTransitionType(PageTransitionType::EXIT_PUSH);
2322         }
2323         if (newTopNavDestination != nullptr) {
2324             newTopNavDestination->SetTransitionType(PageTransitionType::ENTER_PUSH);
2325         }
2326     }
2327     if (operation == NavigationOperation::POP) {
2328         if (preTopDestination != nullptr) {
2329             preTopDestination->SetTransitionType(PageTransitionType::EXIT_POP);
2330         }
2331         if (newTopNavDestination != nullptr) {
2332             newTopNavDestination->SetTransitionType(PageTransitionType::ENTER_POP);
2333         } else {
2334             // newTopNavDestination is nullptr, current node is navBar node
2335             auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
2336             CHECK_NULL_RETURN(navBarNode, navigationTransition);
2337             navBarNode->SetTransitionType(PageTransitionType::ENTER_POP);
2338         }
2339     }
2340     LogCustomAnimationStart(preTopDestination, newTopNavDestination, operation);
2341     return onTransition_(preInfo, topInfo, operation);
2342 }
2343 
OnColorConfigurationUpdate()2344 void NavigationPattern::OnColorConfigurationUpdate()
2345 {
2346     UpdateDividerBackgroundColor();
2347 
2348     auto dragBarNode = GetDragBarNode();
2349     CHECK_NULL_VOID(dragBarNode);
2350     auto dragPattern = dragBarNode->GetPattern<NavigationDragBarPattern>();
2351     CHECK_NULL_VOID(dragPattern);
2352     dragPattern->UpdateDefaultColor();
2353 }
2354 
UpdateDividerBackgroundColor()2355 void NavigationPattern::UpdateDividerBackgroundColor()
2356 {
2357     auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2358     CHECK_NULL_VOID(navigationGroupNode);
2359     auto dividerNode = GetDividerNode();
2360     CHECK_NULL_VOID(dividerNode);
2361     auto theme = NavigationGetTheme(navigationGroupNode->GetThemeScopeId());
2362     CHECK_NULL_VOID(theme);
2363     dividerNode->GetRenderContext()->UpdateBackgroundColor(theme->GetNavigationDividerColor());
2364     dividerNode->MarkDirtyNode();
2365 }
2366 
UpdateToobarFocusColor()2367 void NavigationPattern::UpdateToobarFocusColor()
2368 {
2369     auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2370     CHECK_NULL_VOID(navigationGroupNode);
2371     auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationGroupNode->GetNavBarNode());
2372     CHECK_NULL_VOID(navBarNode);
2373     auto toolBarNode = AceType::DynamicCast<NavToolbarNode>(navBarNode->GetPreToolBarNode());
2374     CHECK_NULL_VOID(toolBarNode);
2375     auto containerNode = AceType::DynamicCast<FrameNode>(toolBarNode->GetToolbarContainerNode());
2376     CHECK_NULL_VOID(containerNode);
2377     auto toolBarItemNodes = containerNode->GetChildren();
2378     auto theme = NavigationGetTheme(navigationGroupNode->GetThemeScopeId());
2379     CHECK_NULL_VOID(theme);
2380     for (auto& toolBarItemNode : toolBarItemNodes) {
2381         auto buttonNode = AceType::DynamicCast<FrameNode>(toolBarItemNode);
2382         CHECK_NULL_VOID(buttonNode);
2383         auto buttonPattern = AceType::DynamicCast<ButtonPattern>(buttonNode->GetPattern());
2384         CHECK_NULL_VOID(buttonPattern);
2385         buttonPattern->SetFocusBorderColor(theme->GetToolBarItemFocusColor());
2386         auto focusHub = buttonNode->GetFocusHub();
2387         CHECK_NULL_VOID(focusHub);
2388         focusHub->SetPaintColor(theme->GetToolBarItemFocusColor());
2389     }
2390 }
2391 
OnThemeScopeUpdate(int32_t themeScopeId)2392 bool NavigationPattern::OnThemeScopeUpdate(int32_t themeScopeId)
2393 {
2394     auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2395     CHECK_NULL_RETURN(navigationGroupNode, false);
2396     auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationGroupNode->GetNavBarNode());
2397     CHECK_NULL_RETURN(navBarNode, false);
2398 
2399     auto dividerNode = AceType::DynamicCast<FrameNode>(navBarNode->GetToolBarDividerNode());
2400     CHECK_NULL_RETURN(dividerNode, false);
2401 
2402     auto theme = NavigationGetTheme(themeScopeId);
2403     CHECK_NULL_RETURN(theme, false);
2404 
2405     auto dividerRenderProperty = dividerNode->GetPaintProperty<DividerRenderProperty>();
2406     CHECK_NULL_RETURN(dividerRenderProperty, false);
2407     dividerRenderProperty->UpdateDividerColor(theme->GetToolBarDividerColor());
2408 
2409     navigationGroupNode->MarkModifyDone();
2410     return false;
2411 }
2412 
UpdatePreNavDesZIndex(const RefPtr<FrameNode> & preTopNavDestination,const RefPtr<FrameNode> & newTopNavDestination,int32_t preLastStandardIndex)2413 void NavigationPattern::UpdatePreNavDesZIndex(const RefPtr<FrameNode> &preTopNavDestination,
2414     const RefPtr<FrameNode> &newTopNavDestination, int32_t preLastStandardIndex)
2415 {
2416     auto replaceVal = navigationStack_->GetReplaceValue();
2417     if (replaceVal != 0 && preTopNavDestination && newTopNavDestination) {
2418         auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2419         CHECK_NULL_VOID(hostNode);
2420         auto navigationContentNode = AceType::DynamicCast<FrameNode>(hostNode->GetContentNode());
2421         CHECK_NULL_VOID(navigationContentNode);
2422         auto newDesNodeContext = newTopNavDestination->GetRenderContext();
2423         CHECK_NULL_VOID(newDesNodeContext);
2424         std::optional<int32_t> newNodeZIndex = newDesNodeContext->GetZIndex();
2425         int32_t standardIndex = newNodeZIndex.value_or(0) - 1;
2426         auto hideNodes = hostNode->GetHideNodes();
2427         for (auto iter = hideNodes.begin(); iter != hideNodes.end(); ++iter) {
2428             // if navdestination nodes is not need removed, default zIndex is satisfied, don't need change
2429             if (!iter->second) {
2430                 continue;
2431             }
2432             auto navDestination = iter->first;
2433             if (!navDestination) {
2434                 continue;
2435             }
2436             auto navDestinationContext = navDestination->GetRenderContext();
2437             if (!navDestinationContext) {
2438                 continue;
2439             }
2440             // get navDestination index in hideNodes, use navdestination index in pre navigation stack
2441             int32_t hideNodesIndex =
2442                 static_cast<int32_t>(hideNodes.size()) - (navDestination->GetIndex() - preLastStandardIndex);
2443             navDestinationContext->UpdateZIndex(standardIndex - hideNodesIndex);
2444         }
2445         auto preDesNodeContext = preTopNavDestination->GetRenderContext();
2446         CHECK_NULL_VOID(preDesNodeContext);
2447         preDesNodeContext->UpdateZIndex(standardIndex);
2448         navigationContentNode->RebuildRenderContextTree();
2449         auto context = PipelineContext::GetCurrentContext();
2450         CHECK_NULL_VOID(context);
2451         context->RequestFrame();
2452     }
2453 }
2454 
SetNavigationStack(const RefPtr<NavigationStack> & navigationStack)2455 void NavigationPattern::SetNavigationStack(const RefPtr<NavigationStack>& navigationStack)
2456 {
2457     if (navigationStack_) {
2458         navigationStack_->SetOnStateChangedCallback(nullptr);
2459     }
2460     navigationStack_ = navigationStack;
2461     if (navigationStack_) {
2462         navigationStack_->SetNavigationNode(GetHost());
2463         WeakPtr<NavigationPattern> weakPattern = WeakClaim(this);
2464         auto id = Container::CurrentId();
2465         auto callback = [weakPattern, id]() {
2466             ContainerScope scope(id);
2467             auto pattern = weakPattern.Upgrade();
2468             CHECK_NULL_VOID(pattern);
2469             if (pattern->NeedSyncWithJsStackMarked()) {
2470                 return;
2471             }
2472             pattern->MarkNeedSyncWithJsStack();
2473             auto context = PipelineContext::GetCurrentContext();
2474             CHECK_NULL_VOID(context);
2475             context->AddBuildFinishCallBack([weakPattern]() {
2476                 auto pattern = weakPattern.Upgrade();
2477                 CHECK_NULL_VOID(pattern);
2478                 pattern->SyncWithJsStackIfNeeded();
2479                 auto host = pattern->GetHost();
2480                 CHECK_NULL_VOID(host);
2481                 host->MarkDirtyNode();
2482             });
2483             context->RequestFrame();
2484         };
2485         navigationStack_->SetOnStateChangedCallback(callback);
2486     }
2487 }
2488 
GetParentNavigationPattern()2489 RefPtr<NavigationPattern> NavigationPattern::GetParentNavigationPattern()
2490 {
2491     RefPtr<UINode> node = GetHost();
2492     CHECK_NULL_RETURN(node, nullptr);
2493     node = node->GetParent();
2494     while (node) {
2495         if (node->GetTag() == V2::NAVIGATION_VIEW_ETS_TAG) {
2496             break;
2497         }
2498         node = node->GetParent();
2499     }
2500     auto groupNode = AceType::DynamicCast<NavigationGroupNode>(node);
2501     CHECK_NULL_RETURN(groupNode, nullptr);
2502     return AceType::DynamicCast<NavigationPattern>(groupNode->GetPattern());
2503 }
2504 
AttachNavigationStackToParent()2505 void NavigationPattern::AttachNavigationStackToParent()
2506 {
2507     CHECK_NULL_VOID(navigationStack_);
2508     auto parentPattern = GetParentNavigationPattern();
2509     CHECK_NULL_VOID(parentPattern);
2510     auto parentStack = parentPattern->GetNavigationStack();
2511     if (parentStack) {
2512         navigationStack_->OnAttachToParent(parentStack);
2513     }
2514 }
2515 
DetachNavigationStackFromParent()2516 void NavigationPattern::DetachNavigationStackFromParent()
2517 {
2518     if (navigationStack_) {
2519         navigationStack_->OnDetachFromParent();
2520     }
2521 }
2522 
DealTransitionVisibility(const RefPtr<FrameNode> & node,bool isVisible,bool isNavBar)2523 void NavigationPattern::DealTransitionVisibility(const RefPtr<FrameNode>& node, bool isVisible, bool isNavBar)
2524 {
2525     auto renderContext = node->GetRenderContext();
2526     if (!renderContext->HasDisappearTransition()) {
2527         auto layoutProperty = node->GetLayoutProperty();
2528         layoutProperty->UpdateVisibility(isVisible ? VisibleType::VISIBLE : VisibleType::INVISIBLE);
2529         node->SetJSViewActive(isVisible);
2530         return;
2531     }
2532     auto layoutProperty = node->GetLayoutProperty();
2533     layoutProperty->UpdateVisibility(isVisible ? VisibleType::VISIBLE : VisibleType::INVISIBLE, true);
2534     renderContext->SetTransitionOutCallback([weakNode = WeakPtr<FrameNode>(node), isVisible, isNavBar] {
2535         auto curNode = weakNode.Upgrade();
2536         CHECK_NULL_VOID(curNode);
2537         if (isNavBar) {
2538             auto navBarNode = AceType::DynamicCast<NavBarNode>(curNode);
2539             if (navBarNode->GetTransitionType() != PageTransitionType::EXIT_PUSH) {
2540                 return;
2541             }
2542         } else {
2543             auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
2544             if (navDestinationNode->GetTransitionType() != PageTransitionType::EXIT_PUSH) {
2545                 return;
2546             }
2547         }
2548         curNode->SetJSViewActive(isVisible);
2549     });
2550 }
2551 
AddToDumpManager()2552 void NavigationPattern::AddToDumpManager()
2553 {
2554     auto node = GetHost();
2555     auto context = PipelineContext::GetCurrentContext();
2556     if (!node || !context) {
2557         return;
2558     }
2559     auto mgr = context->GetNavigationManager();
2560     if (!mgr) {
2561         return;
2562     }
2563     auto callback = [weakPattern = WeakClaim(this)](int depth) {
2564         auto pattern = weakPattern.Upgrade();
2565         if (!pattern) {
2566             return;
2567         }
2568         const auto& stack = pattern->GetNavigationStack();
2569         if (!stack) {
2570             return;
2571         }
2572         auto infos = stack->DumpStackInfo();
2573     };
2574     mgr->AddNavigationDumpCallback(node->GetId(), node->GetDepth(), callback);
2575 }
2576 
RemoveFromDumpManager()2577 void NavigationPattern::RemoveFromDumpManager()
2578 {
2579     auto node = GetHost();
2580     auto context = PipelineContext::GetCurrentContext();
2581     if (!node || !context) {
2582         return;
2583     }
2584     auto mgr = context->GetNavigationManager();
2585     if (mgr) {
2586         mgr->RemoveNavigationDumpCallback(node->GetId(), node->GetDepth());
2587     }
2588 }
2589 
FireInterceptionEvent(bool isBefore,const std::optional<std::pair<std::string,RefPtr<UINode>>> & newTopPath)2590 void NavigationPattern::FireInterceptionEvent(bool isBefore,
2591     const std::optional<std::pair<std::string, RefPtr<UINode>>>& newTopPath)
2592 {
2593     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2594     CHECK_NULL_VOID(hostNode);
2595     RefPtr<NavDestinationContext> to;
2596     if (newTopPath.has_value()) {
2597         auto topDestination =
2598             AceType::DynamicCast<NavDestinationGroupNode>(hostNode->GetNavDestinationNode(newTopPath->second));
2599         if (topDestination) {
2600             auto pattern = AceType::DynamicCast<NavDestinationPattern>(topDestination->GetPattern());
2601             to = pattern->GetNavDestinationContext();
2602         }
2603     }
2604     NavigationOperation operation;
2605     if (isReplace_ != 0) {
2606         operation = NavigationOperation::REPLACE;
2607     } else {
2608         operation = lastPreIndex_ == -1 ? NavigationOperation::POP : NavigationOperation::PUSH;
2609     }
2610     auto layoutProperty = hostNode->GetLayoutProperty<NavigationLayoutProperty>();
2611     // mode is split and stack size is one,don't need to do animation.
2612     if ((layoutProperty->GetUsrNavigationModeValue(NavigationMode::AUTO) == NavigationMode::SPLIT
2613         || navigationMode_ == NavigationMode::SPLIT) && !preContext_) {
2614         isAnimated_ = false;
2615     }
2616     navigationStack_->FireNavigationInterception(isBefore, preContext_, to, operation,
2617         isAnimated_);
2618 
2619     if (!isBefore) {
2620         NotifyNavDestinationSwitch(preContext_, to, operation);
2621     }
2622 }
2623 
UpdateIsAnimation(const std::optional<std::pair<std::string,RefPtr<UINode>>> & preTopNavPath)2624 void NavigationPattern::UpdateIsAnimation(const std::optional<std::pair<std::string, RefPtr<UINode>>>& preTopNavPath)
2625 {
2626     auto disAbleAnimation = navigationStack_->GetDisableAnimation();
2627     auto animated = navigationStack_->GetAnimatedValue();
2628     // current animation flag is false
2629     if (disAbleAnimation || !animated) {
2630         isAnimated_ = false;
2631         return;
2632     }
2633     // check is dialog mode
2634     bool isDialog = false;
2635     if (preTopNavPath.has_value()) {
2636         auto preDestination = AceType::DynamicCast<NavDestinationGroupNode>(
2637             NavigationGroupNode::GetNavDestinationNode(preTopNavPath->second));
2638         if (preDestination) {
2639             isDialog = isDialog || (preDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG);
2640         }
2641     }
2642     auto topNode = navigationStack_->Get();
2643     if (topNode) {
2644         auto newTopDestination = AceType::DynamicCast<NavDestinationGroupNode>(
2645             NavigationGroupNode::GetNavDestinationNode(topNode));
2646         if (newTopDestination) {
2647             isDialog = isDialog || (newTopDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG);
2648         }
2649     }
2650     if (!isDialog) {
2651         isAnimated_ = true;
2652         return;
2653     }
2654     isAnimated_ = isCustomAnimation_;
2655 }
2656 
NotifyNavDestinationSwitch(const RefPtr<NavDestinationContext> & from,const RefPtr<NavDestinationContext> & to,NavigationOperation operation)2657 void NavigationPattern::NotifyNavDestinationSwitch(const RefPtr<NavDestinationContext>& from,
2658     const RefPtr<NavDestinationContext>& to, NavigationOperation operation)
2659 {
2660     auto host = GetHost();
2661     auto NavdestinationSwitchFunc =
2662         UIObserverHandler::GetInstance().GetHandleNavDestinationSwitchFunc();
2663     if (!host || !NavdestinationSwitchFunc) {
2664         return;
2665     }
2666 
2667     std::string navigationId = host->GetInspectorIdValue("");
2668     std::optional<NavDestinationInfo> fromInfo;
2669     std::optional<NavDestinationInfo> toInfo;
2670     RefPtr<NavPathInfo> pathInfo = nullptr;
2671     if (from) {
2672         pathInfo = from->GetNavPathInfo();
2673     } else if (to) {
2674         pathInfo = to->GetNavPathInfo();
2675     }
2676     if (pathInfo) {
2677         pathInfo->OpenScope();
2678     }
2679     BuildNavDestinationInfoFromContext(navigationId, NavDestinationState::ON_HIDDEN, from, true, fromInfo);
2680     BuildNavDestinationInfoFromContext(navigationId, NavDestinationState::ON_SHOWN, to, false, toInfo);
2681     UIObserverHandler::GetInstance().NotifyNavDestinationSwitch(
2682         std::move(fromInfo), std::move(toInfo), operation);
2683     if (pathInfo) {
2684         pathInfo->CloseScope();
2685     }
2686 }
2687 
StartTransition(const RefPtr<NavDestinationGroupNode> & preDestination,const RefPtr<NavDestinationGroupNode> & topDestination,bool isAnimated,bool isPopPage,bool isNeedVisible)2688 void NavigationPattern::StartTransition(const RefPtr<NavDestinationGroupNode>& preDestination,
2689     const RefPtr<NavDestinationGroupNode>& topDestination,
2690     bool isAnimated, bool isPopPage, bool isNeedVisible)
2691 {
2692     std::string fromPathInfo;
2693     std::string toPathInfo;
2694     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2695     CHECK_NULL_VOID(hostNode);
2696     bool isNotNeedAnimation = !isAnimated;
2697 #if defined(ENABLE_NAV_SPLIT_MODE)
2698     isNotNeedAnimation = !isAnimated ||
2699         (navigationMode_ == NavigationMode::SPLIT && navigationStack_->Size() <= 1 &&
2700             !isBackPage_ && !isCustomAnimation_);
2701     TAG_LOGI(AceLogTag::ACE_NAVIGATION, "StartTransition navigationMode_:%{public}d isNotNeedAnimation:%{public}d",
2702         navigationMode_, isNotNeedAnimation);
2703 #endif
2704 
2705     std::string fromNavDestinationName = "";
2706     std::string toNavDestinationName = "";
2707     if (preDestination) {
2708         fromPathInfo = preDestination->GetNavDestinationPathInfo();
2709         auto preDestinationPattern = preDestination->GetPattern<NavDestinationPattern>();
2710         CHECK_NULL_VOID(preDestinationPattern);
2711         fromNavDestinationName = preDestinationPattern->GetName();
2712         fromPathInfo += ", navDesitinationName: " + fromNavDestinationName;
2713         if ((isPopPage || preDestination->NeedRemoveInPush()) && isNotNeedAnimation) {
2714             /**
2715              * when transition without animation, 'pop' and 'push with remove' need to post
2716              * afterLayoutTask to delay old top's onDisappear. So set this flag to 'false'
2717              */
2718             preDestination->SetIsAnimated(false);
2719         }
2720     } else {
2721         fromPathInfo = hostNode->GetNavigationPathInfo();
2722     }
2723     if (topDestination) {
2724         toPathInfo = topDestination->GetNavDestinationPathInfo();
2725         auto topDestinationPattern = topDestination->GetPattern<NavDestinationPattern>();
2726         CHECK_NULL_VOID(topDestinationPattern);
2727         toNavDestinationName = topDestinationPattern->GetName();
2728         toPathInfo += ", navDesitinationName: " + toNavDestinationName;
2729     } else {
2730         toPathInfo = hostNode->GetNavigationPathInfo();
2731     }
2732     ACE_SCOPED_TRACE_COMMERCIAL("NavDestination Page from %s to %s", fromPathInfo.c_str(), toPathInfo.c_str());
2733     ResSchedReport::GetInstance().HandlePageTransition(fromNavDestinationName, toNavDestinationName, "navigation");
2734 
2735     // fire onWillHide
2736     if (!isPopPage && !preDestination && navigationMode_ == NavigationMode::STACK) {
2737         // NavBar will be covered in STACK mode
2738         auto navBarNode = AceType::DynamicCast<FrameNode>(hostNode->GetNavBarNode());
2739         ProcessAutoSave(navBarNode);
2740     }
2741     if (isPopPage || (preDestination &&
2742         (hostNode->GetLastStandardIndex() > preDestination->GetIndex() || preDestination->NeedRemoveInPush()))) {
2743         NotifyDestinationLifecycle(preDestination, NavDestinationLifecycle::ON_WILL_HIDE);
2744     }
2745     hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_WILL_HIDE);
2746     auto pipeline = PipelineContext::GetCurrentContext();
2747     CHECK_NULL_VOID(pipeline);
2748     auto navigationManager = pipeline->GetNavigationManager();
2749     navigationManager->FireNavigationUpdateCallback();
2750     auto overlayManager = pipeline->GetOverlayManager();
2751     if (overlayManager) {
2752         overlayManager->RemoveAllModalInOverlay(false);
2753     }
2754     if (topDestination) {
2755         NotifyDialogChange(NavDestinationLifecycle::ON_WILL_SHOW, true);
2756     }
2757     if (isNotNeedAnimation) {
2758         FireShowAndHideLifecycle(preDestination, topDestination, isPopPage, false);
2759         TransitionWithOutAnimation(preDestination, topDestination, isPopPage, isNeedVisible);
2760         return;
2761     }
2762     pipeline->AddAfterLayoutTask([weakNavigation = WeakClaim(this),
2763         weakPreDestination = WeakPtr<NavDestinationGroupNode>(preDestination),
2764         weakTopDestination = WeakPtr<NavDestinationGroupNode>(topDestination),
2765         isPopPage, isNeedVisible]() {
2766         auto navigationPattern = AceType::DynamicCast<NavigationPattern>(weakNavigation.Upgrade());
2767         CHECK_NULL_VOID(navigationPattern);
2768         auto preDestination = weakPreDestination.Upgrade();
2769         auto topDestination = weakTopDestination.Upgrade();
2770         navigationPattern->FireShowAndHideLifecycle(preDestination, topDestination, isPopPage, true);
2771         navigationPattern->TransitionWithAnimation(preDestination, topDestination, isPopPage, isNeedVisible);
2772     });
2773 }
2774 
ProcessAutoSave(const RefPtr<FrameNode> & node)2775 void NavigationPattern::ProcessAutoSave(const RefPtr<FrameNode>& node)
2776 {
2777     CHECK_NULL_VOID(node);
2778     if (!node->NeedRequestAutoSave()) {
2779         return;
2780     }
2781     auto container = Container::Current();
2782     CHECK_NULL_VOID(container);
2783     container->RequestAutoSave(node);
2784 }
2785 
NotifyDestinationLifecycle(const RefPtr<UINode> & uiNode,NavDestinationLifecycle lifecycle,NavDestinationActiveReason reason)2786 void NavigationPattern::NotifyDestinationLifecycle(const RefPtr<UINode>& uiNode,
2787     NavDestinationLifecycle lifecycle, NavDestinationActiveReason reason)
2788 {
2789     auto curDestination =
2790         AceType::DynamicCast<NavDestinationGroupNode>(NavigationGroupNode::GetNavDestinationNode(uiNode));
2791     CHECK_NULL_VOID(curDestination);
2792     auto eventHub = curDestination->GetEventHub<NavDestinationEventHub>();
2793     CHECK_NULL_VOID(eventHub);
2794     if (lifecycle == NavDestinationLifecycle::ON_WILL_DISAPPEAR) {
2795         NavigationPattern::FireNavigationLifecycleChange(curDestination, lifecycle);
2796         eventHub->FireOnWillDisAppear();
2797         return;
2798     }
2799     auto navDestinationPattern = curDestination->GetPattern<NavDestinationPattern>();
2800     CHECK_NULL_VOID(navDestinationPattern);
2801     if (lifecycle == NavDestinationLifecycle::ON_INACTIVE) {
2802         FireOnInactiveLifecycle(curDestination, reason);
2803         return;
2804     }
2805     if (lifecycle == NavDestinationLifecycle::ON_ACTIVE) {
2806         FireOnActiveLifecycle(curDestination, reason);
2807         return;
2808     }
2809     if ((navDestinationPattern->GetIsOnShow() && (lifecycle == NavDestinationLifecycle::ON_SHOW ||
2810             lifecycle == NavDestinationLifecycle::ON_WILL_SHOW)) ||
2811         (!navDestinationPattern->GetIsOnShow() && (lifecycle == NavDestinationLifecycle::ON_HIDE ||
2812             lifecycle == NavDestinationLifecycle::ON_WILL_HIDE))) {
2813         return;
2814     }
2815     if (lifecycle == NavDestinationLifecycle::ON_WILL_SHOW) {
2816         eventHub->FireOnWillShow();
2817         NavigationPattern::FireNavigationLifecycleChange(curDestination, lifecycle);
2818         return;
2819     }
2820     if (lifecycle == NavDestinationLifecycle::ON_SHOW) {
2821         FireOnShowLifecycle(curDestination);
2822         return;
2823     }
2824     NavigationPattern::FireNavigationLifecycleChange(curDestination, lifecycle);
2825     if (lifecycle == NavDestinationLifecycle::ON_WILL_HIDE) {
2826         eventHub->FireOnWillHide();
2827         return;
2828     }
2829     if (lifecycle == NavDestinationLifecycle::ON_HIDE) {
2830         eventHub->FireOnHiddenEvent(navDestinationPattern->GetName());
2831         NotifyPageHide(navDestinationPattern->GetName());
2832         navDestinationPattern->SetIsOnShow(false);
2833     }
2834 }
2835 
FireOnShowLifecycle(const RefPtr<NavDestinationGroupNode> & curDestination)2836 void NavigationPattern::FireOnShowLifecycle(const RefPtr<NavDestinationGroupNode>& curDestination)
2837 {
2838     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2839     CHECK_NULL_VOID(navigationNode);
2840     auto parentDestinationNode = navigationNode->GetParentDestinationNode().Upgrade();
2841     if (CheckParentDestinationIsOnhide(parentDestinationNode) && CheckDestinationIsPush(parentDestinationNode)) {
2842         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "parentDestinationNode is onhide");
2843         return;
2844     }
2845     auto param = Recorder::EventRecorder::Get().IsPageParamRecordEnable() ? navigationStack_->GetRouteParam() : "";
2846     auto eventHub = curDestination->GetEventHub<NavDestinationEventHub>();
2847     CHECK_NULL_VOID(eventHub);
2848     auto navDestinationPattern = curDestination->GetPattern<NavDestinationPattern>();
2849     CHECK_NULL_VOID(navDestinationPattern);
2850     eventHub->FireOnShownEvent(navDestinationPattern->GetName(), param);
2851     NotifyPageShow(navDestinationPattern->GetName());
2852     navDestinationPattern->SetIsOnShow(true);
2853     NavigationPattern::FireNavigationLifecycleChange(curDestination, NavDestinationLifecycle::ON_SHOW);
2854 }
2855 
FireOnActiveLifecycle(const RefPtr<NavDestinationGroupNode> & curDestination,NavDestinationActiveReason reason)2856 void NavigationPattern::FireOnActiveLifecycle(const RefPtr<NavDestinationGroupNode>& curDestination,
2857     NavDestinationActiveReason reason)
2858 {
2859     auto navDestinationPattern = curDestination->GetPattern<NavDestinationPattern>();
2860     CHECK_NULL_VOID(navDestinationPattern);
2861     if (navDestinationPattern->IsActive() || CheckParentDestinationInactive()) {
2862         return;
2863     }
2864     auto eventHub = curDestination->GetEventHub<NavDestinationEventHub>();
2865     CHECK_NULL_VOID(eventHub);
2866     navDestinationPattern->SetIsActive(true);
2867     eventHub->FireOnActive(static_cast<int32_t>(reason));
2868     NavigationPattern::FireNavigationLifecycle(curDestination, NavDestinationLifecycle::ON_ACTIVE, reason);
2869 }
2870 
FireOnInactiveLifecycle(const RefPtr<NavDestinationGroupNode> & curDestination,NavDestinationActiveReason reason)2871 void NavigationPattern::FireOnInactiveLifecycle(const RefPtr<NavDestinationGroupNode>& curDestination,
2872     NavDestinationActiveReason reason)
2873 {
2874     auto navDestinationPattern = curDestination->GetPattern<NavDestinationPattern>();
2875     CHECK_NULL_VOID(navDestinationPattern);
2876     if (!navDestinationPattern->IsActive()) {
2877         return;
2878     }
2879     auto eventHub = curDestination->GetEventHub<NavDestinationEventHub>();
2880     CHECK_NULL_VOID(eventHub);
2881     navDestinationPattern->SetIsActive(false);
2882     NavigationPattern::FireNavigationLifecycle(curDestination, NavDestinationLifecycle::ON_INACTIVE, reason);
2883     eventHub->FireOnInactive(static_cast<int32_t>(reason));
2884 }
2885 
GetNavdestinationJsonArray()2886 std::unique_ptr<JsonValue> NavigationPattern::GetNavdestinationJsonArray()
2887 {
2888     auto allNavdestinationInfo = JsonUtil::CreateArray(true);
2889     const auto& navdestinationNodes = GetAllNavDestinationNodes();
2890     for (auto iter : navdestinationNodes) {
2891         auto navdestinationInfo = JsonUtil::Create(true);
2892         auto navdestinationNode =
2893             AceType::DynamicCast<NavDestinationGroupNode>(NavigationGroupNode::GetNavDestinationNode(iter.second));
2894         if (!navdestinationNode) {
2895             continue;
2896         }
2897         if (!navdestinationNode->CanRecovery()) {
2898             continue;
2899         }
2900         auto navdestinationPattern = navdestinationNode->GetPattern<NavDestinationPattern>();
2901         if (!navdestinationPattern) {
2902             continue;
2903         }
2904         auto name = navdestinationPattern->GetName();
2905         auto param = navigationStack_->GetStringifyParamByIndex(navdestinationNode->GetIndex());
2906         auto mode = static_cast<int32_t>(navdestinationNode->GetNavDestinationMode());
2907         navdestinationInfo->Put("name", name.c_str());
2908         navdestinationInfo->Put("param", param.c_str());
2909         navdestinationInfo->Put("mode", mode);
2910         allNavdestinationInfo->Put(navdestinationInfo);
2911     }
2912     return allNavdestinationInfo;
2913 }
2914 
RestoreJsStackIfNeeded()2915 void NavigationPattern::RestoreJsStackIfNeeded()
2916 {
2917     auto pipeline = PipelineContext::GetCurrentContext();
2918     CHECK_NULL_VOID(pipeline);
2919     auto navigationManager = pipeline->GetNavigationManager();
2920     CHECK_NULL_VOID(navigationManager);
2921     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2922     CHECK_NULL_VOID(hostNode);
2923     auto navdestinationsInfo = navigationManager->GetNavigationRecoveryInfo(hostNode->GetCurId());
2924     if (navdestinationsInfo.empty()) {
2925         return;
2926     }
2927     navigationStack_->SetPathArray(navdestinationsInfo);
2928 }
2929 
PerformanceEventReport(int32_t nodeCount,int32_t depth,const std::string & navDestinationName)2930 void NavigationPattern::PerformanceEventReport(int32_t nodeCount, int32_t depth, const std::string& navDestinationName)
2931 {
2932     if (nodeCount >= PAGE_NODES) {
2933         EventReport::ReportPageNodeOverflow(navDestinationName, nodeCount, PAGE_NODES);
2934     }
2935     if (depth >= PAGE_DEPTH) {
2936         EventReport::ReportPageDepthOverflow(navDestinationName, depth, PAGE_DEPTH);
2937     }
2938 }
2939 
FireShowAndHideLifecycle(const RefPtr<NavDestinationGroupNode> & preDestination,const RefPtr<NavDestinationGroupNode> & topDestination,bool isPopPage,bool isAnimated)2940 void NavigationPattern::FireShowAndHideLifecycle(const RefPtr<NavDestinationGroupNode>& preDestination,
2941     const RefPtr<NavDestinationGroupNode>& topDestination, bool isPopPage, bool isAnimated)
2942 {
2943     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2944     CHECK_NULL_VOID(hostNode);
2945     // don't move position hide lifecycle is from top to end
2946     if (preDestination) {
2947         NotifyDestinationLifecycle(preDestination, NavDestinationLifecycle::ON_INACTIVE);
2948         auto lastStandardIndex = hostNode->GetLastStandardIndex();
2949         if (isPopPage || lastStandardIndex > preDestination->GetIndex() || preDestination->NeedRemoveInPush()) {
2950             // fire preTop Destination lifecycle
2951             NotifyDestinationLifecycle(preDestination, NavDestinationLifecycle::ON_HIDE);
2952         }
2953     }
2954     // fire remove navDestination and invisible navDestination lifecycle for pop or clear
2955     hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_HIDE);
2956     if (isPopPage || (preDestination && preDestination->NeedRemoveInPush())) {
2957         // fire removed preDestination lifecycle for pop many times or clear
2958         NotifyDestinationLifecycle(preDestination, NavDestinationLifecycle::ON_WILL_DISAPPEAR);
2959     }
2960     // fire removed navDestination lifecycle
2961     hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_WILL_DISAPPEAR);
2962     if (!isAnimated) {
2963         auto pipelineContext = PipelineContext::GetCurrentContext();
2964         CHECK_NULL_VOID(pipelineContext);
2965         pipelineContext->AddAfterLayoutTask([weakNavigation = WeakClaim(this),
2966             weakTopDestination = WeakPtr<NavDestinationGroupNode>(topDestination)]() {
2967             auto navigation = weakNavigation.Upgrade();
2968             CHECK_NULL_VOID(navigation);
2969             auto topDestination = weakTopDestination.Upgrade();
2970             navigation->NotifyDialogChange(NavDestinationLifecycle::ON_SHOW, true);
2971             navigation->NotifyDestinationLifecycle(topDestination, NavDestinationLifecycle::ON_ACTIVE);
2972         });
2973     } else {
2974         NotifyDialogChange(NavDestinationLifecycle::ON_SHOW, true);
2975         NotifyDestinationLifecycle(topDestination, NavDestinationLifecycle::ON_ACTIVE);
2976     }
2977     FireInterceptionEvent(false, navigationStack_->GetTopNavPath());
2978 }
2979 
OnWindowSizeChanged(int32_t,int32_t,WindowSizeChangeReason type)2980 void NavigationPattern::OnWindowSizeChanged(int32_t  /*width*/, int32_t  /*height*/, WindowSizeChangeReason type)
2981 {
2982     if (WindowSizeChangeReason::ROTATION == type) {
2983         auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2984         CHECK_NULL_VOID(hostNode);
2985         AbortAnimation(hostNode);
2986         CloseLongPressDialog();
2987     }
2988 }
2989 
OnWindowHide()2990 void NavigationPattern::OnWindowHide()
2991 {
2992     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2993     CHECK_NULL_VOID(hostNode);
2994     auto navigationPattern = hostNode->GetPattern<NavigationPattern>();
2995     CHECK_NULL_VOID(navigationPattern);
2996     navigationPattern->SyncWithJsStackIfNeeded();
2997 }
2998 
NotifyPerfMonitorPageMsg(const std::string & pageName)2999 void NavigationPattern::NotifyPerfMonitorPageMsg(const std::string& pageName)
3000 {
3001     auto container = Container::Current();
3002     if (container != nullptr && PerfMonitor::GetPerfMonitor() != nullptr) {
3003         std::string bundleName = container->GetBundleName();
3004         PerfMonitor::GetPerfMonitor()->ReportPageShowMsg("", bundleName, pageName);
3005     }
3006 }
3007 
RefreshFocusToDestination()3008 void NavigationPattern::RefreshFocusToDestination()
3009 {
3010     auto newTopNavPath = navigationStack_->GetTopNavPath();
3011     if (!newTopNavPath.has_value()) {
3012         return;
3013     }
3014     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
3015     CHECK_NULL_VOID(hostNode);
3016     auto navBarNode = AceType::DynamicCast<FrameNode>(hostNode->GetNavBarNode());
3017     CHECK_NULL_VOID(navBarNode);
3018     auto navBarFocus = navBarNode->GetFocusHub();
3019     CHECK_NULL_VOID(navBarFocus);
3020     if (!navBarFocus->IsCurrentFocus()) {
3021         return;
3022     }
3023     auto newTopNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(
3024         NavigationGroupNode::GetNavDestinationNode(newTopNavPath->second));
3025     CHECK_NULL_VOID(newTopNavDestination);
3026     if (!GetIsFocusable(newTopNavDestination)) {
3027         return;
3028     }
3029     auto navDestinationFocusView = newTopNavDestination->GetPattern<FocusView>();
3030     CHECK_NULL_VOID(navDestinationFocusView);
3031     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TWELVE)) {
3032         navDestinationFocusView->SetIsViewRootScopeFocused(false);
3033     }
3034     navDestinationFocusView->FocusViewShow();
3035 }
3036 
RecoveryToLastStack(const RefPtr<NavDestinationGroupNode> & preTopDestination,const RefPtr<NavDestinationGroupNode> & newTopDestination)3037 void NavigationPattern::RecoveryToLastStack(
3038     const RefPtr<NavDestinationGroupNode>& preTopDestination,
3039     const RefPtr<NavDestinationGroupNode>& newTopDestination)
3040 {
3041     if (preTopDestination) {
3042         preTopDestination->SetIsOnAnimation(false);
3043         preTopDestination->SetInCurrentStack(true);
3044     }
3045     if (newTopDestination) {
3046         newTopDestination->SetIsOnAnimation(false);
3047     }
3048     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
3049     CHECK_NULL_VOID(hostNode);
3050     hostNode->CleanHideNodes();
3051     CHECK_NULL_VOID(navigationStack_);
3052     navigationStack_->SetNavPathList(navigationStack_->GetRecoveryList());
3053 
3054     // update cached node
3055     auto destinationNodes = navigationStack_->GetAllNavDestinationNodes();
3056     for (uint32_t index = 0; index < destinationNodes.size(); index++) {
3057         auto childNode = destinationNodes[index];
3058         if (!childNode.second) {
3059             continue;
3060         }
3061         auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(
3062             NavigationGroupNode::GetNavDestinationNode(childNode.second));
3063         if (!navDestinationNode) {
3064             continue;
3065         }
3066         // update pre cache node to cache node list
3067         auto cacheNode = navigationStack_->GetFromCacheNode(childNode.first);
3068         if (cacheNode && cacheNode == childNode.second) {
3069             navigationStack_->AddCacheNode(childNode.first, childNode.second);
3070         }
3071     }
3072     hostNode->UpdateNavDestinationNodeWithoutMarkDirty(nullptr, navigationModeChange_);
3073 
3074     // recover lifecycle state before transition
3075     NotifyDestinationLifecycle(preTopDestination, NavDestinationLifecycle::ON_INACTIVE);
3076     hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_HIDE);
3077     hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_WILL_DISAPPEAR);
3078     NotifyDialogChange(NavDestinationLifecycle::ON_SHOW, true);
3079     NotifyDestinationLifecycle(newTopDestination, NavDestinationLifecycle::ON_ACTIVE);
3080     hostNode->RemoveDialogDestination(false, true);
3081     hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
3082 
3083     // update name index
3084     navigationStack_->RecoveryNavigationStack();
3085     ACE_SCOPED_TRACE_COMMERCIAL("Navigation page transition end");
3086     PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH, true);
3087     hostNode->SetIsOnAnimation(false);
3088     auto id = hostNode->GetTopDestination() ? hostNode->GetTopDestination()->GetAccessibilityId() : -1;
3089     hostNode->OnAccessibilityEvent(
3090         AccessibilityEventType::PAGE_CHANGE, id, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID);
3091 }
3092 
ExecuteAddAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage,const RefPtr<NavigationTransitionProxy> & proxy,NavigationTransition navigationTransition)3093 bool NavigationPattern::ExecuteAddAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
3094     const RefPtr<NavDestinationGroupNode>& newTopNavDestination,
3095     bool isPopPage, const RefPtr<NavigationTransitionProxy>& proxy,
3096     NavigationTransition navigationTransition)
3097 {
3098     // custom animation return undefined,finish this transition
3099     if (!navigationTransition.isValid) {
3100         proxy->SetIsSuccess(false);
3101         proxy->SetIsFinished(true);
3102         return false;
3103     }
3104     if (preTopNavDestination) {
3105         preTopNavDestination->SetIsOnAnimation(true);
3106         if (!isPopPage) {
3107             auto renderContext = preTopNavDestination->GetRenderContext();
3108             CHECK_NULL_RETURN(renderContext, false);
3109             renderContext->RemoveClipWithRRect();
3110         }
3111     }
3112     if (newTopNavDestination) {
3113         newTopNavDestination->SetIsOnAnimation(true);
3114     }
3115     auto proxyId = proxy->GetProxyId();
3116     proxy->SetInteractive(navigationTransition.interactive);
3117     // set on transition end callback
3118     proxy->SetEndCallback(std::move(navigationTransition.endCallback));
3119     proxy->SetFinishTransitionEvent([weakNavigation = WeakClaim(this),
3120                                         weakPreNavDestination = WeakPtr<NavDestinationGroupNode>(preTopNavDestination),
3121                                         weakNewNavDestination = WeakPtr<NavDestinationGroupNode>(newTopNavDestination),
3122                                         isPopPage, proxyId]() {
3123         auto pattern = weakNavigation.Upgrade();
3124         CHECK_NULL_VOID(pattern);
3125         auto proxy = pattern->GetProxyById(proxyId);
3126         auto preDestination = weakPreNavDestination.Upgrade();
3127         auto topDestination = weakNewNavDestination.Upgrade();
3128         // disable render group for text node after the custom animation
3129         if (isPopPage && preDestination) {
3130             preDestination->ReleaseTextNodeList();
3131         }
3132         if (!isPopPage && topDestination) {
3133             topDestination->ReleaseTextNodeList();
3134         }
3135 
3136         // to avoid call finishTransition many times
3137         if (proxy == nullptr) {
3138             TAG_LOGW(AceLogTag::ACE_NAVIGATION, "custom animation proxy is empty or is finished");
3139             return;
3140         }
3141         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "custom animation finish end");
3142         proxy->SetIsFinished(true);
3143         // update pre navigation stack
3144         ACE_SCOPED_TRACE_COMMERCIAL("navigation page custom transition end");
3145         PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH, true);
3146         pattern->ClearRecoveryList();
3147         pattern->OnCustomAnimationFinish(preDestination, topDestination, isPopPage);
3148         pattern->RemoveProxyById(proxyId);
3149     });
3150     // add timeout callback
3151     auto timeout = navigationTransition.timeout;
3152     auto hostNode = GetHost();
3153     CHECK_NULL_RETURN(hostNode, false);
3154     auto pipeline = hostNode->GetContext();
3155     CHECK_NULL_RETURN(pipeline, false);
3156     auto taskExecutor = pipeline->GetTaskExecutor();
3157     CHECK_NULL_RETURN(taskExecutor, false);
3158     if (timeout < 0) {
3159         return true;
3160     }
3161     // deal timeout callback
3162     taskExecutor->PostDelayedTask(
3163         [weakProxy = WeakPtr<NavigationTransitionProxy>(proxy)] {
3164             auto transitionProxy = weakProxy.Upgrade();
3165             CHECK_NULL_VOID(transitionProxy);
3166             transitionProxy->FireFinishCallback();
3167         },
3168         TaskExecutor::TaskType::UI, timeout, "ArkUINavigationTransitionProxyFinish");
3169     return true;
3170 }
3171 
GetIsFocusable(const RefPtr<FrameNode> & frameNode)3172 bool NavigationPattern::GetIsFocusable(const RefPtr<FrameNode>& frameNode)
3173 {
3174     CHECK_NULL_RETURN(frameNode, false);
3175     auto hostNode = AceType::DynamicCast<FrameNode>(GetHost());
3176     CHECK_NULL_RETURN(hostNode, false);
3177     auto focusHub = hostNode->GetFocusHub();
3178     CHECK_NULL_RETURN(focusHub, false);
3179     if (!focusHub->IsFocusableWholePath()) {
3180         return false;
3181     }
3182     auto currentFocusHub = frameNode->GetFocusHub();
3183     CHECK_NULL_RETURN(currentFocusHub, false);
3184     return currentFocusHub->IsFocusableNode();
3185 }
3186 
IsLastStdChange()3187 bool NavigationPattern::IsLastStdChange()
3188 {
3189     // check whether last std navdestination id is changed, change return true, not change return false
3190     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
3191     CHECK_NULL_RETURN(navigationNode, false);
3192     auto& navPathList = navigationStack_->GetAllNavDestinationNodes();
3193     auto& preNavPathList = navigationStack_->GetAllNavDestinationNodesPrev();
3194     auto lastStdIndex = navigationNode->GetLastStandardIndex();
3195     auto preLastStdIndex = navigationNode->GetPreLastStandardIndex();
3196     if (preLastStdIndex == -1 && lastStdIndex == -1) {
3197         return false;
3198     }
3199     if (preLastStdIndex != -1 && lastStdIndex != -1) {
3200         // check new and pre std navdestination id changed or not
3201         auto preStd = NavigationGroupNode::GetNavDestinationNode(preNavPathList[preLastStdIndex].second.Upgrade());
3202         auto newStd = NavigationGroupNode::GetNavDestinationNode(navPathList[lastStdIndex].second);
3203         if (preStd && newStd) {
3204             return preStd != newStd;
3205         }
3206     }
3207     return true;
3208 }
3209 
FollowStdNavdestinationAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage)3210 void NavigationPattern::FollowStdNavdestinationAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
3211     const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage)
3212 {
3213     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
3214     CHECK_NULL_VOID(navigationNode);
3215     if (preTopNavDestination && newTopNavDestination) {
3216         if (isPopPage) {
3217             navigationNode->TransitionWithDialogPop(preTopNavDestination, newTopNavDestination);
3218         } else {
3219             navigationNode->TransitionWithDialogPush(preTopNavDestination, newTopNavDestination);
3220         }
3221         return;
3222     }
3223     if (newTopNavDestination && navigationMode_ == NavigationMode::STACK) {
3224         auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationNode->GetNavBarNode());
3225         CHECK_NULL_VOID(navBarNode);
3226         navigationNode->TransitionWithDialogPush(navBarNode, newTopNavDestination, true);
3227         return;
3228     }
3229     if (preTopNavDestination) {
3230         if (navigationMode_ == NavigationMode::SPLIT) {
3231             navigationNode->TransitionWithDialogPop(preTopNavDestination, nullptr);
3232         }
3233         if (navigationMode_ == NavigationMode::STACK) {
3234             auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationNode->GetNavBarNode());
3235             CHECK_NULL_VOID(navBarNode);
3236             navigationNode->TransitionWithDialogPop(preTopNavDestination, navBarNode, true);
3237         }
3238     }
3239 }
3240 
TransitionWithDialogAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage)3241 void NavigationPattern::TransitionWithDialogAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
3242     const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage)
3243 {
3244     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
3245     CHECK_NULL_VOID(navigationNode);
3246 
3247     // if last standard id is not changed and new top navdestination is standard
3248     if (!isPopPage && !IsLastStdChange() && newTopNavDestination &&
3249         newTopNavDestination->GetNavDestinationMode() == NavDestinationMode::STANDARD) {
3250         return;
3251     }
3252     auto replaceVal = navigationStack_->GetReplaceValue();
3253     if (replaceVal != 0) {
3254         ReplaceAnimation(preTopNavDestination, newTopNavDestination);
3255         return;
3256     }
3257     // last std id is not change, but new dialogs came into stack and upward animation
3258     if (!IsLastStdChange()) {
3259         if (isPopPage) {
3260             navigationNode->StartDialogtransition(preTopNavDestination, newTopNavDestination, false);
3261         } else {
3262             if (!preTopNavDestination && navigationMode_ == NavigationMode::SPLIT) {
3263                 // if split mode and push one dialog at the first time, no animation
3264                 return;
3265             }
3266             navigationNode->StartDialogtransition(preTopNavDestination, newTopNavDestination, true);
3267         }
3268         return;
3269     }
3270     FollowStdNavdestinationAnimation(preTopNavDestination, newTopNavDestination, isPopPage);
3271 }
3272 
DumpInfo(std::unique_ptr<JsonValue> & json)3273 void NavigationPattern::DumpInfo(std::unique_ptr<JsonValue>& json)
3274 {
3275     if (!navigationStack_) {
3276         return;
3277     }
3278     json->Put("size", std::to_string(navigationStack_->Size()).c_str());
3279 }
3280 
CreateDragBarNode(const RefPtr<NavigationGroupNode> & navigationGroupNode)3281 void NavigationPattern::CreateDragBarNode(const RefPtr<NavigationGroupNode>& navigationGroupNode)
3282 {
3283     auto dragBarNode = FrameNode::GetOrCreateFrameNode("DragBar", ElementRegister::GetInstance()->MakeUniqueId(),
3284         []() { return AceType::MakeRefPtr<NavigationDragBarPattern>(); });
3285     auto dragBarLayoutProperty = dragBarNode->GetLayoutProperty();
3286     CHECK_NULL_VOID(dragBarLayoutProperty);
3287     auto theme = NavigationGetTheme();
3288     CHECK_NULL_VOID(theme);
3289     auto renderContext = dragBarNode->GetRenderContext();
3290     CHECK_NULL_VOID(renderContext);
3291     renderContext->UpdateBackBlurRadius(DRAG_BAR_BLUR_RADIUS);
3292     renderContext->UpdateBorderRadius(BorderRadiusProperty(DRAG_BAR_RADIUS));
3293     renderContext->UpdateZIndex(1);
3294     dragBarNode->MarkModifyDone();
3295     auto dragBarItem = CreateDragBarItemNode();
3296     dragBarItem->MountToParent(dragBarNode);
3297     dragBarNode->MountToParent(navigationGroupNode);
3298     navigationGroupNode->SetDragBarNode(dragBarNode);
3299 
3300     auto dragBarPattern = dragBarNode->GetPattern<NavigationDragBarPattern>();
3301     CHECK_NULL_VOID(dragBarPattern);
3302     dragBarPattern->UpdateDefaultColor();
3303 }
3304 
CreateDragBarItemNode()3305 RefPtr<FrameNode> NavigationPattern::CreateDragBarItemNode()
3306 {
3307     auto dragBarItemNode = FrameNode::GetOrCreateFrameNode("DragBarItem",
3308         ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<Pattern>(); });
3309     auto dragBarItemLayoutProperty = dragBarItemNode->GetLayoutProperty();
3310     CHECK_NULL_RETURN(dragBarItemLayoutProperty, nullptr);
3311     dragBarItemLayoutProperty->UpdateAlignment(Alignment::CENTER);
3312     auto renderContext = dragBarItemNode->GetRenderContext();
3313     CHECK_NULL_RETURN(renderContext, nullptr);
3314     renderContext->UpdateZIndex(SECOND_ZINDEX_VALUE);
3315     renderContext->UpdateBorderRadius(BorderRadiusProperty(DRAG_BAR_ITEM_RADIUS));
3316     dragBarItemNode->MarkModifyDone();
3317     return dragBarItemNode;
3318 }
3319 
GetProxyById(uint64_t id) const3320 RefPtr<NavigationTransitionProxy> NavigationPattern::GetProxyById(uint64_t id) const
3321 {
3322     for (auto proxy : proxyList_) {
3323         if (proxy && proxy->GetProxyId() == id) {
3324             return proxy;
3325         }
3326     }
3327     return nullptr;
3328 }
3329 
RemoveProxyById(uint64_t id)3330 void NavigationPattern::RemoveProxyById(uint64_t id)
3331 {
3332     for (auto it = proxyList_.begin(); it != proxyList_.end(); ++it) {
3333         if (*it && (*it)->GetProxyId() == id) {
3334             it = proxyList_.erase(it);
3335             return;
3336         }
3337     }
3338 }
3339 
InitTouchEvent(const RefPtr<GestureEventHub> & gestureHub)3340 void NavigationPattern::InitTouchEvent(const RefPtr<GestureEventHub>& gestureHub)
3341 {
3342     if (touchEvent_) {
3343         return;
3344     }
3345     auto touchTask = [weak = WeakClaim(this)](const TouchEventInfo& info) {
3346         auto pattern = weak.Upgrade();
3347         CHECK_NULL_VOID(pattern);
3348         pattern->HandleTouchEvent(info);
3349     };
3350     touchEvent_ = MakeRefPtr<TouchEventImpl>(std::move(touchTask));
3351     gestureHub->AddTouchEvent(touchEvent_);
3352 }
3353 
HandleTouchEvent(const TouchEventInfo & info)3354 void NavigationPattern::HandleTouchEvent(const TouchEventInfo& info)
3355 {
3356     auto touchType = info.GetTouches().front().GetTouchType();
3357     if (touchType == TouchType::DOWN) {
3358         HandleTouchDown();
3359     }
3360     if (touchType == TouchType::UP || touchType == TouchType::CANCEL) {
3361         HandleTouchUp();
3362     }
3363 }
3364 
HandleTouchDown()3365 void NavigationPattern::HandleTouchDown()
3366 {
3367     auto dragBarNode = GetDragBarNode();
3368     CHECK_NULL_VOID(dragBarNode);
3369     auto dragPattern = dragBarNode->GetPattern<NavigationDragBarPattern>();
3370     CHECK_NULL_VOID(dragPattern);
3371     dragPattern->UpdateActiveColor();
3372 
3373     auto dividerNode = GetDividerNode();
3374     CHECK_NULL_VOID(dividerNode);
3375     auto dividerRenderContext = dividerNode->GetRenderContext();
3376     CHECK_NULL_VOID(dividerRenderContext);
3377     auto theme = NavigationGetTheme();
3378     CHECK_NULL_VOID(theme);
3379     NG::Gradient gradient;
3380     gradient.CreateGradientWithType(NG::GradientType::LINEAR);
3381     gradient.AddColor(CreatePercentGradientColor(0, theme->GetDviderLightBlueColor()));
3382     gradient.AddColor(CreatePercentGradientColor(HALF_POSITION, theme->GetDviderDarkBlueColor()));
3383     gradient.AddColor(CreatePercentGradientColor(END_POSITION, theme->GetDviderLightBlueColor()));
3384     dividerRenderContext->UpdateBackgroundColor(Color::TRANSPARENT);
3385     dividerRenderContext->UpdateLinearGradient(gradient);
3386 }
3387 
HandleTouchUp()3388 void NavigationPattern::HandleTouchUp()
3389 {
3390     auto dragBarNode = GetDragBarNode();
3391     CHECK_NULL_VOID(dragBarNode);
3392     auto dragPattern = dragBarNode->GetPattern<NavigationDragBarPattern>();
3393     CHECK_NULL_VOID(dragPattern);
3394     dragPattern->UpdateDefaultColor();
3395 
3396     auto theme = NavigationGetTheme();
3397     CHECK_NULL_VOID(theme);
3398     auto dividerNode = GetDividerNode();
3399     CHECK_NULL_VOID(dividerNode);
3400     NG::Gradient gradient;
3401     gradient.CreateGradientWithType(NG::GradientType::LINEAR);
3402     gradient.AddColor(CreatePercentGradientColor(0, Color::TRANSPARENT));
3403     dividerNode->GetRenderContext()->UpdateLinearGradient(gradient);
3404     dividerNode->GetRenderContext()->UpdateBackgroundColor(theme->GetNavigationDividerColor());
3405 }
3406 
CheckContentNeedMeasure(const RefPtr<FrameNode> & node)3407 void NavigationPattern::CheckContentNeedMeasure(const RefPtr<FrameNode>& node)
3408 {
3409     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(node);
3410     CHECK_NULL_VOID(navigationNode);
3411     auto navigationLayoutProperty = navigationNode->GetLayoutProperty<NavigationLayoutProperty>();
3412     CHECK_NULL_VOID(navigationLayoutProperty);
3413     if (!NavigationLayoutAlgorithm::IsAutoHeight(navigationLayoutProperty)) {
3414         return;
3415     }
3416     TAG_LOGI(AceLogTag::ACE_NAVIGATION, "Navigation height is auto, content need to measure after pushAnimation ends");
3417     auto contentNode = navigationNode->GetContentNode();
3418     CHECK_NULL_VOID(contentNode);
3419     contentNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
3420 }
3421 
CloseLongPressDialog()3422 void NavigationPattern::CloseLongPressDialog()
3423 {
3424     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
3425     CHECK_NULL_VOID(hostNode);
3426     auto pipeline = hostNode->GetContext();
3427     CHECK_NULL_VOID(pipeline);
3428     auto overlayManager = pipeline->GetOverlayManager();
3429     CHECK_NULL_VOID(overlayManager);
3430 
3431     auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
3432     CHECK_NULL_VOID(navBarNode);
3433     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navBarNode->GetTitleBarNode());
3434     CHECK_NULL_VOID(titleBarNode);
3435     auto titleBarPattern = AceType::DynamicCast<TitleBarPattern>(titleBarNode->GetPattern());
3436     CHECK_NULL_VOID(titleBarPattern);
3437     auto backButtonDialogNode = titleBarPattern->GetBackButtonDialogNode();
3438     if (backButtonDialogNode) {
3439         overlayManager->CloseDialog(backButtonDialogNode);
3440         titleBarPattern->SetBackButtonDialogNode(nullptr);
3441     }
3442 
3443     auto menuItemDialogNode = titleBarPattern->GetLargeFontPopUpDialogNode();
3444     if (menuItemDialogNode) {
3445         overlayManager->CloseDialog(menuItemDialogNode);
3446         titleBarPattern->SetLargeFontPopUpDialogNode(nullptr);
3447     }
3448 
3449     auto toolBarNode = AceType::DynamicCast<NavToolbarNode>(navBarNode->GetToolBarNode());
3450     CHECK_NULL_VOID(toolBarNode);
3451     auto toolBarPattern = AceType::DynamicCast<NavToolbarPattern>(toolBarNode->GetPattern());
3452     CHECK_NULL_VOID(toolBarPattern);
3453     auto toolBarItemDialogNode = toolBarPattern->GetDialogNode();
3454     if (toolBarItemDialogNode) {
3455         overlayManager->CloseDialog(toolBarItemDialogNode);
3456         toolBarPattern->SetToolBarItemDialogNode(nullptr);
3457     }
3458 }
3459 
FindInCurStack(const RefPtr<FrameNode> & navDestinationNode)3460 bool NavigationPattern::FindInCurStack(const RefPtr<FrameNode>& navDestinationNode)
3461 {
3462     const auto& navdestinationNodes = GetAllNavDestinationNodes();
3463     for (auto navdestination : navdestinationNodes) {
3464         if (navDestinationNode == NavigationGroupNode::GetNavDestinationNode(navdestination.second)) {
3465             return true;
3466         }
3467     }
3468     return false;
3469 }
3470 
SetMouseStyle(MouseFormat format)3471 void NavigationPattern::SetMouseStyle(MouseFormat format)
3472 {
3473     auto host = GetHost();
3474     CHECK_NULL_VOID(host);
3475     auto pipeline = host->GetContextWithCheck();
3476     CHECK_NULL_VOID(pipeline);
3477     auto frameNodeId = host->GetId();
3478     int32_t windowId = static_cast<int32_t>(pipeline->GetFocusWindowId());
3479 #ifdef WINDOW_SCENE_SUPPORTED
3480     windowId = static_cast<int32_t>(WindowSceneHelper::GetFocusSystemWindowId(host));
3481 #endif
3482     pipeline->SetMouseStyleHoldNode(frameNodeId);
3483     pipeline->ChangeMouseStyle(frameNodeId, format, windowId);
3484     pipeline->FreeMouseStyleHoldNode(frameNodeId);
3485 }
3486 
OnAvoidInfoChange(const ContainerModalAvoidInfo & info)3487 void NavigationPattern::OnAvoidInfoChange(const ContainerModalAvoidInfo& info)
3488 {
3489     if (!isFullPageNavigation_) {
3490         return;
3491     }
3492     MarkAllNavDestinationDirtyIfNeeded(GetHost(), true);
3493 }
3494 
RegisterAvoidInfoChangeListener(const RefPtr<FrameNode> & hostNode)3495 void NavigationPattern::RegisterAvoidInfoChangeListener(const RefPtr<FrameNode>& hostNode)
3496 {
3497     CHECK_NULL_VOID(hostNode);
3498     auto pipeline = hostNode->GetContext();
3499     CHECK_NULL_VOID(pipeline);
3500     auto mgr = pipeline->GetAvoidInfoManager();
3501     CHECK_NULL_VOID(mgr);
3502     mgr->AddAvoidInfoListener(WeakClaim(this));
3503 }
3504 
UnregisterAvoidInfoChangeListener(const RefPtr<FrameNode> & hostNode)3505 void NavigationPattern::UnregisterAvoidInfoChangeListener(const RefPtr<FrameNode>& hostNode)
3506 {
3507     CHECK_NULL_VOID(hostNode);
3508     auto pipeline = hostNode->GetContext();
3509     CHECK_NULL_VOID(pipeline);
3510     auto mgr = pipeline->GetAvoidInfoManager();
3511     CHECK_NULL_VOID(mgr);
3512     mgr->RemoveAvoidInfoListener(WeakClaim(this));
3513 }
3514 
MarkAllNavDestinationDirtyIfNeeded(const RefPtr<FrameNode> & hostNode,bool skipCheck)3515 void NavigationPattern::MarkAllNavDestinationDirtyIfNeeded(const RefPtr<FrameNode>& hostNode, bool skipCheck)
3516 {
3517     auto groupNode = AceType::DynamicCast<NavigationGroupNode>(hostNode);
3518     CHECK_NULL_VOID(groupNode);
3519     if (!skipCheck) {
3520         auto pipeline = groupNode->GetContext();
3521         CHECK_NULL_VOID(pipeline);
3522         auto avoidInfoMgr = pipeline->GetAvoidInfoManager();
3523         CHECK_NULL_VOID(avoidInfoMgr);
3524         if (!avoidInfoMgr->NeedAvoidContainerModal()) {
3525             return;
3526         }
3527     }
3528 
3529     auto contentNode = AceType::DynamicCast<FrameNode>(groupNode->GetContentNode());
3530     CHECK_NULL_VOID(contentNode);
3531     auto& childrens = contentNode->GetChildren();
3532     for (auto& child : childrens) {
3533         auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(child);
3534         if (!navDestination) {
3535             continue;
3536         }
3537         if (!navDestination->IsVisible()) {
3538             navDestination->SetNeedForceMeasure(true);
3539             continue;
3540         }
3541         navDestination->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
3542         auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navDestination->GetTitleBarNode());
3543         if (titleBarNode) {
3544             titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3545         }
3546     }
3547 }
3548 
FireNavigationLifecycle(const RefPtr<UINode> & uiNode,NavDestinationLifecycle lifecycle,NavDestinationActiveReason reason)3549 void NavigationPattern::FireNavigationLifecycle(const RefPtr<UINode>& uiNode, NavDestinationLifecycle lifecycle,
3550     NavDestinationActiveReason reason)
3551 {
3552     auto frameNode = AceType::DynamicCast<FrameNode>(uiNode);
3553     CHECK_NULL_VOID(frameNode);
3554     auto context = frameNode->GetContextRefPtr();
3555     CHECK_NULL_VOID(context);
3556     auto navigationManager = context->GetNavigationManager();
3557     CHECK_NULL_VOID(navigationManager);
3558     auto navigationIds = navigationManager->FindNavigationInTargetParent(frameNode->GetId());
3559     for (auto navigationId: navigationIds) {
3560         auto navigation = AceType::DynamicCast<NavigationGroupNode>(
3561             FrameNode::GetFrameNode(V2::NAVIGATION_VIEW_ETS_TAG, navigationId));
3562         if (!navigation) {
3563             continue;
3564         }
3565         auto pattern = navigation->GetPattern<NavigationPattern>();
3566         if (!pattern) {
3567             continue;
3568         }
3569         auto navigationStack = pattern->GetNavigationStack();
3570         if (navigationStack) {
3571             pattern->NotifyDestinationLifecycle(AceType::DynamicCast<NavDestinationGroupNode>(
3572                 NavigationGroupNode::GetNavDestinationNode(navigationStack->Get())), lifecycle, reason);
3573         }
3574     }
3575 }
3576 
GenerateLastStandardPage(NavPathList & navPathList)3577 void NavigationPattern::GenerateLastStandardPage(NavPathList& navPathList)
3578 {
3579     int64_t lastPageIndex = navPathList.size() - 1;
3580     // if top page is nullptr or is dialog node, we need to generate node util standard page is found.
3581     while (lastPageIndex >= 0 &&
3582         (navPathList[lastPageIndex].second == nullptr || !IsStandardPage(navPathList[lastPageIndex].second))) {
3583         auto pageNode = navPathList[lastPageIndex].second;
3584         // existed dialog node is no need to generate
3585         bool isExistedNode = (pageNode != nullptr);
3586         if (!pageNode && !GenerateUINodeByIndex(lastPageIndex, pageNode)) {
3587             std::string replacedName;
3588             int32_t replacedIndex = -1;
3589             if (navigationStack_->CheckIsReplacedDestination(lastPageIndex, replacedName, replacedIndex)) {
3590                 navigationStack_->SetRecoveryFromReplaceDestination(lastPageIndex, false);
3591                 continue;
3592             }
3593             navPathList.erase(navPathList.begin() + lastPageIndex);
3594             lastPageIndex--;
3595             continue;
3596         }
3597         navPathList[lastPageIndex].second = pageNode;
3598         auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(
3599             NavigationGroupNode::GetNavDestinationNode(pageNode));
3600         if (!isExistedNode && navDestinationNode && navigationStack_->GetIsForceSet(lastPageIndex)) {
3601             navigationStack_->ResetIsForceSetFlag(lastPageIndex);
3602         }
3603         if (navDestinationNode && navDestinationNode->GetNavDestinationMode() == NavDestinationMode::STANDARD) {
3604             break;
3605         }
3606         lastPageIndex--;
3607     }
3608 }
3609 
IsStandardPage(const RefPtr<UINode> & uiNode) const3610 bool NavigationPattern::IsStandardPage(const RefPtr<UINode>& uiNode) const
3611 {
3612     auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(
3613         NavigationGroupNode::GetNavDestinationNode(uiNode));
3614     CHECK_NULL_RETURN(navDestinationNode, false);
3615     return navDestinationNode->GetNavDestinationMode() == NavDestinationMode::STANDARD;
3616 }
3617 
FindNavDestinationNodeInPreList(const uint64_t navDestinationId) const3618 RefPtr<UINode> NavigationPattern::FindNavDestinationNodeInPreList(const uint64_t navDestinationId) const
3619 {
3620     CHECK_NULL_RETURN(navigationStack_, nullptr);
3621     auto preNavDestinationList = navigationStack_->GetAllNavDestinationNodesPrev();
3622     for (auto preNavDestinationInfo : preNavDestinationList) {
3623         auto preNavDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(
3624             NavigationGroupNode::GetNavDestinationNode(preNavDestinationInfo.second.Upgrade()));
3625         CHECK_NULL_CONTINUE(preNavDestinationNode);
3626         auto pattern = preNavDestinationNode->GetPattern<NavDestinationPattern>();
3627         CHECK_NULL_CONTINUE(pattern);
3628         auto preId = pattern->GetNavDestinationId();
3629         if (preId == navDestinationId) {
3630             return preNavDestinationInfo.second.Upgrade();
3631         }
3632     }
3633     return nullptr;
3634 }
3635 
FireOnNewParam(const RefPtr<UINode> & uiNode)3636 void NavigationPattern::FireOnNewParam(const RefPtr<UINode>& uiNode)
3637 {
3638     CHECK_NULL_VOID(uiNode);
3639     auto navDestination = DynamicCast<NavDestinationGroupNode>(NavigationGroupNode::GetNavDestinationNode(uiNode));
3640     CHECK_NULL_VOID(navDestination);
3641     auto navDestinationPattern = navDestination->GetPattern<NavDestinationPattern>();
3642     CHECK_NULL_VOID(navDestinationPattern);
3643     auto navPathInfo = navDestinationPattern->GetNavPathInfo();
3644     CHECK_NULL_VOID(navPathInfo);
3645     auto eventHub = navDestination->GetEventHub<NavDestinationEventHub>();
3646     CHECK_NULL_VOID(eventHub);
3647     eventHub->FireOnNewParam(navPathInfo->GetParamObj());
3648 }
3649 
ClearRecoveryList()3650 void NavigationPattern::ClearRecoveryList()
3651 {
3652     if (!isFinishInteractiveAnimation_) {
3653         return;
3654     }
3655     CHECK_NULL_VOID(navigationStack_);
3656     navigationStack_->ClearRecoveryList();
3657 }
3658 } // namespace OHOS::Ace::NG
3659