• 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 #include <string>
18 
19 #include "base/geometry/dimension.h"
20 #include "base/log/dump_log.h"
21 #include "base/log/event_report.h"
22 #include "base/perfmonitor/perf_constants.h"
23 #include "base/perfmonitor/perf_monitor.h"
24 #include "core/common/container.h"
25 #include "core/common/ime/input_method_manager.h"
26 #include "core/common/manager_interface.h"
27 #include "core/components_ng/base/observer_handler.h"
28 #include "core/components_ng/pattern/navigation/nav_bar_layout_property.h"
29 #include "core/components_ng/pattern/navigation/nav_bar_pattern.h"
30 #include "core/components_ng/pattern/navigation/nav_bar_node.h"
31 #include "core/components_ng/pattern/navigation/navigation_model_data.h"
32 #include "core/components_ng/pattern/navigation/title_bar_pattern.h"
33 #include "core/components_ng/pattern/stage/page_pattern.h"
34 #include "core/components_ng/pattern/text_field/text_field_manager.h"
35 
36 namespace OHOS::Ace::NG {
37 
38 constexpr int32_t NAVIMODE_CHANGE_ANIMATION_DURATION = 250;
39 constexpr int32_t OPACITY_ANIMATION_DURATION_APPEAR = 150;
40 constexpr int32_t OPACITY_ANIMATION_DURATION_DISAPPEAR = 250;
41 constexpr int32_t EMPTY_DESTINATION_CHILD_SIZE = 1;
42 constexpr Dimension DEFAULT_DRAG_REGION = 12.0_vp;
43 constexpr float DEFAULT_HALF = 2.0f;
44 const Color MASK_COLOR = Color::FromARGB(25, 0, 0, 0);
45 constexpr int32_t PAGE_NODES = 1000;
46 constexpr int32_t PAGE_DEPTH = 300;
47 namespace {
48 constexpr static int32_t PLATFORM_VERSION_TEN = 10;
49 constexpr int32_t MODE_SWITCH_ANIMATION_DURATION = 500; // ms
50 const RefPtr<CubicCurve> MODE_SWITCH_CURVE = AceType::MakeRefPtr<CubicCurve>(0.2f, 0.2f, 0.1f, 1.0f);
51 
BuildNavDestinationInfoFromContext(const std::string & navigationId,NavDestinationState state,const RefPtr<NavDestinationContext> & context,bool isFrom,std::optional<NavDestinationInfo> & info)52 void BuildNavDestinationInfoFromContext(const std::string& navigationId, NavDestinationState state,
53     const RefPtr<NavDestinationContext>& context, bool isFrom, std::optional<NavDestinationInfo>& info)
54 {
55     if (!context) {
56         info.reset();
57         return;
58     }
59 
60     int32_t index = isFrom ? context->GetPreIndex() : context->GetIndex();
61     std::string navDestinationId = std::to_string(context->GetNavDestinationId());
62     std::string name;
63     napi_value param = nullptr;
64     auto pathInfo = context->GetNavPathInfo();
65     if (pathInfo) {
66         name = pathInfo->GetName();
67         param = pathInfo->GetParamObj();
68     }
69     info = std::make_optional<NavDestinationInfo>(navigationId, name, state, index, param, navDestinationId);
70 }
71 } // namespace
72 
NavigationPattern()73 NavigationPattern::NavigationPattern()
74 {
75     navigationController_ = std::make_shared<InnerNavigationController>(WeakClaim(this), Container::CurrentId());
76 }
77 
GetTitleBarRenderContext()78 RefPtr<RenderContext> NavigationPattern::GetTitleBarRenderContext()
79 {
80     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
81     CHECK_NULL_RETURN(hostNode, nullptr);
82     auto layoutProperty = GetLayoutProperty<NavigationLayoutProperty>();
83     CHECK_NULL_RETURN(layoutProperty, nullptr);
84     auto contentNode = AceType::DynamicCast<FrameNode>(hostNode->GetContentNode());
85     CHECK_NULL_RETURN(contentNode, nullptr);
86     if (contentNode->FindChildNodeOfClass<NavDestinationGroupNode>()) {
87         auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
88         CHECK_NULL_RETURN(navBarNode, nullptr);
89         auto renderContext = navBarNode->GetRenderContext();
90         return renderContext;
91     } else {
92         auto renderContext = contentNode->GetRenderContext();
93         return renderContext;
94     }
95 }
96 
DoAnimation(NavigationMode usrNavigationMode)97 void NavigationPattern::DoAnimation(NavigationMode usrNavigationMode)
98 {
99     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
100     CHECK_NULL_VOID(hostNode);
101     auto layoutProperty = GetLayoutProperty<NavigationLayoutProperty>();
102     CHECK_NULL_VOID(layoutProperty);
103 
104     auto context = PipelineContext::GetCurrentContext();
105     CHECK_NULL_VOID(context);
106     layoutProperty->UpdateNavigationMode(navigationMode_);
107     hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
108     AnimationOption option = AnimationOption();
109     option.SetDuration(NAVIMODE_CHANGE_ANIMATION_DURATION);
110     option.SetCurve(Curves::FRICTION);
111     option.SetFillMode(FillMode::FORWARDS);
112     AnimationOption optionAlpha = AnimationOption();
113     optionAlpha.SetCurve(Curves::SHARP);
114     optionAlpha.SetFillMode(FillMode::FORWARDS);
115     auto renderContext = GetTitleBarRenderContext();
116     CHECK_NULL_VOID(renderContext);
117 
118     std::function<void()> finishCallback = [optionAlpha, renderContext, hostNode]() {
119         renderContext->OpacityAnimation(optionAlpha, 0, 1);
120         hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
121     };
122 
123     context->OpenImplicitAnimation(option, option.GetCurve(), finishCallback);
124     layoutProperty->UpdateNavigationMode(usrNavigationMode);
125     hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
126     context->FlushUITasks();
127     if (usrNavigationMode == NavigationMode::STACK || navigationMode_ == NavigationMode::SPLIT) {
128         optionAlpha.SetDuration(OPACITY_ANIMATION_DURATION_DISAPPEAR);
129         renderContext->OpacityAnimation(optionAlpha, 1, 0);
130     } else if (usrNavigationMode == NavigationMode::SPLIT || navigationMode_ == NavigationMode::STACK) {
131         optionAlpha.SetDuration(OPACITY_ANIMATION_DURATION_APPEAR);
132         renderContext->OpacityAnimation(optionAlpha, 0, 1);
133     }
134     context->CloseImplicitAnimation();
135     navigationMode_ = usrNavigationMode;
136 }
137 
OnAttachToFrameNode()138 void NavigationPattern::OnAttachToFrameNode()
139 {
140     auto host = GetHost();
141     CHECK_NULL_VOID(host);
142     auto pipelineContext = PipelineContext::GetCurrentContext();
143     CHECK_NULL_VOID(pipelineContext);
144     pipelineContext->AddWindowStateChangedCallback(host->GetId());
145     pipelineContext->AddWindowSizeChangeCallback(host->GetId());
146 
147     auto theme = NavigationGetTheme();
148     if (theme && theme->GetNavBarUnfocusEffectEnable()) {
149         pipelineContext->AddWindowFocusChangedCallback(host->GetId());
150     }
151     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
152         SafeAreaExpandOpts opts = { .type = SAFE_AREA_TYPE_ALL, .edges = SAFE_AREA_EDGE_ALL };
153         host->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
154     }
155 }
156 
OnDetachFromFrameNode(FrameNode * frameNode)157 void NavigationPattern::OnDetachFromFrameNode(FrameNode* frameNode)
158 {
159     auto id = frameNode->GetId();
160     auto pipeline = AceType::DynamicCast<PipelineContext>(PipelineBase::GetCurrentContext());
161     CHECK_NULL_VOID(pipeline);
162     pipeline->RemoveWindowStateChangedCallback(id);
163     pipeline->RemoveWindowSizeChangeCallback(id);
164 }
165 
166 
DoNavbarHideAnimation(const RefPtr<NavigationGroupNode> & hostNode)167 void NavigationPattern::DoNavbarHideAnimation(const RefPtr<NavigationGroupNode>& hostNode)
168 {
169     AnimationOption option;
170     option.SetCurve(MODE_SWITCH_CURVE);
171     option.SetFillMode(FillMode::FORWARDS);
172     option.SetDuration(MODE_SWITCH_ANIMATION_DURATION);
173     AnimationUtils::Animate(option, [weakHost = WeakPtr<NavigationGroupNode>(hostNode)]() {
174         auto hostNode = weakHost.Upgrade();
175         CHECK_NULL_VOID(hostNode);
176         auto layoutProperty = AceType::DynamicCast<NavigationLayoutProperty>(hostNode->GetLayoutProperty());
177         CHECK_NULL_VOID(layoutProperty);
178         bool hideNavBar = layoutProperty->GetHideNavBarValue(false);
179         auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
180         CHECK_NULL_VOID(navBarNode);
181         auto navBarLayoutProperty = navBarNode->GetLayoutProperty();
182         CHECK_NULL_VOID(navBarLayoutProperty);
183         navBarLayoutProperty->UpdateVisibility(hideNavBar ? VisibleType::INVISIBLE : VisibleType::VISIBLE, true);
184         hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
185         hostNode->GetContext()->FlushUITasks();
186     });
187 }
188 
OnModifyDone()189 void NavigationPattern::OnModifyDone()
190 {
191     // !!! Do not add operations about NavPathStack here, see @SyncWithJsStackIfNeeded
192     Pattern::OnModifyDone();
193     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
194     CHECK_NULL_VOID(hostNode);
195     auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
196     CHECK_NULL_VOID(navBarNode);
197     navBarNode->MarkModifyDone();
198     isRightToLeft_ = AceApplicationInfo::GetInstance().IsRightToLeft();
199 
200     auto pipeline = PipelineContext::GetCurrentContext();
201     CHECK_NULL_VOID(pipeline);
202     auto currentPlatformVersion = pipeline->GetMinPlatformVersion();
203     if (currentPlatformVersion >= PLATFORM_VERSION_TEN) {
204         auto dividerNode = GetDividerNode();
205         CHECK_NULL_VOID(dividerNode);
206         auto gestureHub = dividerNode->GetOrCreateGestureEventHub();
207         CHECK_NULL_VOID(gestureHub);
208         InitPanEvent(gestureHub);
209         auto inputHub = dividerNode->GetOrCreateInputEventHub();
210         CHECK_NULL_VOID(inputHub);
211         InitDividerMouseEvent(inputHub);
212     }
213 
214     auto layoutProperty = hostNode->GetLayoutProperty();
215     CHECK_NULL_VOID(layoutProperty);
216     auto&& opts = layoutProperty->GetSafeAreaExpandOpts();
217     if (opts) {
218         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "Navigation SafArea expand as %{public}s", opts->ToString().c_str());
219         uint8_t ignoreExpandKeyboard = 0x11;
220         SafeAreaExpandOpts optsExceptKeyboard = { .type = opts->type & ignoreExpandKeyboard,
221             .edges = opts->edges };
222         navBarNode->GetLayoutProperty()->UpdateSafeAreaExpandOpts(optsExceptKeyboard);
223         navBarNode->MarkModifyDone();
224 
225         auto navigationContentNode = AceType::DynamicCast<FrameNode>(hostNode->GetContentNode());
226         CHECK_NULL_VOID(navigationContentNode);
227         navigationContentNode->GetLayoutProperty()->UpdateSafeAreaExpandOpts(optsExceptKeyboard);
228         navigationContentNode->MarkModifyDone();
229 
230         auto dividerNode = AceType::DynamicCast<FrameNode>(hostNode->GetDividerNode());
231         CHECK_NULL_VOID(dividerNode);
232         dividerNode->GetLayoutProperty()->UpdateSafeAreaExpandOpts(optsExceptKeyboard);
233         dividerNode->MarkModifyDone();
234     }
235 
236     if (GetNavigationMode() == NavigationMode::SPLIT && GetNavBarVisibilityChange()) {
237         DoNavbarHideAnimation(hostNode);
238     }
239 }
240 
SetSystemBarStyle(const RefPtr<SystemBarStyle> & style)241 void NavigationPattern::SetSystemBarStyle(const RefPtr<SystemBarStyle>& style)
242 {
243     auto host = GetHost();
244     CHECK_NULL_VOID(host);
245     auto pipeline = host->GetContext();
246     CHECK_NULL_VOID(pipeline);
247     auto windowManager = pipeline->GetWindowManager();
248     CHECK_NULL_VOID(windowManager);
249     if (!backupStyle_.has_value()) {
250         backupStyle_ = windowManager->GetSystemBarStyle();
251     }
252     currStyle_ = style;
253 
254     // The systemBarStyle may only take effect when navigation fills the entire page.
255     if (!isFullPageNavigation_) {
256         return;
257     }
258 
259     // When there is NavDestination in the stack, the systemBarStyle set for Navigation does not take effect.
260     do {
261         if (!navigationStack_) {
262             break;
263         }
264         auto topPath = navigationStack_->GetTopNavPath();
265         if (!topPath.has_value()) {
266             break;
267         }
268         auto topNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(
269             NavigationGroupNode::GetNavDestinationNode(topPath->second));
270         if (topNavDestination) {
271             return;
272         }
273     } while (false);
274 
275     /**
276      * When developers provide a valid style to systemBarStyle, we should set the style to window;
277      * when 'undefined' was provided, we should restore the style.
278      */
279     if (currStyle_.value() != nullptr) {
280         windowManager->SetSystemBarStyle(currStyle_.value());
281     } else {
282         TryRestoreSystemBarStyle(windowManager);
283     }
284 }
285 
OnAttachToMainTree()286 void NavigationPattern::OnAttachToMainTree()
287 {
288     auto host = GetHost();
289     CHECK_NULL_VOID(host);
290     InitPageNode(host);
291     InitFoldState();
292 }
293 
InitFoldState()294 void NavigationPattern::InitFoldState()
295 {
296     auto container = Container::Current();
297     CHECK_NULL_VOID(container);
298     container->InitIsFoldable();
299     if (container->IsFoldable()) {
300         currentFoldStatus_ = container->GetCurrentFoldStatus();
301     }
302 }
303 
OnDetachFromMainTree()304 void NavigationPattern::OnDetachFromMainTree()
305 {
306     isFullPageNavigation_ = false;
307     auto host = GetHost();
308     CHECK_NULL_VOID(host);
309     auto pipeline = host->GetContext();
310     CHECK_NULL_VOID(pipeline);
311     auto windowManager = pipeline->GetWindowManager();
312     CHECK_NULL_VOID(windowManager);
313     TryRestoreSystemBarStyle(windowManager);
314     backupStyle_.reset();
315     currStyle_.reset();
316     pageNode_ = nullptr;
317 }
318 
IsTopNavDestination(const RefPtr<UINode> & node) const319 bool NavigationPattern::IsTopNavDestination(const RefPtr<UINode>& node) const
320 {
321     if (!navigationStack_) {
322         return false;
323     }
324     auto topPath = navigationStack_->GetTopNavPath();
325     if (!topPath.has_value()) {
326         return false;
327     }
328     auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(
329         NavigationGroupNode::GetNavDestinationNode(topPath->second));
330     return navDestination == node;
331 }
332 
JudgeFoldStateChangeAndUpdateState()333 bool NavigationPattern::JudgeFoldStateChangeAndUpdateState()
334 {
335     auto container = Container::Current();
336     CHECK_NULL_RETURN(container, false);
337     auto foldStatus = container->GetCurrentFoldStatus();
338     TAG_LOGI(AceLogTag::ACE_NAVIGATION, "newFoldStatus: %{public}d, currentFoldStatus: %{public}d.",
339         static_cast<int32_t>(foldStatus), static_cast<int32_t>(currentFoldStatus_));
340     if (foldStatus != currentFoldStatus_) {
341         currentFoldStatus_ = foldStatus;
342         return true;
343     }
344     return false;
345 }
346 
UpdateIsFullPageNavigation(const RefPtr<FrameNode> & host)347 void NavigationPattern::UpdateIsFullPageNavigation(const RefPtr<FrameNode>& host)
348 {
349     CHECK_NULL_VOID(host);
350     auto geometryNode = host->GetGeometryNode();
351     CHECK_NULL_VOID(geometryNode);
352     auto frame = geometryNode->GetFrameRect();
353     auto pipeline = host->GetContext();
354     CHECK_NULL_VOID(pipeline);
355     auto windowManager = pipeline->GetWindowManager();
356     CHECK_NULL_VOID(windowManager);
357 
358     bool isFullPage = false;
359     auto pageNode = pageNode_.Upgrade();
360     if (pageNode) {
361         auto pageNodeGeometryNode = pageNode->GetGeometryNode();
362         if (pageNodeGeometryNode) {
363             auto pageFrame = pageNodeGeometryNode->GetFrameRect();
364             isFullPage = pageFrame.GetSize() == frame.GetSize();
365         }
366     }
367     pageNode = nullptr;
368 
369     if (isFullPage == isFullPageNavigation_) {
370         return;
371     }
372 
373     isFullPageNavigation_ = isFullPage;
374     UpdateSystemBarStyleOnFullPageStateChange(windowManager);
375     if (isFullPageNavigation_) {
376         RegisterPageVisibilityChangeCallback();
377     }
378 }
379 
UpdateSystemBarStyleOnFullPageStateChange(const RefPtr<WindowManager> & windowManager)380 void NavigationPattern::UpdateSystemBarStyleOnFullPageStateChange(const RefPtr<WindowManager>& windowManager)
381 {
382     // full page -> partial page
383     if (!isFullPageNavigation_) {
384         TryRestoreSystemBarStyle(windowManager);
385         return;
386     }
387 
388     // partial page -> full page
389     auto topPath = navigationStack_->GetTopNavPath();
390     UpdateSystemBarStyleWithTopNavPath(windowManager, topPath);
391 }
392 
UpdateSystemBarStyleOnTopNavPathChange(const std::optional<std::pair<std::string,RefPtr<UINode>>> & newTopNavPath)393 void NavigationPattern::UpdateSystemBarStyleOnTopNavPathChange(
394     const std::optional<std::pair<std::string, RefPtr<UINode>>>& newTopNavPath)
395 {
396     if (!isFullPageNavigation_) {
397         return;
398     }
399 
400     auto host = GetHost();
401     CHECK_NULL_VOID(host);
402     auto pipeline = host->GetContext();
403     CHECK_NULL_VOID(pipeline);
404     auto windowManager = pipeline->GetWindowManager();
405     CHECK_NULL_VOID(windowManager);
406     UpdateSystemBarStyleWithTopNavPath(windowManager, newTopNavPath);
407 }
408 
UpdateSystemBarStyleWithTopNavPath(const RefPtr<WindowManager> & windowManager,const std::optional<std::pair<std::string,RefPtr<UINode>>> & topNavPath)409 void NavigationPattern::UpdateSystemBarStyleWithTopNavPath(const RefPtr<WindowManager>& windowManager,
410     const std::optional<std::pair<std::string, RefPtr<UINode>>>& topNavPath)
411 {
412     if (ApplyTopNavPathSystemBarStyleOrRestore(windowManager, topNavPath)) {
413         return;
414     }
415 
416     if (currStyle_.has_value() && currStyle_.value() != nullptr) {
417         windowManager->SetSystemBarStyle(currStyle_.value());
418     } else {
419         TryRestoreSystemBarStyle(windowManager);
420     }
421 }
422 
TryRestoreSystemBarStyle(const RefPtr<WindowManager> & windowManager)423 void NavigationPattern::TryRestoreSystemBarStyle(const RefPtr<WindowManager>& windowManager)
424 {
425     if (backupStyle_.has_value()) {
426         windowManager->SetSystemBarStyle(backupStyle_.value());
427     }
428 }
429 
UpdateSystemBarStyleOnPageVisibilityChange(bool show)430 void NavigationPattern::UpdateSystemBarStyleOnPageVisibilityChange(bool show)
431 {
432     if (!isFullPageNavigation_) {
433         return;
434     }
435 
436     CHECK_NULL_VOID(navigationStack_);
437     auto host = GetHost();
438     CHECK_NULL_VOID(host);
439     auto pipeline = host->GetContext();
440     CHECK_NULL_VOID(pipeline);
441     auto windowManager = pipeline->GetWindowManager();
442     CHECK_NULL_VOID(windowManager);
443     if (show) {
444         // page containing Navigation, hide -> show
445         auto topPath = navigationStack_->GetTopNavPath();
446         UpdateSystemBarStyleWithTopNavPath(windowManager, topPath);
447     } else {
448         // page containing Navigation, show -> hide
449         TryRestoreSystemBarStyle(windowManager);
450     }
451 }
452 
RegisterPageVisibilityChangeCallback()453 void NavigationPattern::RegisterPageVisibilityChangeCallback()
454 {
455     auto pageNode = pageNode_.Upgrade();
456     CHECK_NULL_VOID(pageNode);
457     RefPtr<PagePattern> pagePattern = pageNode->GetPattern<PagePattern>();
458     CHECK_NULL_VOID(pagePattern);
459     auto callback = [weak = WeakClaim(this)](bool show) {
460         auto pattern = weak.Upgrade();
461         CHECK_NULL_VOID(pattern);
462         // we need update the "systemBarStyle" at the beginning of the transition animation on the router page
463         pattern->UpdateSystemBarStyleOnPageVisibilityChange(show);
464     };
465     pagePattern->SetPageVisibilityChangeCallback(std::move(callback));
466 }
467 
ApplyTopNavPathSystemBarStyleOrRestore(const RefPtr<WindowManager> & windowManager,const std::optional<std::pair<std::string,RefPtr<UINode>>> & topNavPath)468 bool NavigationPattern::ApplyTopNavPathSystemBarStyleOrRestore(
469     const RefPtr<WindowManager>& windowManager,
470     const std::optional<std::pair<std::string, RefPtr<UINode>>>& topNavPath)
471 {
472     if (!topNavPath.has_value()) {
473         return false;
474     }
475 
476     auto topNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(
477         NavigationGroupNode::GetNavDestinationNode(topNavPath->second));
478     if (!topNavDestination) {
479         return false;
480     }
481 
482     auto navDestinationPattern = topNavDestination->GetPattern<NavDestinationPattern>();
483     if (!navDestinationPattern) {
484         return false;
485     }
486     /**
487      * Backup is only performed when the developer sets the "systemBarStyle" attribute,
488      * and the entire Navigation is only backed up once.
489      * Therefore, when developer only set the "systemBarStyle" attribute to NavDestination, we need to
490      * save the attribute to Navigation.
491      */
492     auto backupFromNavDestination = navDestinationPattern->GetBackupStyle();
493     if (!backupStyle_.has_value() && backupFromNavDestination.has_value()) {
494         backupStyle_ = backupFromNavDestination;
495     }
496 
497     auto destCurrStyle = navDestinationPattern->GetCurrentStyle();
498     if (destCurrStyle.has_value() && destCurrStyle.value() != nullptr) {
499         windowManager->SetSystemBarStyle(destCurrStyle.value());
500     } else {
501         TryRestoreSystemBarStyle(windowManager);
502     }
503     return true;
504 }
505 
InitPageNode(const RefPtr<FrameNode> & host)506 void NavigationPattern::InitPageNode(const RefPtr<FrameNode>& host)
507 {
508     CHECK_NULL_VOID(host);
509     auto parent = host->GetParent();
510     CHECK_NULL_VOID(parent);
511     RefPtr<FrameNode> pageNode = nullptr;
512     while (parent) {
513         if (parent->GetTag() == V2::PAGE_ETS_TAG) {
514             pageNode = AceType::DynamicCast<FrameNode>(parent);
515             break;
516         }
517         parent = parent->GetParent();
518     }
519     if (!pageNode) {
520         TAG_LOGE(AceLogTag::ACE_NAVIGATION, "Failed to find PageNode of Navigation");
521     } else {
522         pageNode_ = WeakPtr<FrameNode>(pageNode);
523     }
524 }
525 
OnLanguageConfigurationUpdate()526 void NavigationPattern::OnLanguageConfigurationUpdate()
527 {
528     bool isRightToLeft = AceApplicationInfo::GetInstance().IsRightToLeft();
529     if (isRightToLeft != isRightToLeft_) {
530         auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
531         CHECK_NULL_VOID(hostNode);
532         hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
533         isRightToLeft_ = isRightToLeft;
534     }
535 }
536 
SyncWithJsStackIfNeeded()537 void NavigationPattern::SyncWithJsStackIfNeeded()
538 {
539     if (!needSyncWithJsStack_) {
540         TAG_LOGI(AceLogTag::ACE_NAVIGATION,
541             "not need SyncWithJsStack, needSyncWithJsStack_ %{public}d", needSyncWithJsStack_);
542         return;
543     }
544     CHECK_NULL_VOID(navigationStack_);
545     needSyncWithJsStack_ = false;
546     if (!isFinishInteractiveAnimation_) {
547         TAG_LOGI(AceLogTag::ACE_NAVIGATION,
548             "not need SyncWithJsStack, interactive animation: %{public}d", isFinishInteractiveAnimation_);
549         return;
550     }
551     TAG_LOGI(AceLogTag::ACE_NAVIGATION, "sync with js stack");
552     preTopNavPath_ = navigationStack_->GetPreTopNavPath();
553     preStackSize_ = navigationStack_->PreSize();
554 
555     preContext_ = nullptr;
556     if (preTopNavPath_.has_value()) {
557         auto preDestination = AceType::DynamicCast<NavDestinationGroupNode>(
558             NavigationGroupNode::GetNavDestinationNode(preTopNavPath_->second));
559         if (preDestination) {
560             auto pattern = AceType::DynamicCast<NavDestinationPattern>(preDestination->GetPattern());
561             preContext_ = pattern->GetNavDestinationContext();
562             if (preContext_) {
563                 preContext_->SetPreIndex(preStackSize_ - 1);
564             }
565         }
566     }
567     if (isCustomAnimation_) {
568         navigationStack_->UpdateRecoveryList();
569     }
570     UpdateNavPathList();
571     auto newTopNavPath = navigationStack_->GetTopNavPath();
572     auto replaceValue = navigationStack_->GetReplaceValue();
573     if (preTopNavPath_ != newTopNavPath || replaceValue == 1) {
574         isReplace_ = replaceValue != 0;
575         UpdateIsAnimation(preTopNavPath_);
576         lastPreIndex_ = 0;
577         if (preTopNavPath_.has_value()) {
578             lastPreIndex_ = navigationStack_->FindIndex(preTopNavPath_->first,
579             preTopNavPath_->second, true);
580         }
581         FireInterceptionEvent(true, newTopNavPath);
582         if (needSyncWithJsStack_) {
583             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "sync with js stack in before interception");
584             UpdateNavPathList();
585             needSyncWithJsStack_ = false;
586         }
587     }
588     RefreshNavDestination();
589 }
590 
UpdateNavPathList()591 void NavigationPattern::UpdateNavPathList()
592 {
593     CHECK_NULL_VOID(navigationStack_);
594     auto pathNames = navigationStack_->GetAllPathName();
595     auto indexes = navigationStack_->GetAllPathIndex();
596     auto cacheNodes = navigationStack_->GetAllCacheNodes();
597     NavPathList navPathList;
598     int32_t pathListSize = static_cast<int32_t>(pathNames.size());
599     isCurTopNewInstance_ = false;
600     for (int32_t index = 0; index < pathListSize; ++index) {
601         auto pathName = pathNames[index];
602         auto pathIndex = indexes[index];
603         RefPtr<UINode> uiNode = nullptr;
604         if (navigationStack_->NeedBuildNewInstance(index)) {
605             // if marked NEW_INSTANCE when push/replace in frontend, build a new instance anyway
606             uiNode = GenerateUINodeByIndex(index);
607             navPathList.emplace_back(std::make_pair(pathName, uiNode));
608             navigationStack_->SetNeedBuildNewInstance(index, false);
609             if (index == pathListSize - 1) {
610                 isCurTopNewInstance_ = true;
611             }
612             continue;
613         }
614         if (index == pathListSize - 1 && addByNavRouter_) {
615             addByNavRouter_ = false;
616             uiNode = navigationStack_->Get();
617         } else {
618             uiNode = navigationStack_->Get(pathIndex);
619         }
620         if (uiNode) {
621             TAG_LOGD(AceLogTag::ACE_NAVIGATION, "find in list, navigation stack reserve node, "
622                 "old index: %{public}d, index: %{public}d, name: %{public}s.",
623                 pathIndex, index, pathName.c_str());
624             /**
625              * If we call the function pushPath/pushDestination with singleton mode(
626              * LaunchMode == MOVE_TO_TOP_SINGLETON/POP_TO_SINGLETON), and the top NavDestination of stack
627              * is the NavDestination which we need to push(NavDestination's name == NavPathInfo's name),
628              * then wee need to update the NavDestination's parameters.
629              */
630             navigationStack_->UpdatePathInfoIfNeeded(uiNode, index);
631             auto navDestinationGroupNode = AceType::DynamicCast<NavDestinationGroupNode>(
632                 NavigationGroupNode::GetNavDestinationNode(uiNode));
633             if (navDestinationGroupNode && navDestinationGroupNode->GetCanReused()) {
634                 navPathList.emplace_back(std::make_pair(pathName, uiNode));
635                 continue;
636             }
637         }
638         uiNode = navigationStack_->GetFromCacheNode(cacheNodes, pathName);
639         if (uiNode) {
640             TAG_LOGD(AceLogTag::ACE_NAVIGATION, "find in cached node, navigation stack reserve node, "
641                 "index: %{public}d, name: %{public}s.", index, pathName.c_str());
642             navPathList.emplace_back(std::make_pair(pathName, uiNode));
643             navigationStack_->RemoveCacheNode(cacheNodes, pathName, uiNode);
644             continue;
645         }
646         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "find in nowhere, navigation stack create new node, "
647             "index: %{public}d, name: %{public}s.", index, pathName.c_str());
648         uiNode = GenerateUINodeByIndex(index);
649         navPathList.emplace_back(std::make_pair(pathName, uiNode));
650     }
651     navigationStack_->ClearPreBuildNodeList();
652     navigationStack_->SetNavPathList(navPathList);
653     navigationStack_->InitNavPathIndex(pathNames);
654 }
655 
RefreshNavDestination()656 void NavigationPattern::RefreshNavDestination()
657 {
658     isChanged_ = false;
659     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
660     CHECK_NULL_VOID(hostNode);
661     auto pipeline = PipelineContext::GetCurrentContext();
662     CHECK_NULL_VOID(pipeline);
663     auto preTopNavPath = std::move(preTopNavPath_);
664     auto preLastStandardIndex = hostNode->GetLastStandardIndex();
665     auto& navPathList = navigationStack_->GetAllNavDestinationNodes();
666     hostNode->UpdateNavDestinationNodeWithoutMarkDirty(
667         preTopNavPath.has_value() ? preTopNavPath->second : nullptr, navigationModeChange_);
668     auto newTopNavPath = navigationStack_->GetTopNavPath();
669     std::string navDestinationName = "";
670     CheckTopNavPathChange(preTopNavPath, newTopNavPath, preLastStandardIndex);
671 
672     // close keyboard
673 #if defined(ENABLE_STANDARD_INPUT)
674     RefPtr<FrameNode> targetNode = newTopNavPath.has_value() ? AceType::DynamicCast<FrameNode>(
675             NavigationGroupNode::GetNavDestinationNode(newTopNavPath->second)) :
676             AceType::DynamicCast<FrameNode>(hostNode->GetNavBarNode());
677     if (isChanged_ && GetIsFocusable(targetNode)) {
678         InputMethodManager::GetInstance()->CloseKeyboard();
679     }
680 #endif
681 
682     /* if first navDestination is removed, the new one will be refreshed */
683     if (!navPathList.empty()) {
684         auto firstNavDesNode = AceType::DynamicCast<NavDestinationGroupNode>(
685             NavigationGroupNode::GetNavDestinationNode(navPathList.front().second));
686         CHECK_NULL_VOID(firstNavDesNode);
687         firstNavDesNode->MarkModifyDone();
688     }
689 
690     if (newTopNavPath.has_value()) {
691         navDestinationName = newTopNavPath->first;
692     }
693     pipeline->AddPredictTask([weak = WeakClaim(this), weakNode = WeakPtr<FrameNode>(hostNode),
694         navDestinationName](int64_t deadline, bool canUseLongPredictTask) {
695             auto navigationPattern = weak.Upgrade();
696             CHECK_NULL_VOID(navigationPattern);
697             auto navigationNode = weakNode.Upgrade();
698             CHECK_NULL_VOID(navigationNode);
699             int32_t count = 0;
700             int32_t depth = 0;
701             navigationNode->GetPageNodeCountAndDepth(&count, &depth);
702             navigationPattern->PerformanceEventReport(count, depth, navDestinationName);
703         });
704 }
705 
CheckTopNavPathChange(const std::optional<std::pair<std::string,RefPtr<UINode>>> & preTopNavPath,const std::optional<std::pair<std::string,RefPtr<UINode>>> & newTopNavPath,int32_t preLastStandardIndex)706 void NavigationPattern::CheckTopNavPathChange(
707     const std::optional<std::pair<std::string, RefPtr<UINode>>>& preTopNavPath,
708     const std::optional<std::pair<std::string, RefPtr<UINode>>>& newTopNavPath,
709     int32_t preLastStandardIndex)
710 {
711     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
712     CHECK_NULL_VOID(hostNode);
713     if (preTopNavPath != newTopNavPath) {
714         UpdateSystemBarStyleOnTopNavPathChange(newTopNavPath);
715     }
716     auto replaceValue = navigationStack_->GetReplaceValue();
717     if (preTopNavPath == newTopNavPath && replaceValue != 1) {
718         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "page is not change. don't transition");
719         auto currentProxy = GetTopNavigationProxy();
720         if (currentProxy) {
721             currentProxy->SetIsSuccess(false);
722         }
723         hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_WILL_HIDE);
724         NotifyDialogChange(NavDestinationLifecycle::ON_WILL_SHOW, true, true);
725         auto pipeline = PipelineContext::GetCurrentContext();
726         CHECK_NULL_VOID(pipeline);
727         pipeline->AddAfterLayoutTask([weakPattern = WeakClaim(this)]() {
728             auto pattern = weakPattern.Upgrade();
729             CHECK_NULL_VOID(pattern);
730             auto hostNode = AceType::DynamicCast<NavigationGroupNode>(pattern->GetHost());
731             CHECK_NULL_VOID(hostNode);
732             hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_HIDE);
733             hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_WILL_DISAPPEAR);
734             pattern->NotifyDialogChange(NavDestinationLifecycle::ON_SHOW, true, true);
735             hostNode->RemoveDialogDestination();
736         });
737         navigationStack_->ClearRecoveryList();
738         return;
739     }
740 
741     isChanged_ = true;
742     UpdateIsAnimation(preTopNavPath);
743     isReplace_ = replaceValue != 0;
744     if (replaceValue == 1) {
745         const int32_t replaceAnimation = 2;
746         navigationStack_->UpdateReplaceValue(replaceAnimation);
747     }
748     auto contentNode = hostNode->GetContentNode();
749     CHECK_NULL_VOID(contentNode);
750     auto context = PipelineContext::GetCurrentContext();
751     CHECK_NULL_VOID(context);
752     // close the text selection menu before transition.
753     auto selectOverlayManager = context->GetSelectOverlayManager();
754     if (selectOverlayManager) {
755         selectOverlayManager->ResetSelectionAndDestroySelectOverlay();
756     }
757     // fire onHidden and lostFocus event
758     RefPtr<NavDestinationGroupNode> preTopNavDestination;
759     int32_t lastPreIndex = -1;
760     bool isPopPage = false;
761     if (preTopNavPath.has_value()) {
762         // pre page is not in the current stack
763         lastPreIndex = navigationStack_->FindIndex(preTopNavPath->first, preTopNavPath->second, true);
764         isPopPage |= lastPreIndex == -1;
765         preTopNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(
766             NavigationGroupNode::GetNavDestinationNode(preTopNavPath->second));
767     }
768     if (isCurTopNewInstance_) {
769         isPopPage = false;
770     }
771     RefPtr<NavDestinationGroupNode> newTopNavDestination;
772     if (newTopNavPath.has_value()) {
773         newTopNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(
774             NavigationGroupNode::GetNavDestinationNode(newTopNavPath->second));
775         do {
776             if (!newTopNavDestination) {
777                 break;
778             }
779             if (!GetIsFocusable(newTopNavDestination)) {
780                 break;
781             }
782             auto navDestinationPattern = newTopNavDestination->GetPattern<NavDestinationPattern>();
783             auto navDestinationFocusView = AceType::DynamicCast<FocusView>(navDestinationPattern);
784             CHECK_NULL_VOID(navDestinationFocusView);
785             if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TWELVE)) {
786                 navDestinationFocusView->SetIsViewRootScopeFocused(false);
787             }
788             navDestinationFocusView->FocusViewShow();
789         } while (0);
790     } else {
791         // back to navBar case
792         auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
793         CHECK_NULL_VOID(navBarNode);
794         auto navigationLayoutProperty = AceType::DynamicCast<NavigationLayoutProperty>(hostNode->GetLayoutProperty());
795         if (!navigationLayoutProperty->GetHideNavBarValue(false)) {
796             navBarNode->GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE);
797             navBarNode->SetJSViewActive(true);
798         }
799         auto stageManager = context->GetStageManager();
800         if (stageManager != nullptr) {
801             RefPtr<FrameNode> pageNode = stageManager->GetLastPage();
802             CHECK_NULL_VOID(pageNode);
803             auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
804             CHECK_NULL_VOID(pagePattern);
805             auto pageInfo = pagePattern->GetPageInfo();
806             NotifyPageShow(pageInfo->GetPageUrl());
807         }
808         navBarNode->GetEventHub<EventHub>()->SetEnabledInternal(true);
809         if (GetIsFocusable(navBarNode)) {
810             auto navBarFocusView = navBarNode->GetPattern<FocusView>();
811             CHECK_NULL_VOID(navBarFocusView);
812             if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TWELVE)) {
813                 navBarFocusView->SetIsViewRootScopeFocused(false);
814             }
815             navBarFocusView->FocusViewShow();
816         }
817     }
818     bool isShow = false;
819     bool isDialog =
820         (preTopNavDestination && preTopNavDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG) ||
821         (newTopNavDestination && newTopNavDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG);
822     if (preTopNavDestination && isDialog) {
823         auto lastStandardIndex = hostNode->GetLastStandardIndex();
824         isShow = (lastPreIndex != -1) && (lastPreIndex >= lastStandardIndex);
825         hostNode->SetNeedSetInvisible(lastStandardIndex >= 0);
826         if (lastStandardIndex < 0) {
827             auto navBarNode = AceType::DynamicCast<FrameNode>(hostNode->GetNavBarNode());
828             auto layoutProperty = navBarNode->GetLayoutProperty();
829             layoutProperty->UpdateVisibility(VisibleType::VISIBLE, true);
830             navBarNode->SetJSViewActive(true);
831         }
832     }
833     bool disableAllAnimation = navigationStack_->GetDisableAnimation();
834     bool animated = navigationStack_->GetAnimatedValue();
835     TAG_LOGI(AceLogTag::ACE_NAVIGATION,
836         "transition start, disableAllAnimation: %{public}d, animated: %{public}d, isPopPage: %{public}d, isDialog: "
837         "%{public}d",
838         disableAllAnimation, animated, isPopPage, isDialog);
839     if (disableAllAnimation || !animated) {
840         // transition without animation need to run before layout for geometryTransition.
841         StartTransition(preTopNavDestination, newTopNavDestination, false, isPopPage, isShow);
842         navigationStack_->UpdateAnimatedValue(true);
843         hostNode->GetLayoutProperty()->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
844         return;
845     }
846     if (isDialog && !isCustomAnimation_) {
847         bool isNeedAnimation =
848             AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_THIRTEEN) ?
849             true : false;
850         StartTransition(preTopNavDestination, newTopNavDestination, isNeedAnimation, isPopPage, isShow);
851         hostNode->GetLayoutProperty()->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
852         return;
853     }
854 
855     // before the animation of navDes replacing, update the zIndex of the previous navDes node
856     UpdatePreNavDesZIndex(preTopNavDestination, newTopNavDestination, preLastStandardIndex);
857     // transition with animation need to run after layout task
858     StartTransition(preTopNavDestination, newTopNavDestination, true, isPopPage, isShow);
859     hostNode->GetLayoutProperty()->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
860 }
861 
FireNavDestinationStateChange(NavDestinationLifecycle lifecycle)862 int32_t NavigationPattern::FireNavDestinationStateChange(NavDestinationLifecycle lifecycle)
863 {
864     const auto& navDestinationNodes = navigationStack_->GetAllNavDestinationNodes();
865     auto errIndex = static_cast<int32_t>(navDestinationNodes.size());
866     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
867     CHECK_NULL_RETURN(hostNode, errIndex);
868     NotifyDialogChange(lifecycle, false, true);
869     return hostNode->GetLastStandardIndex();
870 }
871 
CheckParentDestinationIsOnhide(const RefPtr<NavDestinationGroupNode> & destinationNode)872 bool NavigationPattern::CheckParentDestinationIsOnhide(const RefPtr<NavDestinationGroupNode>& destinationNode)
873 {
874     CHECK_NULL_RETURN(destinationNode, false);
875     auto destinationNodePattern = destinationNode->GetPattern<NavDestinationPattern>();
876     CHECK_NULL_RETURN(destinationNodePattern, false);
877     return !destinationNodePattern->GetIsOnShow();
878 }
879 
CheckDestinationIsPush(const RefPtr<NavDestinationGroupNode> & destinationNode)880 bool NavigationPattern::CheckDestinationIsPush(const RefPtr<NavDestinationGroupNode>& destinationNode)
881 {
882     CHECK_NULL_RETURN(destinationNode, false);
883     return destinationNode->GetIndex() != -1 || destinationNode->GetNavDestinationCustomNode();
884 }
885 
FireNavigationInner(const RefPtr<UINode> & node,bool isOnShow)886 void NavigationPattern::FireNavigationInner(const RefPtr<UINode>& node, bool isOnShow)
887 {
888     CHECK_NULL_VOID(node);
889     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(node);
890     if (!navigationNode) {
891         NavigationPattern::FireNavigationChange(node, isOnShow, false);
892         return;
893     }
894     auto navigationPattern = navigationNode->GetPattern<NavigationPattern>();
895     CHECK_NULL_VOID(navigationPattern);
896     CHECK_NULL_VOID(navigationPattern->navigationStack_);
897     const auto& navDestinationNodes = navigationPattern->navigationStack_->GetAllNavDestinationNodes();
898     auto lastStandardIndex = navigationNode->GetLastStandardIndex();
899     int32_t standardIndex = lastStandardIndex >= 0 ? lastStandardIndex : 0;
900     int32_t start = standardIndex;
901     int32_t end = navigationPattern->navigationStack_->Size();
902     auto pipeline = PipelineContext::GetCurrentContext();
903     CHECK_NULL_VOID(pipeline);
904     auto overlayManager = pipeline->GetOverlayManager();
905     if (isOnShow) {
906         if (overlayManager && overlayManager->HasModalPage()) {
907             return;
908         }
909         for (int32_t index = start; index < end; index++) {
910             const auto& curPath = navDestinationNodes[index];
911             auto curDestination = AceType::DynamicCast<NavDestinationGroupNode>(
912                 navigationNode->GetNavDestinationNode(curPath.second));
913             if (!curDestination || !curDestination->GetLayoutProperty()) {
914                 continue;
915             }
916             auto navDestinationPattern = curDestination->GetPattern<NavDestinationPattern>();
917             CHECK_NULL_VOID(navDestinationPattern);
918             auto property = curDestination->GetLayoutProperty();
919             if (property->GetVisibilityValue(VisibleType::VISIBLE) != VisibleType::VISIBLE ||
920                 !curDestination->IsActive() || navDestinationPattern->GetIsOnShow() == isOnShow) {
921                 continue;
922             }
923             auto eventHub = curDestination->GetEventHub<NavDestinationEventHub>();
924             CHECK_NULL_VOID(eventHub);
925             auto param = Recorder::EventRecorder::Get().IsPageParamRecordEnable() ?
926                 navigationPattern->navigationStack_->GetRouteParam() : "";
927             eventHub->FireOnShownEvent(navDestinationPattern->GetName(), param);
928             navDestinationPattern->SetIsOnShow(true);
929             NavigationPattern::FireNavigationChange(curDestination, true, false);
930             NavigationPattern::NotifyPerfMonitorPageMsg(navDestinationPattern->GetName());
931         }
932         return;
933     }
934     for (int32_t index = end - 1; index >= 0 && index >= start; index--) {
935         const auto& curPath = navDestinationNodes[index];
936         auto curDestination = AceType::DynamicCast<NavDestinationGroupNode>(
937             navigationNode->GetNavDestinationNode(curPath.second));
938         if (!curDestination || !curDestination->GetLayoutProperty()) {
939             continue;
940         }
941         auto navDestinationPattern = curDestination->GetPattern<NavDestinationPattern>();
942         CHECK_NULL_VOID(navDestinationPattern);
943         auto property = curDestination->GetLayoutProperty();
944         if (property->GetVisibilityValue(VisibleType::VISIBLE) != VisibleType::VISIBLE ||
945             !curDestination->IsActive() || navDestinationPattern->GetIsOnShow() == isOnShow) {
946             continue;
947         }
948         auto eventHub = curDestination->GetEventHub<NavDestinationEventHub>();
949         CHECK_NULL_VOID(eventHub);
950         eventHub->FireOnHiddenEvent(navDestinationPattern->GetName());
951         navDestinationPattern->SetIsOnShow(false);
952         NavigationPattern::FireNavigationChange(curDestination, false, false);
953     }
954 }
955 
FireNavigationChange(const RefPtr<UINode> & node,bool isOnShow,bool isFirst)956 void NavigationPattern::FireNavigationChange(const RefPtr<UINode>& node, bool isOnShow, bool isFirst)
957 {
958     CHECK_NULL_VOID(node);
959     if (isFirst) {
960         FireNavigationInner(node, isOnShow);
961         return;
962     }
963     const auto& children = node->GetChildren();
964     for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
965         auto& child = *iter;
966         FireNavigationInner(child, isOnShow);
967     }
968 }
969 
FireNavigationStateChange(const RefPtr<UINode> & node,bool isShow)970 void NavigationPattern::FireNavigationStateChange(const RefPtr<UINode>& node, bool isShow)
971 {
972     if (isShow) {
973         NavigationPattern::FireNavigationLifecycleChange(node, NavDestinationLifecycle::ON_SHOW);
974         return;
975     }
976     NavigationPattern::FireNavigationLifecycleChange(node, NavDestinationLifecycle::ON_HIDE);
977 }
978 
FireNavigationLifecycleChange(const RefPtr<UINode> & node,NavDestinationLifecycle lifecycle)979 void NavigationPattern::FireNavigationLifecycleChange(const RefPtr<UINode>& node, NavDestinationLifecycle lifecycle)
980 {
981     CHECK_NULL_VOID(node);
982     const auto& children = node->GetChildren();
983     for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
984         auto& child = *iter;
985         auto navigation = AceType::DynamicCast<NavigationGroupNode>(child);
986         if (navigation) {
987             auto destinationNode = navigation->GetParentDestinationNode().Upgrade();
988             if ((lifecycle == NavDestinationLifecycle::ON_SHOW) && CheckParentDestinationIsOnhide(destinationNode) &&
989                 CheckDestinationIsPush(destinationNode)) {
990                 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation parent is onhide");
991                 continue;
992             }
993             auto navigationPattern = AceType::DynamicCast<NavigationPattern>(navigation->GetPattern());
994             CHECK_NULL_VOID(navigationPattern);
995             navigationPattern->FireNavDestinationStateChange(lifecycle);
996         } else {
997             NavigationPattern::FireNavigationLifecycleChange(child, lifecycle);
998         }
999     }
1000 }
1001 
NotifyPageHide(const std::string & pageName)1002 void NavigationPattern::NotifyPageHide(const std::string& pageName)
1003 {
1004     auto container = Container::Current();
1005     CHECK_NULL_VOID(container);
1006     auto pageUrlChecker = container->GetPageUrlChecker();
1007     CHECK_NULL_VOID(pageUrlChecker);
1008     pageUrlChecker->NotifyPageHide(pageName);
1009 }
1010 
NotifyPageShow(const std::string & pageName)1011 void NavigationPattern::NotifyPageShow(const std::string& pageName)
1012 {
1013     auto container = Container::Current();
1014     CHECK_NULL_VOID(container);
1015     auto pageUrlChecker = container->GetPageUrlChecker();
1016     CHECK_NULL_VOID(pageUrlChecker);
1017     pageUrlChecker->NotifyPageShow(pageName);
1018     if (PerfMonitor::GetPerfMonitor() != nullptr) {
1019         PerfMonitor::GetPerfMonitor()->SetPageName(pageName);
1020     }
1021 }
1022 
ReplaceAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination)1023 void NavigationPattern::ReplaceAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
1024     const RefPtr<NavDestinationGroupNode>& newTopNavDestination)
1025 {
1026     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1027     CHECK_NULL_VOID(navigationNode);
1028     auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationNode->GetNavBarNode());
1029     CHECK_NULL_VOID(navBarNode);
1030     if (newTopNavDestination && preTopNavDestination) {
1031         navigationNode->DealNavigationExit(preTopNavDestination, false, false);
1032     } else if (newTopNavDestination && navigationMode_ == NavigationMode::STACK) {
1033         navigationNode->DealNavigationExit(navBarNode, true, false);
1034     }
1035     navigationNode->RemoveDialogDestination();
1036     auto id = navigationNode->GetTopDestination() ? navigationNode->GetTopDestination()->GetAccessibilityId() : -1;
1037     navigationNode->OnAccessibilityEvent(
1038         AccessibilityEventType::PAGE_CHANGE, id, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID);
1039     navigationStack_->UpdateReplaceValue(0);
1040 }
1041 
TransitionWithOutAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage,bool needVisible)1042 void NavigationPattern::TransitionWithOutAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
1043     const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage, bool needVisible)
1044 {
1045     navigationStack_->ClearRecoveryList();
1046     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1047     CHECK_NULL_VOID(navigationNode);
1048     auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationNode->GetNavBarNode());
1049     CHECK_NULL_VOID(navBarNode);
1050     auto pipeline = PipelineContext::GetCurrentContext();
1051     CHECK_NULL_VOID(pipeline);
1052 
1053     // replace
1054     auto replaceVal = navigationStack_->GetReplaceValue();
1055     if (replaceVal != 0) {
1056         ReplaceAnimation(preTopNavDestination, newTopNavDestination);
1057         return;
1058     }
1059 
1060     // navDestination push/pop navDestination
1061     if (newTopNavDestination && preTopNavDestination) {
1062         if (isPopPage) {
1063             newTopNavDestination->SetTransitionType(PageTransitionType::ENTER_POP);
1064             preTopNavDestination->CleanContent();
1065             auto parent = preTopNavDestination->GetParent();
1066             CHECK_NULL_VOID(parent);
1067             parent->RemoveChild(preTopNavDestination, true);
1068             parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1069         } else {
1070             preTopNavDestination->GetRenderContext()->RemoveClipWithRRect();
1071             preTopNavDestination->SetTransitionType(PageTransitionType::EXIT_PUSH);
1072             newTopNavDestination->SetTransitionType(PageTransitionType::ENTER_PUSH);
1073             DealTransitionVisibility(preTopNavDestination, needVisible, false);
1074             if (preTopNavDestination->NeedRemoveInPush()) {
1075                 preTopNavDestination->CleanContent();
1076                 auto parent = preTopNavDestination->GetParent();
1077                 CHECK_NULL_VOID(parent);
1078                 parent->RemoveChild(preTopNavDestination, true);
1079                 parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1080             }
1081         }
1082         navigationNode->RemoveDialogDestination();
1083         auto id = navigationNode->GetTopDestination() ? navigationNode->GetTopDestination()->GetAccessibilityId() : -1;
1084         navigationNode->OnAccessibilityEvent(
1085             AccessibilityEventType::PAGE_CHANGE, id, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID);
1086         return;
1087     }
1088 
1089     // navBar push navDestination
1090     if (newTopNavDestination && newTopNavDestination->GetNavDestinationMode() == NavDestinationMode::STANDARD) {
1091         newTopNavDestination->SetTransitionType(PageTransitionType::ENTER_PUSH);
1092         auto navBar = AceType::DynamicCast<NavBarNode>(navBarNode);
1093         // current mode is stack, set navBar invisible
1094         if (navigationMode_ == NavigationMode::STACK && navBar) {
1095             navBar->SetTransitionType(PageTransitionType::EXIT_PUSH);
1096             DealTransitionVisibility(navBarNode, false, true);
1097         }
1098         // if current mode is auto, need set navBar need set invisible true
1099         navigationNode->SetNeedSetInvisible(true);
1100     }
1101 
1102     // navDestination pop to navBar
1103     if (preTopNavDestination) {
1104         auto parent = preTopNavDestination->GetParent();
1105         CHECK_NULL_VOID(parent);
1106         auto preTopNavDestinationPattern = preTopNavDestination->GetPattern<NavDestinationPattern>();
1107         auto shallowBuilder = preTopNavDestinationPattern->GetShallowBuilder();
1108         if (shallowBuilder) {
1109             shallowBuilder->MarkIsExecuteDeepRenderDone(false);
1110         }
1111         if (preTopNavDestination->GetContentNode()) {
1112             preTopNavDestination->GetContentNode()->Clean(false, true);
1113         }
1114         parent->RemoveChild(preTopNavDestination, true);
1115         navigationNode->SetNeedSetInvisible(false);
1116         auto navBar = AceType::DynamicCast<NavBarNode>(navBarNode);
1117         if (navBar) {
1118             navBar->SetTransitionType(PageTransitionType::ENTER_POP);
1119         }
1120         parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1121     }
1122     navigationNode->RemoveDialogDestination();
1123     auto id = navigationNode->GetTopDestination() ? navigationNode->GetTopDestination()->GetAccessibilityId() : -1;
1124     navigationNode->OnAccessibilityEvent(
1125         AccessibilityEventType::PAGE_CHANGE, id, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID);
1126 }
1127 
TransitionWithAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage,bool isNeedVisible)1128 void NavigationPattern::TransitionWithAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
1129     const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage, bool isNeedVisible)
1130 {
1131     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1132     CHECK_NULL_VOID(navigationNode);
1133     auto pipeline = PipelineContext::GetCurrentContext();
1134     CHECK_NULL_VOID(pipeline);
1135     auto layoutProperty = navigationNode->GetLayoutProperty<NavigationLayoutProperty>();
1136     CHECK_NULL_VOID(layoutProperty);
1137     if (layoutProperty->GetHideNavBarValue(false) && (!newTopNavDestination || !preTopNavDestination)) {
1138         // hide navBarNode and need to do animation with navBarNode
1139         if (preTopNavDestination) {
1140             // remove preTopNavDestination node in pop
1141             auto parent = preTopNavDestination->GetParent();
1142             CHECK_NULL_VOID(parent);
1143             if (preTopNavDestination->GetContentNode()) {
1144                 preTopNavDestination->GetContentNode()->Clean();
1145             }
1146             parent->RemoveChild(preTopNavDestination);
1147             auto preTopNavDestinationPattern = preTopNavDestination->GetPattern<NavDestinationPattern>();
1148             CHECK_NULL_VOID(preTopNavDestinationPattern);
1149             parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1150         }
1151         navigationNode->RemoveDialogDestination();
1152         navigationStack_->ClearRecoveryList();
1153         return;
1154     }
1155     if (isCustomAnimation_ && TriggerCustomAnimation(preTopNavDestination, newTopNavDestination, isPopPage)) {
1156         return;
1157     }
1158     StartDefaultAnimation(preTopNavDestination, newTopNavDestination, isPopPage, isNeedVisible);
1159 }
1160 
DialogAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage,bool isNeedVisible)1161 void NavigationPattern::DialogAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
1162     const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage, bool isNeedVisible)
1163 {
1164     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_THIRTEEN)) {
1165         TransitionWithDialogAnimation(preTopNavDestination, newTopNavDestination, isPopPage);
1166     } else {
1167         TransitionWithOutAnimation(preTopNavDestination, newTopNavDestination, isPopPage, isNeedVisible);
1168     }
1169 }
1170 
StartDefaultAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage,bool isNeedVisible)1171 void NavigationPattern::StartDefaultAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
1172     const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage, bool isNeedVisible)
1173 {
1174     auto currentProxy = GetTopNavigationProxy();
1175     if (currentProxy) {
1176         currentProxy->SetIsFinished(true);
1177     }
1178     navigationStack_->ClearRecoveryList();
1179     bool isPreDialog = preTopNavDestination &&
1180         preTopNavDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG;
1181     bool isNewDialog = newTopNavDestination &&
1182         newTopNavDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG;
1183     if (isPreDialog || isNewDialog) {
1184         DialogAnimation(preTopNavDestination, newTopNavDestination, isPopPage, isNeedVisible);
1185         return;
1186     }
1187     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1188     CHECK_NULL_VOID(navigationNode);
1189     auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationNode->GetNavBarNode());
1190     CHECK_NULL_VOID(navBarNode);
1191     // replace
1192     auto replaceValue = navigationStack_->GetReplaceValue();
1193     if (replaceValue != 0) {
1194         if (newTopNavDestination && preTopNavDestination) {
1195             navigationNode->TransitionWithReplace(preTopNavDestination, newTopNavDestination, false);
1196         } else if (newTopNavDestination && navigationMode_ == NavigationMode::STACK) {
1197             navigationNode->TransitionWithReplace(navBarNode, newTopNavDestination, true);
1198         }
1199         navigationStack_->UpdateReplaceValue(0);
1200         return;
1201     }
1202     // navDestination push/pop navDestination
1203     if (newTopNavDestination && preTopNavDestination) {
1204         if (isPopPage) {
1205             navigationNode->TransitionWithPop(preTopNavDestination, newTopNavDestination);
1206         } else {
1207             navigationNode->TransitionWithPush(preTopNavDestination, newTopNavDestination);
1208         }
1209         return;
1210     }
1211     // navBar push navDestination
1212     if (newTopNavDestination && navigationMode_ == NavigationMode::STACK) {
1213         navigationNode->TransitionWithPush(navBarNode, newTopNavDestination, true);
1214         return;
1215     }
1216     // navDestination pop to navBar
1217     if (preTopNavDestination) {
1218         if (navigationMode_ == NavigationMode::SPLIT) {
1219             navigationNode->TransitionWithPop(preTopNavDestination, nullptr);
1220         }
1221         if (navigationMode_ == NavigationMode::STACK) {
1222             navigationNode->TransitionWithPop(preTopNavDestination, navBarNode, true);
1223         }
1224     }
1225 }
1226 
OnVisibleChange(bool isVisible)1227 void NavigationPattern::OnVisibleChange(bool isVisible)
1228 {
1229     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1230     CHECK_NULL_VOID(hostNode);
1231     auto eventHub = hostNode->GetEventHub<NavigationEventHub>();
1232     CHECK_NULL_VOID(eventHub);
1233     eventHub->FireNavBarStateChangeEvent(isVisible);
1234 }
1235 
OnNavBarStateChange(bool modeChange)1236 void NavigationPattern::OnNavBarStateChange(bool modeChange)
1237 {
1238     auto layoutProperty = GetLayoutProperty<NavigationLayoutProperty>();
1239     CHECK_NULL_VOID(layoutProperty);
1240     auto visibilityValue = layoutProperty->GetVisibilityValue(VisibleType::VISIBLE);
1241     if (visibilityValue != VisibleType::VISIBLE) {
1242         return;
1243     }
1244 
1245     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1246     CHECK_NULL_VOID(hostNode);
1247     auto eventHub = hostNode->GetEventHub<NavigationEventHub>();
1248     CHECK_NULL_VOID(eventHub);
1249     auto currentNavigationMode = GetNavigationMode();
1250 
1251     if (modeChange) {
1252         if (currentNavigationMode == NavigationMode::SPLIT) {
1253             if (layoutProperty->GetHideNavBarValue(false)) {
1254                 eventHub->FireNavBarStateChangeEvent(false);
1255             } else {
1256                 eventHub->FireNavBarStateChangeEvent(true);
1257             }
1258         } else {
1259             if (navigationStack_->Empty() && !layoutProperty->GetHideNavBarValue(false)) {
1260                 eventHub->FireNavBarStateChangeEvent(true);
1261             } else {
1262                 eventHub->FireNavBarStateChangeEvent(false);
1263             }
1264         }
1265         SetNavBarVisibilityChange(false);
1266         return;
1267     }
1268 
1269     if (GetNavBarVisibilityChange()) {
1270         if (!layoutProperty->GetHideNavBarValue(false)) {
1271             eventHub->FireNavBarStateChangeEvent(true);
1272         } else {
1273             eventHub->FireNavBarStateChangeEvent(false);
1274         }
1275         SetNavBarVisibilityChange(false);
1276         return;
1277     }
1278 
1279     if (currentNavigationMode == NavigationMode::STACK) {
1280         eventHub->FireNavBarStateChangeEvent(navigationStack_->Empty());
1281     }
1282 }
1283 
OnNavigationModeChange(bool modeChange)1284 void NavigationPattern::OnNavigationModeChange(bool modeChange)
1285 {
1286     if (!modeChange) {
1287         return;
1288     }
1289     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1290     CHECK_NULL_VOID(hostNode);
1291     auto eventHub = hostNode->GetEventHub<NavigationEventHub>();
1292     CHECK_NULL_VOID(eventHub);
1293     eventHub->FireNavigationModeChangeEvent(navigationMode_);
1294     // fire navigation stack navigation mode change event
1295     navigationStack_->FireNavigationModeChange(navigationMode_);
1296 }
1297 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)1298 bool NavigationPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
1299 {
1300     if (config.skipMeasure && config.skipLayout) {
1301         return false;
1302     }
1303     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1304     CHECK_NULL_RETURN(hostNode, false);
1305     UpdateIsFullPageNavigation(hostNode);
1306     if (navigationModeChange_) {
1307         if (NavigationMode::STACK == navigationMode_) {
1308             // Set focus on navDestination when mode changes to STACK
1309             RefreshFocusToDestination();
1310         }
1311         AbortAnimation(hostNode);
1312     }
1313     auto context = PipelineContext::GetCurrentContext();
1314     if (context) {
1315         context->GetTaskExecutor()->PostTask(
1316             [weak = WeakClaim(this), navigationStackWeak = WeakPtr<NavigationStack>(navigationStack_),
1317                 navigationWeak = WeakPtr<NavigationGroupNode>(hostNode)] {
1318                 auto pattern = weak.Upgrade();
1319                 CHECK_NULL_VOID(pattern);
1320                 auto navigationGroupNode = navigationWeak.Upgrade();
1321                 CHECK_NULL_VOID(navigationGroupNode);
1322                 auto navigationLayoutProperty =
1323                     AceType::DynamicCast<NavigationLayoutProperty>(navigationGroupNode->GetLayoutProperty());
1324                 CHECK_NULL_VOID(navigationLayoutProperty);
1325                 auto navigationStack = navigationStackWeak.Upgrade();
1326                 CHECK_NULL_VOID(navigationStack);
1327                 auto curTopNavPath = navigationStack->GetTopNavPath();
1328                 if (curTopNavPath.has_value()) {
1329                     // considering backButton visibility
1330                     auto curTopNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(
1331                         NavigationGroupNode::GetNavDestinationNode(curTopNavPath->second));
1332                     pattern->UpdateContextRect(curTopNavDestination, navigationGroupNode);
1333                 }
1334                 // considering navBar visibility
1335                 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationGroupNode->GetNavBarNode());
1336                 CHECK_NULL_VOID(navBarNode);
1337                 auto navBarLayoutProperty = navBarNode->GetLayoutProperty<NavBarLayoutProperty>();
1338                 CHECK_NULL_VOID(navBarLayoutProperty);
1339                 bool isSetInvisible =
1340                     (navigationGroupNode->GetNeedSetInvisible() && navigationStack->Size() != 0) ? true : false;
1341                 if (navigationLayoutProperty->GetHideNavBar().value_or(false) ||
1342                     (pattern->GetNavigationMode() == NavigationMode::STACK && isSetInvisible)) {
1343                     navBarLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
1344                     navBarNode->SetJSViewActive(false);
1345                 } else {
1346                     navBarNode->GetRenderContext()->UpdateOpacity(1.0f);
1347                     navBarLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
1348                     navBarNode->SetJSViewActive(true);
1349                 }
1350                 auto navigationContentNode = AceType::DynamicCast<FrameNode>(navigationGroupNode->GetContentNode());
1351                 CHECK_NULL_VOID(navigationContentNode);
1352                 auto navDestinationNode =
1353                     AceType::DynamicCast<NavDestinationGroupNode>(navigationContentNode->GetLastChild());
1354                 CHECK_NULL_VOID(navDestinationNode);
1355                 auto navDestinationPattern = navDestinationNode->GetPattern<NavDestinationPattern>();
1356                 auto navDestinationFocusHub = navDestinationNode->GetFocusHub();
1357                 CHECK_NULL_VOID(navDestinationFocusHub);
1358                 auto defaultFocusHub = navDestinationFocusHub->GetChildFocusNodeByType(FocusNodeType::DEFAULT);
1359                 if (!defaultFocusHub && navDestinationNode->GetChildren().size() <= EMPTY_DESTINATION_CHILD_SIZE &&
1360                     navDestinationPattern->GetBackButtonState()) {
1361                     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navDestinationNode->GetTitleBarNode());
1362                     CHECK_NULL_VOID(titleBarNode);
1363                     auto backButtonNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetBackButton());
1364                     backButtonNode->GetOrCreateFocusHub()->SetIsDefaultFocus(true);
1365                     auto navigation = pattern->GetHost();
1366                     CHECK_NULL_VOID(navigation);
1367                     auto navigationFocusHub = navigation->GetFocusHub();
1368                     CHECK_NULL_VOID(navigationFocusHub);
1369                     auto navDestinationFocusView = navDestinationNode->GetPattern<FocusView>();
1370                     if (navigationFocusHub->IsCurrentFocus() && navDestinationFocusView) {
1371                         if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1372                             navDestinationFocusView->SetIsViewRootScopeFocused(false);
1373                         }
1374                         navDestinationFocusView->FocusViewShow();
1375                     }
1376                 }
1377             },
1378             TaskExecutor::TaskType::UI, "ArkUINavigationDirtyLayoutWrapperSwap");
1379     }
1380     auto navigationLayoutProperty = AceType::DynamicCast<NavigationLayoutProperty>(hostNode->GetLayoutProperty());
1381     CHECK_NULL_RETURN(navigationLayoutProperty, false);
1382     UpdateTitleModeChangeEventHub(hostNode);
1383     AddDividerHotZoneRect();
1384     ifNeedInit_ = false;
1385     return false;
1386 }
1387 
AbortAnimation(RefPtr<NavigationGroupNode> & hostNode)1388 void NavigationPattern::AbortAnimation(RefPtr<NavigationGroupNode>& hostNode)
1389 {
1390     TAG_LOGD(AceLogTag::ACE_NAVIGATION, "Aborting navigation animations");
1391     if (!hostNode->GetPushAnimations().empty()) {
1392         auto pushAnimations = hostNode->GetPushAnimations();
1393         for (const auto& animation : pushAnimations) {
1394             if (animation) {
1395                 AnimationUtils::StopAnimation(animation);
1396             }
1397         }
1398     }
1399     if (!hostNode->GetPopAnimations().empty()) {
1400         auto popAnimations = hostNode->GetPopAnimations();
1401         for (const auto& animation : popAnimations) {
1402             if (animation) {
1403                 AnimationUtils::StopAnimation(animation);
1404             }
1405         }
1406     }
1407     hostNode->CleanPushAnimations();
1408     hostNode->CleanPopAnimations();
1409 }
1410 
UpdateContextRect(const RefPtr<NavDestinationGroupNode> & curDestination,const RefPtr<NavigationGroupNode> & hostNode)1411 void NavigationPattern::UpdateContextRect(
1412     const RefPtr<NavDestinationGroupNode>& curDestination, const RefPtr<NavigationGroupNode>& hostNode)
1413 {
1414     CHECK_NULL_VOID(curDestination);
1415     CHECK_NULL_VOID(hostNode);
1416     auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
1417     CHECK_NULL_VOID(navBarNode);
1418     auto navigationPattern = AceType::DynamicCast<NavigationPattern>(hostNode->GetPattern());
1419     CHECK_NULL_VOID(navigationPattern);
1420 
1421     if (navigationPattern->GetNavigationMode() == NavigationMode::STACK) {
1422         curDestination->GetRenderContext()->SetActualForegroundColor(Color::TRANSPARENT);
1423         return;
1424     }
1425     auto navigationLayoutProperty = hostNode->GetLayoutProperty<NavigationLayoutProperty>();
1426     CHECK_NULL_VOID(navigationLayoutProperty);
1427     auto navBarProperty = navBarNode->GetLayoutProperty();
1428     navBarProperty->UpdateVisibility(VisibleType::VISIBLE);
1429     navBarNode->SetJSViewActive(true);
1430     if (!curDestination->IsOnAnimation()) {
1431         curDestination->GetRenderContext()->UpdateTranslateInXY(OffsetF { 0.0f, 0.0f });
1432         curDestination->GetRenderContext()->SetActualForegroundColor(Color::TRANSPARENT);
1433         navBarNode->GetEventHub<EventHub>()->SetEnabledInternal(true);
1434         auto titleBarNode = DynamicCast<TitleBarNode>(navBarNode->GetTitleBarNode());
1435         CHECK_NULL_VOID(titleBarNode);
1436         auto titleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
1437         CHECK_NULL_VOID(titleNode);
1438         titleNode->GetRenderContext()->UpdateTranslateInXY(OffsetF { 0.0f, 0.0f });
1439     }
1440 }
1441 
UpdateTitleModeChangeEventHub(const RefPtr<NavigationGroupNode> & hostNode)1442 bool NavigationPattern::UpdateTitleModeChangeEventHub(const RefPtr<NavigationGroupNode>& hostNode)
1443 {
1444     auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
1445     CHECK_NULL_RETURN(navBarNode, false);
1446     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navBarNode->GetTitleBarNode());
1447     CHECK_NULL_RETURN(titleBarNode, false);
1448     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
1449     CHECK_NULL_RETURN(titleBarLayoutProperty, false);
1450     auto eventHub = hostNode->GetEventHub<NavigationEventHub>();
1451     CHECK_NULL_RETURN(eventHub, false);
1452     if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) == NavigationTitleMode::FREE) {
1453         auto titleBarPattern = AceType::DynamicCast<TitleBarPattern>(titleBarNode->GetPattern());
1454         CHECK_NULL_RETURN(titleBarPattern, false);
1455         NavigationTitleMode titleMode = titleBarPattern->GetNavigationTitleMode();
1456         if (titleMode != NavigationTitleMode::FREE && titleMode_ != titleMode) {
1457             NavigationTitleModeChangeEvent navigationTitleModeChange(titleMode == NavigationTitleMode::MINI);
1458             eventHub->FireChangeEvent(&navigationTitleModeChange);
1459             titleMode_ = titleMode;
1460         }
1461     }
1462     return true;
1463 }
1464 
GenerateUINodeByIndex(int32_t index)1465 RefPtr<UINode> NavigationPattern::GenerateUINodeByIndex(int32_t index)
1466 {
1467     auto node = navigationStack_->CreateNodeByIndex(index, parentNode_);
1468     auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(
1469         NavigationGroupNode::GetNavDestinationNode(node));
1470     CHECK_NULL_RETURN(navDestinationNode, node);
1471     // set navigation id
1472     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1473     auto navDestinationPattern = AceType::DynamicCast<NavDestinationPattern>(navDestinationNode->GetPattern());
1474     if (navigationNode && navDestinationPattern) {
1475         navDestinationPattern->SetNavigationNode(navigationNode);
1476         navDestinationPattern->SetNavigationId(navigationNode->GetInspectorId().value_or(""));
1477         navigationStack_->SetDestinationIdToJsStack(
1478             index, std::to_string(navDestinationPattern->GetNavDestinationId()));
1479     }
1480     auto eventHub = navDestinationNode->GetEventHub<NavDestinationEventHub>();
1481     CHECK_NULL_RETURN(eventHub, node);
1482     eventHub->FireOnWillAppear();
1483     return node;
1484 }
1485 
InitDividerMouseEvent(const RefPtr<InputEventHub> & inputHub)1486 void NavigationPattern::InitDividerMouseEvent(const RefPtr<InputEventHub>& inputHub)
1487 {
1488     CHECK_NULL_VOID(inputHub);
1489     CHECK_NULL_VOID(!hoverEvent_);
1490 
1491     auto hoverTask = [weak = WeakClaim(this)](bool isHover) {
1492         auto pattern = weak.Upgrade();
1493         if (pattern) {
1494             pattern->OnHover(isHover);
1495         }
1496     };
1497     hoverEvent_ = MakeRefPtr<InputEvent>(std::move(hoverTask));
1498     inputHub->AddOnHoverEvent(hoverEvent_);
1499 }
1500 
HandleDragStart()1501 void NavigationPattern::HandleDragStart()
1502 {
1503     preNavBarWidth_ = realNavBarWidth_;
1504     if (!isDividerDraggable_) {
1505         return;
1506     }
1507     isInDividerDrag_ = true;
1508     auto pipeline = PipelineContext::GetCurrentContext();
1509     CHECK_NULL_VOID(pipeline);
1510     auto windowId = pipeline->GetWindowId();
1511     auto mouseStyle = MouseStyle::CreateMouseStyle();
1512     mouseStyle->SetPointerStyle(static_cast<int32_t>(windowId), MouseFormat::RESIZE_LEFT_RIGHT);
1513 }
1514 
HandleDragUpdate(float xOffset)1515 void NavigationPattern::HandleDragUpdate(float xOffset)
1516 {
1517     auto navigationLayoutProperty = GetLayoutProperty<NavigationLayoutProperty>();
1518     CHECK_NULL_VOID(navigationLayoutProperty);
1519     auto host = GetHost();
1520     CHECK_NULL_VOID(host);
1521     auto geometryNode = host->GetGeometryNode();
1522     CHECK_NULL_VOID(geometryNode);
1523     auto frameSize = geometryNode->GetFrameSize();
1524     auto frameWidth = frameSize.Width();
1525     auto constraint = navigationLayoutProperty->GetLayoutConstraint();
1526     auto parentSize = CreateIdealSize(constraint.value(), Axis::HORIZONTAL, MeasureType::MATCH_PARENT);
1527 
1528     float minNavBarWidthPx = minNavBarWidthValue_.ConvertToPxWithSize(parentSize.Width().value_or(0.0f));
1529     float maxNavBarWidthPx = maxNavBarWidthValue_.ConvertToPxWithSize(parentSize.Width().value_or(0.0f));
1530     float minContentWidthPx = minContentWidthValue_.ConvertToPxWithSize(parentSize.Width().value_or(0.0f));
1531     auto dividerWidth = static_cast<float>(DIVIDER_WIDTH.ConvertToPx());
1532 
1533     auto navigationPosition = navigationLayoutProperty->GetNavBarPosition().value_or(NavBarPosition::START);
1534     bool isNavBarStart = navigationPosition == NavBarPosition::START;
1535     auto navBarLine = isRightToLeft_ ? preNavBarWidth_ + (isNavBarStart ? -xOffset : xOffset)
1536                                      : preNavBarWidth_ + (isNavBarStart ? xOffset : -xOffset);
1537     float currentNavBarWidth = realNavBarWidth_;
1538 
1539     if (maxNavBarWidthPx + dividerWidth + minContentWidthPx > frameWidth) {
1540         maxNavBarWidthPx = frameWidth - minContentWidthPx - dividerWidth;
1541     }
1542     navBarLine = std::min(navBarLine, maxNavBarWidthPx);
1543 
1544     if (userSetMinContentFlag_ && !userSetNavBarRangeFlag_) {
1545         if (minContentWidthPx >= frameWidth) {
1546             realNavBarWidth_ = 0.0f;
1547         } else if (navBarLine + dividerWidth + minContentWidthPx <= frameWidth) {
1548             realNavBarWidth_ = navBarLine;
1549         } else {
1550             realNavBarWidth_ = frameWidth - minContentWidthPx - dividerWidth;
1551         }
1552     } else {
1553         realDividerWidth_ = dividerWidth;
1554         float remainingSpace = frameWidth - navBarLine - dividerWidth;
1555         if (remainingSpace >= minContentWidthPx) {
1556             realNavBarWidth_ = navBarLine;
1557         } else if (remainingSpace < minContentWidthPx && navBarLine > minNavBarWidthPx) {
1558             realNavBarWidth_ = frameWidth - minContentWidthPx - dividerWidth;
1559         } else {
1560             realNavBarWidth_ = minNavBarWidthPx;
1561         }
1562     }
1563     realNavBarWidth_ = std::min(realNavBarWidth_, frameWidth);
1564     realNavBarWidth_ = std::min(realNavBarWidth_, maxNavBarWidthPx);
1565     realNavBarWidth_ = std::max(realNavBarWidth_, minNavBarWidthPx);
1566     // MEASURE
1567     if (realNavBarWidth_ != currentNavBarWidth) {
1568         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
1569     }
1570 }
1571 
HandleDragEnd()1572 void NavigationPattern::HandleDragEnd()
1573 {
1574     preNavBarWidth_ = realNavBarWidth_;
1575     if (!isDividerDraggable_) {
1576         return;
1577     }
1578     isInDividerDrag_ = false;
1579     auto pipeline = PipelineContext::GetCurrentContext();
1580     CHECK_NULL_VOID(pipeline);
1581     auto windowId = pipeline->GetWindowId();
1582     auto mouseStyle = MouseStyle::CreateMouseStyle();
1583     mouseStyle->SetPointerStyle(static_cast<int32_t>(windowId), MouseFormat::DEFAULT);
1584 }
1585 
InitPanEvent(const RefPtr<GestureEventHub> & gestureHub)1586 void NavigationPattern::InitPanEvent(const RefPtr<GestureEventHub>& gestureHub)
1587 {
1588     CHECK_NULL_VOID(!panEvent_);
1589     auto actionStartTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1590         auto pattern = weak.Upgrade();
1591         CHECK_NULL_VOID(pattern);
1592         pattern->HandleDragStart();
1593     };
1594     auto actionUpdateTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1595         auto pattern = weak.Upgrade();
1596         CHECK_NULL_VOID(pattern);
1597         pattern->HandleDragUpdate(static_cast<float>(info.GetOffsetX()));
1598     };
1599     auto actionEndTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1600         auto pattern = weak.Upgrade();
1601         CHECK_NULL_VOID(pattern);
1602         pattern->HandleDragEnd();
1603     };
1604     auto actionCancelTask = [weak = WeakClaim(this)]() {
1605         auto pattern = weak.Upgrade();
1606         CHECK_NULL_VOID(pattern);
1607         pattern->HandleDragEnd();
1608     };
1609     panEvent_ = MakeRefPtr<PanEvent>(
1610         std::move(actionStartTask), std::move(actionUpdateTask), std::move(actionEndTask), std::move(actionCancelTask));
1611     PanDirection panDirection = { .type = PanDirection::HORIZONTAL };
1612     gestureHub->AddPanEvent(panEvent_, panDirection, DEFAULT_PAN_FINGER, DEFAULT_PAN_DISTANCE);
1613 }
1614 
OnHover(bool isHover)1615 void NavigationPattern::OnHover(bool isHover)
1616 {
1617     if (isInDividerDrag_) {
1618         return;
1619     }
1620     MouseFormat format = isHover ? MouseFormat::RESIZE_LEFT_RIGHT : MouseFormat::DEFAULT;
1621     auto pipeline = PipelineContext::GetCurrentContext();
1622     CHECK_NULL_VOID(pipeline);
1623     auto windowId = pipeline->GetWindowId();
1624     auto mouseStyle = MouseStyle::CreateMouseStyle();
1625     int32_t currentPointerStyle = 0;
1626     mouseStyle->GetPointerStyle(static_cast<int32_t>(windowId), currentPointerStyle);
1627     auto layoutProperty = GetLayoutProperty<NavigationLayoutProperty>();
1628     CHECK_NULL_VOID(layoutProperty);
1629     auto userSetMinNavBarWidthValue = layoutProperty->GetMinNavBarWidthValue(Dimension(0.0));
1630     auto userSetMaxNavBarWidthValue = layoutProperty->GetMaxNavBarWidthValue(Dimension(0.0));
1631     bool navBarWidthRangeEqual = userSetMinNavBarWidthValue.Value() >= userSetMaxNavBarWidthValue.Value();
1632     if ((userSetNavBarWidthFlag_ && !userSetNavBarRangeFlag_) || (userSetNavBarRangeFlag_ && navBarWidthRangeEqual)) {
1633         isDividerDraggable_ = false;
1634         return;
1635     }
1636     isDividerDraggable_ = true;
1637     if (currentPointerStyle != static_cast<int32_t>(format)) {
1638         mouseStyle->SetPointerStyle(static_cast<int32_t>(windowId), format);
1639     }
1640 }
1641 
GetDividerNode() const1642 RefPtr<FrameNode> NavigationPattern::GetDividerNode() const
1643 {
1644     auto host = GetHost();
1645     CHECK_NULL_RETURN(host, nullptr);
1646     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(host);
1647     CHECK_NULL_RETURN(navigationNode, nullptr);
1648     auto dividerFrameNode = AceType::DynamicCast<FrameNode>(navigationNode->GetDividerNode());
1649     CHECK_NULL_RETURN(dividerFrameNode, nullptr);
1650     return dividerFrameNode;
1651 }
1652 
BeforeSyncGeometryProperties(const DirtySwapConfig &)1653 void NavigationPattern::BeforeSyncGeometryProperties(const DirtySwapConfig& /* config */)
1654 {
1655     AddDividerHotZoneRect();
1656 }
1657 
AddDividerHotZoneRect()1658 void NavigationPattern::AddDividerHotZoneRect()
1659 {
1660     if (realDividerWidth_ <= 0.0f) {
1661         return;
1662     }
1663     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1664     CHECK_NULL_VOID(hostNode);
1665     auto navBarNode = AceType::DynamicCast<FrameNode>(hostNode->GetNavBarNode());
1666     CHECK_NULL_VOID(navBarNode);
1667     auto geometryNode = navBarNode->GetGeometryNode();
1668     CHECK_NULL_VOID(geometryNode);
1669 
1670     OffsetF hotZoneOffset;
1671     hotZoneOffset.SetX(-DEFAULT_DIVIDER_HOT_ZONE_HORIZONTAL_PADDING.ConvertToPx());
1672     hotZoneOffset.SetY(DEFAULT_DIVIDER_START_MARGIN.ConvertToPx());
1673     SizeF hotZoneSize;
1674     hotZoneSize.SetWidth(realDividerWidth_ + DIVIDER_HOT_ZONE_HORIZONTAL_PADDING_NUM *
1675                                                  DEFAULT_DIVIDER_HOT_ZONE_HORIZONTAL_PADDING.ConvertToPx());
1676     hotZoneSize.SetHeight(geometryNode->GetFrameSize().Height());
1677     DimensionRect hotZoneRegion;
1678     auto paintHeight = GetPaintRectHeight(navBarNode);
1679     if (navigationMode_ == NavigationMode::STACK) {
1680         hotZoneRegion.SetSize(DimensionSize(Dimension(0.0f), Dimension(0.0f)));
1681     } else {
1682         hotZoneRegion.SetSize(DimensionSize(
1683             Dimension(hotZoneSize.Width()), Dimension(NearZero(paintHeight) ? hotZoneSize.Height() : paintHeight)));
1684     }
1685     hotZoneRegion.SetOffset(DimensionOffset(Dimension(hotZoneOffset.GetX()), Dimension(hotZoneOffset.GetY())));
1686 
1687     std::vector<DimensionRect> mouseRegion;
1688     mouseRegion.emplace_back(hotZoneRegion);
1689 
1690     auto dividerFrameNode = GetDividerNode();
1691     CHECK_NULL_VOID(dividerFrameNode);
1692     auto dividerGestureHub = dividerFrameNode->GetOrCreateGestureEventHub();
1693     CHECK_NULL_VOID(dividerGestureHub);
1694     dividerGestureHub->SetMouseResponseRegion(mouseRegion);
1695 
1696     auto dragRectOffset = geometryNode->GetMarginFrameOffset();
1697     dragRectOffset.SetX(-DEFAULT_DRAG_REGION.ConvertToPx());
1698     dragRect_.SetOffset(dragRectOffset);
1699     if (navigationMode_ == NavigationMode::STACK) {
1700         dragRect_.SetSize(SizeF(0.0f, 0.0f));
1701     } else {
1702         dragRect_.SetSize(SizeF(DEFAULT_DRAG_REGION.ConvertToPx() * DEFAULT_HALF + realDividerWidth_,
1703             NearZero(paintHeight) ? geometryNode->GetFrameSize().Height() : paintHeight));
1704     }
1705 
1706     std::vector<DimensionRect> responseRegion;
1707     DimensionOffset responseOffset(dragRectOffset);
1708     DimensionRect responseRect(Dimension(dragRect_.Width(), DimensionUnit::PX),
1709         Dimension(dragRect_.Height(), DimensionUnit::PX), responseOffset);
1710     responseRegion.emplace_back(responseRect);
1711     dividerGestureHub->SetResponseRegion(responseRegion);
1712 }
1713 
NotifyDialogChange(NavDestinationLifecycle lifecycle,bool isNavigationChanged,bool isFromStandardIndex)1714 void NavigationPattern::NotifyDialogChange(NavDestinationLifecycle lifecycle, bool isNavigationChanged,
1715     bool isFromStandardIndex)
1716 {
1717     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1718     const auto& navDestinationNodes = navigationStack_->GetAllNavDestinationNodes();
1719     int32_t lastStandardIndex = hostNode->GetLastStandardIndex();
1720     int32_t standardIndex = lastStandardIndex >= 0 ? lastStandardIndex : 0;
1721     int32_t start = isFromStandardIndex ? standardIndex : 0;
1722     int32_t end = isFromStandardIndex ? navigationStack_->Size() : standardIndex;
1723     bool isShow = lifecycle == NavDestinationLifecycle::ON_SHOW || (lifecycle == NavDestinationLifecycle::ON_WILL_SHOW);
1724     if (isShow) {
1725         for (int32_t index = start; index < end; index++) {
1726             NotifyDestinationLifecycle(navDestinationNodes[index].second, lifecycle);
1727         }
1728     } else {
1729         for (int32_t index = end - 1; index >= 0 && index >= start; index--) {
1730             NotifyDestinationLifecycle(navDestinationNodes[index].second, lifecycle);
1731         }
1732     }
1733 }
1734 
DumpInfo()1735 void NavigationPattern::DumpInfo()
1736 {
1737     if (!navigationStack_) {
1738         return;
1739     }
1740     DumpLog::GetInstance().AddDesc(std::string("size").append(std::to_string(navigationStack_->Size())));
1741 }
1742 
OnColorConfigurationUpdate()1743 void NavigationPattern::OnColorConfigurationUpdate()
1744 {
1745     auto dividerNode = GetDividerNode();
1746     CHECK_NULL_VOID(dividerNode);
1747     auto theme = NavigationGetTheme();
1748     CHECK_NULL_VOID(theme);
1749     dividerNode->GetRenderContext()->UpdateBackgroundColor(theme->GetNavigationDividerColor());
1750 }
1751 
TriggerCustomAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage)1752 bool NavigationPattern::TriggerCustomAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
1753     const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage)
1754 {
1755     if ((!preTopNavDestination && !newTopNavDestination) || !onTransition_) {
1756         return false;
1757     }
1758     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1759     hostNode->SetIsOnAnimation(true);
1760     if (!newTopNavDestination) {
1761         // pop animation with top navDestination, recover navBar visible tag
1762         hostNode->SetNeedSetInvisible(false);
1763     }
1764     auto proxy = AceType::MakeRefPtr<NavigationTransitionProxy>();
1765     proxy->SetPreDestination(preTopNavDestination);
1766     proxy->SetTopDestination(newTopNavDestination);
1767     auto proxyId = proxy->GetProxyId();
1768     proxyList_.emplace_back(proxy);
1769     auto navigationTransition = ExecuteTransition(preTopNavDestination, newTopNavDestination, isPopPage);
1770     if (!navigationTransition.isValid) {
1771         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "custom transition value is invalid, do default animation");
1772         return false;
1773     }
1774     ExecuteAddAnimation(preTopNavDestination, newTopNavDestination, isPopPage, proxy, navigationTransition);
1775     ACE_SCOPED_TRACE_COMMERCIAL("Navigation page custom transition start");
1776     if (navigationTransition.interactive) {
1777         PerfMonitor::GetPerfMonitor()->Start(PerfConstants::ABILITY_OR_PAGE_SWITCH_INTERACTIVE,
1778             PerfActionType::FIRST_MOVE, "");
1779         auto finishCallback = [weakNavigation = WeakClaim(this),
1780                                   weakPreNavDestination = WeakPtr<NavDestinationGroupNode>(preTopNavDestination),
1781                                   weakNewNavDestination = WeakPtr<NavDestinationGroupNode>(newTopNavDestination),
1782                                   isPopPage, proxyId]() {
1783             auto pattern = weakNavigation.Upgrade();
1784             CHECK_NULL_VOID(pattern);
1785             auto proxy = pattern->GetProxyById(proxyId);
1786             if (proxy == nullptr) {
1787                 return;
1788             }
1789             if (!proxy->GetInteractive()) {
1790                 pattern->RemoveProxyById(proxyId);
1791                 return;
1792             }
1793             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "interactive animation is finish: %{public}d", proxy->GetIsSuccess());
1794             pattern->isFinishInteractiveAnimation_ = true;
1795             auto preDestination = weakPreNavDestination.Upgrade();
1796             auto topDestination = weakNewNavDestination.Upgrade();
1797             proxy->SetIsFinished(true);
1798             // this flag will be update in cancelTransition or finishTransition
1799             ACE_SCOPED_TRACE_COMMERCIAL("navigation page custom transition end");
1800             PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH_INTERACTIVE, true);
1801             if (proxy->GetIsSuccess()) {
1802                 pattern->GetNavigationStack()->ClearRecoveryList();
1803                 pattern->OnCustomAnimationFinish(preDestination, topDestination, isPopPage);
1804             } else {
1805                 // fire page cancel transition
1806                 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "interactive animation canceled");
1807                 pattern->RecoveryToLastStack(preDestination, topDestination);
1808                 pattern->SyncWithJsStackIfNeeded();
1809             }
1810             proxy->FireEndCallback();
1811             pattern->RemoveProxyById(proxyId);
1812         };
1813         auto pipelineContext = hostNode->GetContext();
1814         CHECK_NULL_RETURN(pipelineContext, false);
1815         auto navigationManager = pipelineContext->GetNavigationManager();
1816         CHECK_NULL_RETURN(navigationManager, false);
1817         navigationManager->SetInteractive(hostNode->GetId());
1818         proxy->SetInteractiveAnimation(AnimationUtils::CreateInteractiveAnimation(
1819             nullptr, finishCallback), finishCallback);
1820         navigationTransition.transition(proxy);
1821         isFinishInteractiveAnimation_ = false;
1822         navigationManager->FinishInteractiveAnimation();
1823         proxy->StartAnimation();
1824     } else {
1825         PerfMonitor::GetPerfMonitor()->Start(PerfConstants::ABILITY_OR_PAGE_SWITCH, PerfActionType::LAST_UP, "");
1826         navigationStack_->ClearRecoveryList();
1827         navigationTransition.transition(proxy);
1828         // enable render group for text node during custom animation to reduce
1829         // unnecessary redrawing
1830         if (isPopPage && preTopNavDestination) {
1831             preTopNavDestination->UpdateTextNodeListAsRenderGroup(isPopPage, proxy);
1832         }
1833         if (!isPopPage && newTopNavDestination) {
1834             newTopNavDestination->UpdateTextNodeListAsRenderGroup(isPopPage, proxy);
1835         }
1836     }
1837 
1838     RefPtr<EventHub> eventHub;
1839     if (!preTopNavDestination && navigationMode_ == NavigationMode::STACK) {
1840         auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1841         CHECK_NULL_RETURN(hostNode, true);
1842         auto navBarNode = AceType::DynamicCast<FrameNode>(hostNode->GetNavBarNode());
1843         CHECK_NULL_RETURN(navBarNode, true);
1844         eventHub = navBarNode->GetEventHub<EventHub>();
1845     }
1846     if (preTopNavDestination) {
1847         eventHub = preTopNavDestination->GetEventHub<EventHub>();
1848     }
1849     CHECK_NULL_RETURN(eventHub, true);
1850     eventHub->SetEnabledInternal(false);
1851     return true;
1852 }
1853 
OnCustomAnimationFinish(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage)1854 void NavigationPattern::OnCustomAnimationFinish(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
1855     const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage)
1856 {
1857     if (!preTopNavDestination && !newTopNavDestination) {
1858         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "preDestination and topDestination is invalid");
1859         return;
1860     }
1861     ACE_SCOPED_TRACE_COMMERCIAL("Navigation page custom transition end");
1862     PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH, true);
1863     auto replaceValue = navigationStack_->GetReplaceValue();
1864     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1865     CHECK_NULL_VOID(hostNode);
1866     hostNode->SetIsOnAnimation(false);
1867     if (preTopNavDestination) {
1868         preTopNavDestination->SetIsOnAnimation(false);
1869     }
1870     if (newTopNavDestination) {
1871         newTopNavDestination->SetIsOnAnimation(false);
1872     }
1873     auto id = hostNode->GetTopDestination() ? hostNode->GetTopDestination()->GetAccessibilityId() : -1;
1874     hostNode->OnAccessibilityEvent(
1875         AccessibilityEventType::PAGE_CHANGE, id, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID);
1876     do {
1877         if (replaceValue != 0) {
1878             hostNode->DealNavigationExit(preTopNavDestination, preTopNavDestination == nullptr);
1879             navigationStack_->UpdateReplaceValue(0);
1880             break;
1881         }
1882         if ((newTopNavDestination && preTopNavDestination && isPopPage) ||
1883             (preTopNavDestination && !newTopNavDestination)) {
1884             PageTransitionType preNodeTransitionType = preTopNavDestination->GetTransitionType();
1885             if (preNodeTransitionType != PageTransitionType::EXIT_POP) {
1886                 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "previous destination node is executing another transition");
1887                 return;
1888             }
1889             auto preDestinationPattern = preTopNavDestination->GetPattern<NavDestinationPattern>();
1890             CHECK_NULL_VOID(preDestinationPattern);
1891             auto shallowBuilder = preDestinationPattern->GetShallowBuilder();
1892             if (shallowBuilder) {
1893                 shallowBuilder->MarkIsExecuteDeepRenderDone(false);
1894             }
1895             auto parent = preTopNavDestination->GetParent();
1896             CHECK_NULL_VOID(parent);
1897             parent->RemoveChild(preTopNavDestination);
1898             parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1899             break;
1900         }
1901         if ((newTopNavDestination && preTopNavDestination && !isPopPage) ||
1902             (!preTopNavDestination && newTopNavDestination && navigationMode_ == NavigationMode::STACK)) {
1903             hostNode->SetNeedSetInvisible(true);
1904             RefPtr<FrameNode> node;
1905             PageTransitionType preNodeTransitionType;
1906             if (preTopNavDestination) {
1907                 preNodeTransitionType = preTopNavDestination->GetTransitionType();
1908                 node = preTopNavDestination;
1909             } else {
1910                 // pre destination is nullptr, preNode is navBarNode
1911                 auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
1912                 CHECK_NULL_VOID(navBarNode);
1913                 preNodeTransitionType = navBarNode->GetTransitionType();
1914                 node = AceType::DynamicCast<FrameNode>(hostNode->GetNavBarNode());
1915                 CHECK_NULL_VOID(node);
1916             }
1917             if (preNodeTransitionType != PageTransitionType::EXIT_PUSH) {
1918                 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "previous destination node is executing another transition");
1919                 return;
1920             }
1921             // recover event hub
1922             auto eventHub = node->GetEventHub<EventHub>();
1923             if (eventHub) {
1924                 eventHub->SetEnabledInternal(true);
1925             }
1926             bool isDialog = newTopNavDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG;
1927             if (isDialog) {
1928                 return;
1929             }
1930             auto property = node->GetLayoutProperty();
1931             property->UpdateVisibility(VisibleType::INVISIBLE);
1932             node->SetJSViewActive(false);
1933             if (!preTopNavDestination) {
1934                 hostNode->NotifyPageHide();
1935             }
1936         }
1937     } while (0);
1938     hostNode->RemoveDialogDestination();
1939     auto context = PipelineContext::GetCurrentContext();
1940     CHECK_NULL_VOID(context);
1941     context->MarkNeedFlushMouseEvent();
1942 }
1943 
ExecuteTransition(const RefPtr<NavDestinationGroupNode> & preTopDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage)1944 NavigationTransition NavigationPattern::ExecuteTransition(const RefPtr<NavDestinationGroupNode>& preTopDestination,
1945     const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage)
1946 {
1947     NavigationTransition navigationTransition;
1948     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1949     CHECK_NULL_RETURN(hostNode, navigationTransition);
1950     NavigationOperation operation;
1951     auto currentProxy = GetTopNavigationProxy();
1952     auto preInfo = currentProxy->GetPreDestinationContext();
1953     auto topInfo = currentProxy->GetTopDestinationContext();
1954     auto replaceValue = navigationStack_->GetReplaceValue();
1955     if (replaceValue != 0) {
1956         operation = NavigationOperation::REPLACE;
1957     } else if (!preTopDestination) {
1958         operation = NavigationOperation::PUSH;
1959         // if animated with navBarNode, recover navBar visibility
1960         hostNode->SetNeedSetInvisible(false);
1961     } else if (!newTopNavDestination) {
1962         operation = NavigationOperation::POP;
1963     } else if (isPopPage) {
1964         operation = NavigationOperation::POP;
1965     } else {
1966         operation = NavigationOperation::PUSH;
1967     }
1968 
1969     /* set transition animation flag fro navBarNode or navDestinationNode */
1970     if (operation == NavigationOperation::PUSH) {
1971         if (preTopDestination != nullptr) {
1972             preTopDestination->SetTransitionType(PageTransitionType::EXIT_PUSH);
1973         } else {
1974             // preTopDestination is nullptr, previous node is navBar node
1975             auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
1976             CHECK_NULL_RETURN(navBarNode, navigationTransition);
1977             navBarNode->SetTransitionType(PageTransitionType::EXIT_PUSH);
1978         }
1979 
1980         if (newTopNavDestination != nullptr) {
1981             newTopNavDestination->SetTransitionType(PageTransitionType::ENTER_PUSH);
1982         }
1983     }
1984     if (operation == NavigationOperation::POP) {
1985         if (preTopDestination != nullptr) {
1986             preTopDestination->SetTransitionType(PageTransitionType::EXIT_POP);
1987         }
1988         if (newTopNavDestination != nullptr) {
1989             newTopNavDestination->SetTransitionType(PageTransitionType::ENTER_POP);
1990         } else {
1991             // newTopNavDestination is nullptr, current node is navBar node
1992             auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
1993             CHECK_NULL_RETURN(navBarNode, navigationTransition);
1994             navBarNode->SetTransitionType(PageTransitionType::ENTER_POP);
1995         }
1996     }
1997     TAG_LOGI(AceLogTag::ACE_NAVIGATION, "custom animation start: operation: %{public}d", operation);
1998     return onTransition_(preInfo, topInfo, operation);
1999 }
2000 
UpdatePreNavDesZIndex(const RefPtr<FrameNode> & preTopNavDestination,const RefPtr<FrameNode> & newTopNavDestination,int32_t preLastStandardIndex)2001 void NavigationPattern::UpdatePreNavDesZIndex(const RefPtr<FrameNode> &preTopNavDestination,
2002     const RefPtr<FrameNode> &newTopNavDestination, int32_t preLastStandardIndex)
2003 {
2004     auto replaceVal = navigationStack_->GetReplaceValue();
2005     if (replaceVal != 0 && preTopNavDestination && newTopNavDestination) {
2006         auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2007         CHECK_NULL_VOID(hostNode);
2008         auto navigationContentNode = AceType::DynamicCast<FrameNode>(hostNode->GetContentNode());
2009         CHECK_NULL_VOID(navigationContentNode);
2010         auto newDesNodeContext = newTopNavDestination->GetRenderContext();
2011         CHECK_NULL_VOID(newDesNodeContext);
2012         std::optional<int32_t> newNodeZIndex = newDesNodeContext->GetZIndex();
2013         int32_t standardIndex = newNodeZIndex.value_or(0) - 1;
2014         auto hideNodes = hostNode->GetHideNodes();
2015         for (auto iter = hideNodes.begin(); iter != hideNodes.end(); ++iter) {
2016             // if navdestination nodes is not need removed, default zIndex is satisfied, don't need change
2017             if (!iter->second) {
2018                 continue;
2019             }
2020             auto navDestination = iter->first;
2021             if (!navDestination) {
2022                 continue;
2023             }
2024             auto navDestinationContext = navDestination->GetRenderContext();
2025             if (!navDestinationContext) {
2026                 continue;
2027             }
2028             // get navDestination index in hideNodes, use navdestination index in pre navigation stack
2029             int32_t hideNodesIndex =
2030                 static_cast<int32_t>(hideNodes.size()) - (navDestination->GetIndex() - preLastStandardIndex);
2031             navDestinationContext->UpdateZIndex(standardIndex - hideNodesIndex);
2032         }
2033         auto preDesNodeContext = preTopNavDestination->GetRenderContext();
2034         CHECK_NULL_VOID(preDesNodeContext);
2035         preDesNodeContext->UpdateZIndex(standardIndex);
2036         navigationContentNode->RebuildRenderContextTree();
2037         auto context = PipelineContext::GetCurrentContext();
2038         CHECK_NULL_VOID(context);
2039         context->RequestFrame();
2040     }
2041 }
2042 
SetNavigationStack(const RefPtr<NavigationStack> & navigationStack)2043 void NavigationPattern::SetNavigationStack(const RefPtr<NavigationStack>& navigationStack)
2044 {
2045     if (navigationStack_) {
2046         navigationStack_->SetOnStateChangedCallback(nullptr);
2047     }
2048     navigationStack_ = navigationStack;
2049     if (navigationStack_) {
2050         navigationStack_->SetNavigationNode(GetHost());
2051         WeakPtr<NavigationPattern> weakPattern = WeakClaim(this);
2052         auto id = Container::CurrentId();
2053         auto callback = [weakPattern, id]() {
2054             ContainerScope scope(id);
2055             auto pattern = weakPattern.Upgrade();
2056             CHECK_NULL_VOID(pattern);
2057             if (pattern->NeedSyncWithJsStackMarked()) {
2058                 return;
2059             }
2060             pattern->MarkNeedSyncWithJsStack();
2061             auto context = PipelineContext::GetCurrentContext();
2062             CHECK_NULL_VOID(context);
2063             context->AddBuildFinishCallBack([weakPattern]() {
2064                 auto pattern = weakPattern.Upgrade();
2065                 CHECK_NULL_VOID(pattern);
2066                 pattern->SyncWithJsStackIfNeeded();
2067                 auto host = pattern->GetHost();
2068                 CHECK_NULL_VOID(host);
2069                 host->MarkDirtyNode();
2070             });
2071             context->RequestFrame();
2072         };
2073         navigationStack_->SetOnStateChangedCallback(callback);
2074     }
2075 }
2076 
GetParentNavigationPattern()2077 RefPtr<NavigationPattern> NavigationPattern::GetParentNavigationPattern()
2078 {
2079     RefPtr<UINode> node = GetHost();
2080     CHECK_NULL_RETURN(node, nullptr);
2081     node = node->GetParent();
2082     while (node) {
2083         if (node->GetTag() == V2::NAVIGATION_VIEW_ETS_TAG) {
2084             break;
2085         }
2086         node = node->GetParent();
2087     }
2088     auto groupNode = AceType::DynamicCast<NavigationGroupNode>(node);
2089     CHECK_NULL_RETURN(groupNode, nullptr);
2090     return AceType::DynamicCast<NavigationPattern>(groupNode->GetPattern());
2091 }
2092 
AttachNavigationStackToParent()2093 void NavigationPattern::AttachNavigationStackToParent()
2094 {
2095     CHECK_NULL_VOID(navigationStack_);
2096     auto parentPattern = GetParentNavigationPattern();
2097     CHECK_NULL_VOID(parentPattern);
2098     auto parentStack = parentPattern->GetNavigationStack();
2099     if (parentStack) {
2100         navigationStack_->OnAttachToParent(parentStack);
2101     }
2102 }
2103 
DetachNavigationStackFromParent()2104 void NavigationPattern::DetachNavigationStackFromParent()
2105 {
2106     if (navigationStack_) {
2107         navigationStack_->OnDetachFromParent();
2108     }
2109 }
2110 
DealTransitionVisibility(const RefPtr<FrameNode> & node,bool isVisible,bool isNavBar)2111 void NavigationPattern::DealTransitionVisibility(const RefPtr<FrameNode>& node, bool isVisible, bool isNavBar)
2112 {
2113     auto renderContext = node->GetRenderContext();
2114     if (!renderContext->HasDisappearTransition()) {
2115         auto layoutProperty = node->GetLayoutProperty();
2116         layoutProperty->UpdateVisibility(isVisible ? VisibleType::VISIBLE : VisibleType::INVISIBLE);
2117         node->SetJSViewActive(isVisible);
2118         return;
2119     }
2120     auto layoutProperty = node->GetLayoutProperty();
2121     layoutProperty->UpdateVisibility(isVisible ? VisibleType::VISIBLE : VisibleType::INVISIBLE, true);
2122     renderContext->SetTransitionOutCallback([weakNode = WeakPtr<FrameNode>(node), isVisible, isNavBar] {
2123         auto curNode = weakNode.Upgrade();
2124         CHECK_NULL_VOID(curNode);
2125         if (isNavBar) {
2126             auto navBarNode = AceType::DynamicCast<NavBarNode>(curNode);
2127             if (navBarNode->GetTransitionType() != PageTransitionType::EXIT_PUSH) {
2128                 return;
2129             }
2130         } else {
2131             auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
2132             if (navDestinationNode->GetTransitionType() != PageTransitionType::EXIT_PUSH) {
2133                 return;
2134             }
2135         }
2136         curNode->SetJSViewActive(isVisible);
2137     });
2138 }
2139 
AddToDumpManager()2140 void NavigationPattern::AddToDumpManager()
2141 {
2142     auto node = GetHost();
2143     auto context = PipelineContext::GetCurrentContext();
2144     if (!node || !context) {
2145         return;
2146     }
2147     auto mgr = context->GetNavigationManager();
2148     if (!mgr) {
2149         return;
2150     }
2151     auto callback = [weakPattern = WeakClaim(this)](int depth) {
2152         auto pattern = weakPattern.Upgrade();
2153         if (!pattern) {
2154             return;
2155         }
2156         const auto& stack = pattern->GetNavigationStack();
2157         if (!stack) {
2158             return;
2159         }
2160         auto infos = stack->DumpStackInfo();
2161         for (const auto& info : infos) {
2162             DumpLog::GetInstance().Print(depth, info);
2163         }
2164     };
2165     mgr->AddNavigationDumpCallback(node->GetId(), node->GetDepth(), callback);
2166 }
2167 
RemoveFromDumpManager()2168 void NavigationPattern::RemoveFromDumpManager()
2169 {
2170     auto node = GetHost();
2171     auto context = PipelineContext::GetCurrentContext();
2172     if (!node || !context) {
2173         return;
2174     }
2175     auto mgr = context->GetNavigationManager();
2176     if (mgr) {
2177         mgr->RemoveNavigationDumpCallback(node->GetId(), node->GetDepth());
2178     }
2179 }
2180 
FireInterceptionEvent(bool isBefore,const std::optional<std::pair<std::string,RefPtr<UINode>>> & newTopPath)2181 void NavigationPattern::FireInterceptionEvent(bool isBefore,
2182     const std::optional<std::pair<std::string, RefPtr<UINode>>>& newTopPath)
2183 {
2184     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2185     RefPtr<NavDestinationContext> to;
2186     if (newTopPath.has_value()) {
2187         auto topDestination =
2188             AceType::DynamicCast<NavDestinationGroupNode>(hostNode->GetNavDestinationNode(newTopPath->second));
2189         if (topDestination) {
2190             auto pattern = AceType::DynamicCast<NavDestinationPattern>(topDestination->GetPattern());
2191             to = pattern->GetNavDestinationContext();
2192         }
2193     }
2194     NavigationOperation operation;
2195     if (isReplace_ != 0) {
2196         operation = NavigationOperation::REPLACE;
2197     } else {
2198         operation = lastPreIndex_ == -1 ? NavigationOperation::POP : NavigationOperation::PUSH;
2199     }
2200     auto layoutProperty = hostNode->GetLayoutProperty<NavigationLayoutProperty>();
2201     // mode is split and stack size is one,don't need to do animation.
2202     if ((layoutProperty->GetUsrNavigationModeValue(NavigationMode::AUTO) == NavigationMode::SPLIT
2203         || navigationMode_ == NavigationMode::SPLIT) && !preContext_) {
2204         isAnimated_ = false;
2205     }
2206     navigationStack_->FireNavigationInterception(isBefore, preContext_, to, operation,
2207         isAnimated_);
2208 
2209     if (!isBefore) {
2210         NotifyNavDestinationSwitch(preContext_, to, operation);
2211     }
2212 }
2213 
UpdateIsAnimation(const std::optional<std::pair<std::string,RefPtr<UINode>>> & preTopNavPath)2214 void NavigationPattern::UpdateIsAnimation(const std::optional<std::pair<std::string, RefPtr<UINode>>>& preTopNavPath)
2215 {
2216     auto disAbleAnimation = navigationStack_->GetDisableAnimation();
2217     auto animated = navigationStack_->GetAnimatedValue();
2218     // current animation flag is false
2219     if (disAbleAnimation || !animated) {
2220         isAnimated_ = false;
2221         return;
2222     }
2223     // check is dialog mode
2224     bool isDialog = false;
2225     if (preTopNavPath.has_value()) {
2226         auto preDestination = AceType::DynamicCast<NavDestinationGroupNode>(
2227             NavigationGroupNode::GetNavDestinationNode(preTopNavPath->second));
2228         if (preDestination) {
2229             isDialog = isDialog || (preDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG);
2230         }
2231     }
2232     auto topNode = navigationStack_->Get();
2233     if (topNode) {
2234         auto newTopDestination = AceType::DynamicCast<NavDestinationGroupNode>(
2235             NavigationGroupNode::GetNavDestinationNode(topNode));
2236         if (newTopDestination) {
2237             isDialog = isDialog || (newTopDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG);
2238         }
2239     }
2240     if (!isDialog) {
2241         isAnimated_ = true;
2242         return;
2243     }
2244     isAnimated_ = isCustomAnimation_;
2245 }
2246 
NotifyNavDestinationSwitch(const RefPtr<NavDestinationContext> & from,const RefPtr<NavDestinationContext> & to,NavigationOperation operation)2247 void NavigationPattern::NotifyNavDestinationSwitch(const RefPtr<NavDestinationContext>& from,
2248     const RefPtr<NavDestinationContext>& to, NavigationOperation operation)
2249 {
2250     auto host = GetHost();
2251     auto NavdestinationSwitchFunc =
2252         UIObserverHandler::GetInstance().GetHandleNavDestinationSwitchFunc();
2253     if (!host || !NavdestinationSwitchFunc) {
2254         return;
2255     }
2256 
2257     std::string navigationId = host->GetInspectorIdValue("");
2258     std::optional<NavDestinationInfo> fromInfo;
2259     std::optional<NavDestinationInfo> toInfo;
2260     BuildNavDestinationInfoFromContext(navigationId, NavDestinationState::ON_HIDDEN, from, true, fromInfo);
2261     BuildNavDestinationInfoFromContext(navigationId, NavDestinationState::ON_SHOWN, to, false, toInfo);
2262     UIObserverHandler::GetInstance().NotifyNavDestinationSwitch(
2263         std::move(fromInfo), std::move(toInfo), operation);
2264 }
2265 
StartTransition(const RefPtr<NavDestinationGroupNode> & preDestination,const RefPtr<NavDestinationGroupNode> & topDestination,bool isAnimated,bool isPopPage,bool isNeedVisible)2266 void NavigationPattern::StartTransition(const RefPtr<NavDestinationGroupNode>& preDestination,
2267     const RefPtr<NavDestinationGroupNode>& topDestination,
2268     bool isAnimated, bool isPopPage, bool isNeedVisible)
2269 {
2270     std::string fromPathInfo;
2271     std::string toPathInfo;
2272     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2273     CHECK_NULL_VOID(hostNode);
2274 
2275     if (preDestination) {
2276         fromPathInfo = preDestination->GetNavDestinationPathInfo();
2277         auto preDestinationPattern = preDestination->GetPattern<NavDestinationPattern>();
2278         CHECK_NULL_VOID(preDestinationPattern);
2279         auto navDestinationName = preDestinationPattern->GetName();
2280         fromPathInfo += ", navDesitinationName: " + navDestinationName;
2281         if ((isPopPage || preDestination->NeedRemoveInPush()) && !isAnimated) {
2282             /**
2283              * when transition without animation, 'pop' and 'push with remove' need to post
2284              * afterLayoutTask to delay old top's onDisappear. So set this flag to 'false'
2285              */
2286             preDestination->SetIsAnimated(false);
2287         }
2288     } else {
2289         fromPathInfo = hostNode->GetNavigationPathInfo();
2290     }
2291     if (topDestination) {
2292         toPathInfo = topDestination->GetNavDestinationPathInfo();
2293         auto topDestinationPattern = topDestination->GetPattern<NavDestinationPattern>();
2294         CHECK_NULL_VOID(topDestinationPattern);
2295         auto navDestinationName = topDestinationPattern->GetName();
2296         toPathInfo += ", navDesitinationName: " + navDestinationName;
2297     } else {
2298         toPathInfo = hostNode->GetNavigationPathInfo();
2299     }
2300     ACE_SCOPED_TRACE_COMMERCIAL("NavDestination Page from %s to %s", fromPathInfo.c_str(), toPathInfo.c_str());
2301 
2302     // fire onWillHide
2303     if (!isPopPage && !preDestination && navigationMode_ == NavigationMode::STACK) {
2304         // NavBar will be covered in STACK mode
2305         auto navBarNode = AceType::DynamicCast<FrameNode>(hostNode->GetNavBarNode());
2306         ProcessAutoSave(navBarNode);
2307     }
2308     if (isPopPage || (preDestination &&
2309         (hostNode->GetLastStandardIndex() > preDestination->GetIndex() || preDestination->NeedRemoveInPush()))) {
2310         NotifyDestinationLifecycle(preDestination, NavDestinationLifecycle::ON_WILL_HIDE);
2311     }
2312     hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_WILL_HIDE);
2313     auto pipeline = PipelineContext::GetCurrentContext();
2314     CHECK_NULL_VOID(pipeline);
2315     auto navigationManager = pipeline->GetNavigationManager();
2316     navigationManager->FireNavigationUpdateCallback();
2317     if (topDestination) {
2318         NotifyDialogChange(NavDestinationLifecycle::ON_WILL_SHOW, false, true);
2319     }
2320     if (!isAnimated) {
2321         FireShowAndHideLifecycle(preDestination, topDestination, isPopPage, false);
2322         TransitionWithOutAnimation(preDestination, topDestination, isPopPage, isNeedVisible);
2323         return;
2324     }
2325     pipeline->AddAfterLayoutTask([weakNavigation = WeakClaim(this),
2326         weakPreDestination = WeakPtr<NavDestinationGroupNode>(preDestination),
2327         weakTopDestination = WeakPtr<NavDestinationGroupNode>(topDestination),
2328         isPopPage, isAnimated, isNeedVisible]() {
2329         auto navigationPattern = AceType::DynamicCast<NavigationPattern>(weakNavigation.Upgrade());
2330         CHECK_NULL_VOID(navigationPattern);
2331         auto preDestination = weakPreDestination.Upgrade();
2332         auto topDestination = weakTopDestination.Upgrade();
2333         navigationPattern->FireShowAndHideLifecycle(preDestination, topDestination, isPopPage, true);
2334         navigationPattern->TransitionWithAnimation(preDestination, topDestination, isPopPage, isNeedVisible);
2335     });
2336 }
2337 
ProcessAutoSave(const RefPtr<FrameNode> & node)2338 void NavigationPattern::ProcessAutoSave(const RefPtr<FrameNode>& node)
2339 {
2340     CHECK_NULL_VOID(node);
2341     if (!node->NeedRequestAutoSave()) {
2342         return;
2343     }
2344     auto container = Container::Current();
2345     CHECK_NULL_VOID(container);
2346     container->RequestAutoSave(node);
2347 }
2348 
NotifyDestinationLifecycle(const RefPtr<UINode> & uiNode,NavDestinationLifecycle lifecycle)2349 void NavigationPattern::NotifyDestinationLifecycle(const RefPtr<UINode>& uiNode,
2350     NavDestinationLifecycle lifecycle)
2351 {
2352     auto curDestination =
2353         AceType::DynamicCast<NavDestinationGroupNode>(NavigationGroupNode::GetNavDestinationNode(uiNode));
2354     CHECK_NULL_VOID(curDestination);
2355     auto eventHub = curDestination->GetEventHub<NavDestinationEventHub>();
2356     CHECK_NULL_VOID(eventHub);
2357     if (lifecycle == NavDestinationLifecycle::ON_WILL_DISAPPEAR) {
2358         NavigationPattern::FireNavigationLifecycleChange(curDestination, lifecycle);
2359         eventHub->FireOnWillDisAppear();
2360         return;
2361     }
2362     auto navDestinationPattern = curDestination->GetPattern<NavDestinationPattern>();
2363     if ((navDestinationPattern->GetIsOnShow() && (lifecycle == NavDestinationLifecycle::ON_SHOW ||
2364             lifecycle == NavDestinationLifecycle::ON_WILL_SHOW)) ||
2365         (!navDestinationPattern->GetIsOnShow() && (lifecycle == NavDestinationLifecycle::ON_HIDE ||
2366             lifecycle == NavDestinationLifecycle::ON_WILL_HIDE))) {
2367         return;
2368     }
2369     if (lifecycle == NavDestinationLifecycle::ON_WILL_SHOW) {
2370         eventHub->FireOnWillShow();
2371         NavigationPattern::FireNavigationLifecycleChange(curDestination, lifecycle);
2372         return;
2373     }
2374     if (lifecycle == NavDestinationLifecycle::ON_SHOW) {
2375         auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2376         CHECK_NULL_VOID(navigationNode);
2377         auto parentDestinationNode = navigationNode->GetParentDestinationNode().Upgrade();
2378         if (CheckParentDestinationIsOnhide(parentDestinationNode) && CheckDestinationIsPush(parentDestinationNode)) {
2379             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "parentDestinationNode is onhide");
2380             return;
2381         }
2382         auto param = Recorder::EventRecorder::Get().IsPageParamRecordEnable() ? navigationStack_->GetRouteParam() : "";
2383         eventHub->FireOnShownEvent(navDestinationPattern->GetName(), param);
2384         NotifyPageShow(navDestinationPattern->GetName());
2385         navDestinationPattern->SetIsOnShow(true);
2386         NavigationPattern::FireNavigationLifecycleChange(curDestination, lifecycle);
2387         return;
2388     }
2389     NavigationPattern::FireNavigationLifecycleChange(curDestination, lifecycle);
2390     if (lifecycle == NavDestinationLifecycle::ON_WILL_HIDE) {
2391         eventHub->FireOnWillHide();
2392         return;
2393     }
2394     if (lifecycle == NavDestinationLifecycle::ON_HIDE) {
2395         eventHub->FireOnHiddenEvent(navDestinationPattern->GetName());
2396         NotifyPageHide(navDestinationPattern->GetName());
2397         navDestinationPattern->SetIsOnShow(false);
2398     }
2399 }
2400 
FireShowAndHideLifecycle(const RefPtr<NavDestinationGroupNode> & preDestination,const RefPtr<NavDestinationGroupNode> & topDestination,bool isPopPage,bool isAnimated)2401 void NavigationPattern::FireShowAndHideLifecycle(const RefPtr<NavDestinationGroupNode>& preDestination,
2402     const RefPtr<NavDestinationGroupNode>& topDestination, bool isPopPage, bool isAnimated)
2403 {
2404     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2405     // don't move position hide lifecycle is from top to end
2406     if (preDestination) {
2407         auto lastStandardIndex = hostNode->GetLastStandardIndex();
2408         if (isPopPage || lastStandardIndex > preDestination->GetIndex() || preDestination->NeedRemoveInPush()) {
2409             // fire preTop Destination lifecycle
2410             NotifyDestinationLifecycle(preDestination, NavDestinationLifecycle::ON_HIDE);
2411         }
2412     }
2413     // fire remove navDestination and invisible navDestination lifecycle for pop or clear
2414     hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_HIDE);
2415     if (isPopPage || (preDestination && preDestination->NeedRemoveInPush())) {
2416         // fire removed preDestination lifecycle for pop many times or clear
2417         NotifyDestinationLifecycle(preDestination, NavDestinationLifecycle::ON_WILL_DISAPPEAR);
2418     }
2419     // fire removed navDestination lifecycle
2420     hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_WILL_DISAPPEAR);
2421     if (!isAnimated) {
2422         auto pipelineContext = PipelineContext::GetCurrentContext();
2423         CHECK_NULL_VOID(pipelineContext);
2424         pipelineContext->AddAfterLayoutTask([weakNavigation = WeakClaim(this)]() {
2425             auto navigation = weakNavigation.Upgrade();
2426             CHECK_NULL_VOID(navigation);
2427             navigation->NotifyDialogChange(NavDestinationLifecycle::ON_SHOW, false, true);
2428         });
2429     } else {
2430         NotifyDialogChange(NavDestinationLifecycle::ON_SHOW, false, true);
2431     }
2432     FireInterceptionEvent(false, navigationStack_->GetTopNavPath());
2433 }
2434 
OnWindowSizeChanged(int32_t,int32_t,WindowSizeChangeReason type)2435 void NavigationPattern::OnWindowSizeChanged(int32_t  /*width*/, int32_t  /*height*/, WindowSizeChangeReason type)
2436 {
2437     if (WindowSizeChangeReason::ROTATION == type) {
2438         auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2439         CHECK_NULL_VOID(hostNode);
2440         AbortAnimation(hostNode);
2441     }
2442 }
2443 
PerformanceEventReport(int32_t nodeCount,int32_t depth,const std::string & navDestinationName)2444 void NavigationPattern::PerformanceEventReport(int32_t nodeCount, int32_t depth, const std::string& navDestinationName)
2445 {
2446     if (nodeCount >= PAGE_NODES) {
2447         EventReport::ReportPageNodeOverflow(navDestinationName, nodeCount, PAGE_NODES);
2448     }
2449     if (depth >= PAGE_DEPTH) {
2450         EventReport::ReportPageDepthOverflow(navDestinationName, depth, PAGE_DEPTH);
2451     }
2452 }
2453 
OnWindowHide()2454 void NavigationPattern::OnWindowHide()
2455 {
2456     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2457     CHECK_NULL_VOID(hostNode);
2458     auto navigationPattern = hostNode->GetPattern<NavigationPattern>();
2459     CHECK_NULL_VOID(navigationPattern);
2460     navigationPattern->SyncWithJsStackIfNeeded();
2461 }
2462 
NotifyPerfMonitorPageMsg(const std::string & pageName)2463 void NavigationPattern::NotifyPerfMonitorPageMsg(const std::string& pageName)
2464 {
2465     auto container = Container::Current();
2466     if (container != nullptr && PerfMonitor::GetPerfMonitor() != nullptr) {
2467         std::string bundleName = container->GetBundleName();
2468         PerfMonitor::GetPerfMonitor()->ReportPageShowMsg("", bundleName, pageName);
2469     }
2470 }
2471 
RefreshFocusToDestination()2472 void NavigationPattern::RefreshFocusToDestination()
2473 {
2474     auto newTopNavPath = navigationStack_->GetTopNavPath();
2475     if (!newTopNavPath.has_value()) {
2476         return;
2477     }
2478     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2479     CHECK_NULL_VOID(hostNode);
2480     auto navBarNode = AceType::DynamicCast<FrameNode>(hostNode->GetNavBarNode());
2481     CHECK_NULL_VOID(navBarNode);
2482     auto navBarFocus = navBarNode->GetFocusHub();
2483     CHECK_NULL_VOID(navBarFocus);
2484     if (!navBarFocus->IsCurrentFocus()) {
2485         return;
2486     }
2487     auto newTopNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(
2488         NavigationGroupNode::GetNavDestinationNode(newTopNavPath->second));
2489     CHECK_NULL_VOID(newTopNavDestination);
2490     if (!GetIsFocusable(newTopNavDestination)) {
2491         return;
2492     }
2493     auto navDestinationFocusView = newTopNavDestination->GetPattern<FocusView>();
2494     CHECK_NULL_VOID(navDestinationFocusView);
2495     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TWELVE)) {
2496         navDestinationFocusView->SetIsViewRootScopeFocused(false);
2497     }
2498     navDestinationFocusView->FocusViewShow();
2499 }
2500 
RecoveryToLastStack(const RefPtr<NavDestinationGroupNode> & preTopDestination,const RefPtr<NavDestinationGroupNode> & newTopDestination)2501 void NavigationPattern::RecoveryToLastStack(
2502     const RefPtr<NavDestinationGroupNode>& preTopDestination,
2503     const RefPtr<NavDestinationGroupNode>& newTopDestination)
2504 {
2505     if (preTopDestination) {
2506         preTopDestination->SetIsOnAnimation(false);
2507     }
2508     if (newTopDestination) {
2509         newTopDestination->SetIsOnAnimation(false);
2510     }
2511     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2512     CHECK_NULL_VOID(hostNode);
2513     hostNode->CleanHideNodes();
2514     CHECK_NULL_VOID(navigationStack_);
2515     navigationStack_->SetNavPathList(navigationStack_->GetRecoveryList());
2516 
2517     // update cached node
2518     auto destinationNodes = navigationStack_->GetAllNavDestinationNodes();
2519     for (uint32_t index = 0; index < destinationNodes.size(); index++) {
2520         auto childNode = destinationNodes[index];
2521         if (!childNode.second) {
2522             continue;
2523         }
2524         auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(
2525             NavigationGroupNode::GetNavDestinationNode(childNode.second));
2526         if (!navDestinationNode) {
2527             continue;
2528         }
2529         // update pre cache node to cache node list
2530         auto cacheNode = navigationStack_->GetFromCacheNode(childNode.first);
2531         if (cacheNode && cacheNode == childNode.second) {
2532             navigationStack_->AddCacheNode(childNode.first, childNode.second);
2533         }
2534     }
2535     hostNode->UpdateNavDestinationNodeWithoutMarkDirty(nullptr, navigationModeChange_);
2536 
2537     // recover lifecycle state before transition
2538     hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_HIDE);
2539     hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_WILL_DISAPPEAR);
2540     NotifyDialogChange(NavDestinationLifecycle::ON_SHOW, true, true);
2541     hostNode->RemoveDialogDestination();
2542     hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
2543 
2544     // update name index
2545     navigationStack_->RecoveryNavigationStack();
2546     ACE_SCOPED_TRACE_COMMERCIAL("Navigation page transition end");
2547     PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH, true);
2548     hostNode->SetIsOnAnimation(false);
2549     auto id = hostNode->GetTopDestination() ? hostNode->GetTopDestination()->GetAccessibilityId() : -1;
2550     hostNode->OnAccessibilityEvent(
2551         AccessibilityEventType::PAGE_CHANGE, id, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID);
2552 }
2553 
ExecuteAddAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage,const RefPtr<NavigationTransitionProxy> & proxy,NavigationTransition navigationTransition)2554 bool NavigationPattern::ExecuteAddAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
2555     const RefPtr<NavDestinationGroupNode>& newTopNavDestination,
2556     bool isPopPage, const RefPtr<NavigationTransitionProxy>& proxy,
2557     NavigationTransition navigationTransition)
2558 {
2559     // custom animation return undefined,finish this transition
2560     if (!navigationTransition.isValid) {
2561         proxy->SetIsSuccess(false);
2562         proxy->SetIsFinished(true);
2563         return false;
2564     }
2565     if (preTopNavDestination) {
2566         preTopNavDestination->SetIsOnAnimation(true);
2567     }
2568     if (newTopNavDestination) {
2569         newTopNavDestination->SetIsOnAnimation(true);
2570     }
2571     auto proxyId = proxy->GetProxyId();
2572     proxy->SetInteractive(navigationTransition.interactive);
2573     // set on transition end callback
2574     proxy->SetEndCallback(std::move(navigationTransition.endCallback));
2575     proxy->SetFinishTransitionEvent([weakNavigation = WeakClaim(this),
2576                                         weakPreNavDestination = WeakPtr<NavDestinationGroupNode>(preTopNavDestination),
2577                                         weakNewNavDestination = WeakPtr<NavDestinationGroupNode>(newTopNavDestination),
2578                                         isPopPage, proxyId]() {
2579         auto pattern = weakNavigation.Upgrade();
2580         CHECK_NULL_VOID(pattern);
2581         auto proxy = pattern->GetProxyById(proxyId);
2582         auto preDestination = weakPreNavDestination.Upgrade();
2583         auto topDestination = weakNewNavDestination.Upgrade();
2584         // disable render group for text node after the custom animation
2585         if (isPopPage && preDestination) {
2586             preDestination->ReleaseTextNodeList();
2587         }
2588         if (!isPopPage && topDestination) {
2589             topDestination->ReleaseTextNodeList();
2590         }
2591 
2592         // to avoid call finishTransition many times
2593         if (proxy == nullptr) {
2594             TAG_LOGW(AceLogTag::ACE_NAVIGATION, "custom animation proxy is empty or is finished");
2595             return;
2596         }
2597         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "custom animation finish end");
2598         proxy->SetIsFinished(true);
2599         // update pre navigation stack
2600         ACE_SCOPED_TRACE_COMMERCIAL("navigation page custom transition end");
2601         PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH, true);
2602         pattern->GetNavigationStack()->ClearRecoveryList();
2603         pattern->OnCustomAnimationFinish(preDestination, topDestination, isPopPage);
2604         pattern->RemoveProxyById(proxyId);
2605     });
2606     // add timeout callback
2607     auto timeout = navigationTransition.timeout;
2608     auto pipeline = GetHost()->GetContext();
2609     CHECK_NULL_RETURN(pipeline, false);
2610     auto taskExecutor = pipeline->GetTaskExecutor();
2611     CHECK_NULL_RETURN(taskExecutor, false);
2612     if (timeout < 0) {
2613         return true;
2614     }
2615     // deal timeout callback
2616     taskExecutor->PostDelayedTask(
2617         [weakProxy = WeakPtr<NavigationTransitionProxy>(proxy)] {
2618             auto transitionProxy = weakProxy.Upgrade();
2619             CHECK_NULL_VOID(transitionProxy);
2620             transitionProxy->FireFinishCallback();
2621         },
2622         TaskExecutor::TaskType::UI, timeout, "ArkUINavigationTransitionProxyFinish");
2623     return true;
2624 }
2625 
GetIsFocusable(const RefPtr<FrameNode> & frameNode)2626 bool NavigationPattern::GetIsFocusable(const RefPtr<FrameNode>& frameNode)
2627 {
2628     CHECK_NULL_RETURN(frameNode, false);
2629     auto hostNode = AceType::DynamicCast<FrameNode>(GetHost());
2630     CHECK_NULL_RETURN(hostNode, false);
2631     auto focusHub = hostNode->GetFocusHub();
2632     CHECK_NULL_RETURN(focusHub, false);
2633     if (!focusHub->IsFocusableWholePath()) {
2634         return false;
2635     }
2636     auto currentFocusHub = frameNode->GetFocusHub();
2637     CHECK_NULL_RETURN(currentFocusHub, false);
2638     return currentFocusHub->IsFocusableNode();
2639 }
2640 
IsLastStdChange()2641 bool NavigationPattern::IsLastStdChange()
2642 {
2643     // check whether last std navdestination id is changed, change return true, not change return false
2644     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2645     CHECK_NULL_RETURN(navigationNode, false);
2646     auto& navPathList = navigationStack_->GetAllNavDestinationNodes();
2647     auto& preNavPathList = navigationStack_->GetAllNavDestinationNodesPrev();
2648     auto lastStdIndex = navigationNode->GetLastStandardIndex();
2649     auto preLastStdIndex = navigationNode->GetPreLastStandardIndex();
2650     if (preLastStdIndex == -1 && lastStdIndex == -1) {
2651         return false;
2652     }
2653     if (preLastStdIndex != -1 && lastStdIndex != -1) {
2654         // check new and pre std navdestination id changed or not
2655         auto preStd = NavigationGroupNode::GetNavDestinationNode(preNavPathList[preLastStdIndex].second.Upgrade());
2656         auto newStd = NavigationGroupNode::GetNavDestinationNode(navPathList[lastStdIndex].second);
2657         if (preStd && newStd) {
2658             return preStd != newStd;
2659         }
2660     }
2661     return true;
2662 }
2663 
FollowStdNavdestinationAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage)2664 void NavigationPattern::FollowStdNavdestinationAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
2665     const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage)
2666 {
2667     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2668     CHECK_NULL_VOID(navigationNode);
2669     if (preTopNavDestination && newTopNavDestination) {
2670         if (isPopPage) {
2671             navigationNode->TransitionWithDialogPop(preTopNavDestination, newTopNavDestination);
2672         } else {
2673             navigationNode->TransitionWithDialogPush(preTopNavDestination, newTopNavDestination);
2674         }
2675         return;
2676     }
2677     if (newTopNavDestination && navigationMode_ == NavigationMode::STACK) {
2678         auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationNode->GetNavBarNode());
2679         CHECK_NULL_VOID(navBarNode);
2680         navigationNode->TransitionWithDialogPush(navBarNode, newTopNavDestination, true);
2681         return;
2682     }
2683     if (preTopNavDestination) {
2684         if (navigationMode_ == NavigationMode::SPLIT) {
2685             navigationNode->TransitionWithDialogPop(preTopNavDestination, nullptr);
2686         }
2687         if (navigationMode_ == NavigationMode::STACK) {
2688             auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationNode->GetNavBarNode());
2689             CHECK_NULL_VOID(navBarNode);
2690             navigationNode->TransitionWithDialogPop(preTopNavDestination, navBarNode, true);
2691         }
2692     }
2693 }
2694 
TransitionWithDialogAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage)2695 void NavigationPattern::TransitionWithDialogAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
2696     const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage)
2697 {
2698     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2699     CHECK_NULL_VOID(navigationNode);
2700 
2701     // if last standard id is not changed and new top navdestination is standard
2702     if (!isPopPage && !IsLastStdChange() && newTopNavDestination &&
2703         newTopNavDestination->GetNavDestinationMode() == NavDestinationMode::STANDARD) {
2704         return;
2705     }
2706     auto replaceVal = navigationStack_->GetReplaceValue();
2707     if (replaceVal != 0) {
2708         ReplaceAnimation(preTopNavDestination, newTopNavDestination);
2709         return;
2710     }
2711     // last std id is not change, but new dialogs came into stack and upward animation
2712     if (!IsLastStdChange()) {
2713         if (isPopPage) {
2714             navigationNode->StartDialogtransition(preTopNavDestination, newTopNavDestination, false);
2715         } else {
2716             if (!preTopNavDestination && navigationMode_ == NavigationMode::SPLIT) {
2717                 // if split mode and push one dialog at the first time, no animation
2718                 return;
2719             }
2720             navigationNode->StartDialogtransition(preTopNavDestination, newTopNavDestination, true);
2721         }
2722         return;
2723     }
2724     FollowStdNavdestinationAnimation(preTopNavDestination, newTopNavDestination, isPopPage);
2725 }
2726 
GetProxyById(uint64_t id) const2727 RefPtr<NavigationTransitionProxy> NavigationPattern::GetProxyById(uint64_t id) const
2728 {
2729     for (auto proxy : proxyList_) {
2730         if (proxy && proxy->GetProxyId() == id) {
2731             return proxy;
2732         }
2733     }
2734     return nullptr;
2735 }
2736 
RemoveProxyById(uint64_t id)2737 void NavigationPattern::RemoveProxyById(uint64_t id)
2738 {
2739     for (auto it = proxyList_.begin(); it != proxyList_.end(); ++it) {
2740         if (*it && (*it)->GetProxyId() == id) {
2741             it = proxyList_.erase(it);
2742             return;
2743         }
2744     }
2745 }
2746 
CheckContentNeedMeasure(const RefPtr<FrameNode> & node)2747 void NavigationPattern::CheckContentNeedMeasure(const RefPtr<FrameNode>& node)
2748 {
2749     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(node);
2750     CHECK_NULL_VOID(navigationNode);
2751     auto navigationLayoutProperty = navigationNode->GetLayoutProperty<NavigationLayoutProperty>();
2752     CHECK_NULL_VOID(navigationLayoutProperty);
2753     if (!NavigationLayoutAlgorithm::IsAutoHeight(navigationLayoutProperty)) {
2754         return;
2755     }
2756     TAG_LOGI(AceLogTag::ACE_NAVIGATION, "Navigation height is auto, content need to measure after pushAnimation ends");
2757     auto contentNode = navigationNode->GetContentNode();
2758     CHECK_NULL_VOID(contentNode);
2759     contentNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
2760 }
2761 } // namespace OHOS::Ace::NG
2762