• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2024 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_group_node.h"
17 
18 #include "base/log/ace_checker.h"
19 #include "base/log/ace_performance_check.h"
20 #include "base/memory/ace_type.h"
21 #include "base/memory/referenced.h"
22 #include "base/perfmonitor/perf_constants.h"
23 #include "base/perfmonitor/perf_monitor.h"
24 #include "base/utils/utils.h"
25 #include "core/animation/page_transition_common.h"
26 #include "core/common/container.h"
27 #include "core/components/common/layout/constants.h"
28 #include "core/components/theme/app_theme.h"
29 
30 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
31 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
32 #endif
33 
34 #if !defined(ACE_UNITTEST)
35 #include "core/components_ng/base/transparent_node_detector.h"
36 #endif
37 
38 #include "core/components_ng/base/view_stack_processor.h"
39 #include "core/components_ng/event/focus_hub.h"
40 #include "core/components_ng/pattern/button/button_layout_property.h"
41 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
42 #include "core/components_ng/pattern/navigation/nav_bar_node.h"
43 #include "core/components_ng/pattern/navigation/nav_bar_layout_property.h"
44 #include "core/components_ng/pattern/navigation/navigation_declaration.h"
45 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
46 #include "core/components_ng/pattern/navigation/navigation_title_util.h"
47 #include "core/components_ng/pattern/navigation/title_bar_layout_property.h"
48 #include "core/components_ng/pattern/navrouter/navdestination_event_hub.h"
49 #include "core/components_ng/pattern/navrouter/navdestination_group_node.h"
50 #include "core/components_ng/pattern/navrouter/navdestination_layout_property.h"
51 #include "core/components_ng/pattern/navrouter/navdestination_pattern.h"
52 #include "core/components_ng/pattern/navrouter/navrouter_event_hub.h"
53 #include "core/components_ng/pattern/navrouter/navrouter_group_node.h"
54 #include "core/components_ng/pattern/stack/stack_layout_property.h"
55 #include "core/components_ng/pattern/stack/stack_model_ng.h"
56 #include "core/components_ng/pattern/stack/stack_pattern.h"
57 #include "core/components_ng/pattern/stage/page_pattern.h"
58 #include "core/components_ng/property/measure_property.h"
59 #include "core/components_ng/property/property.h"
60 #include "core/components_ng/render/render_context.h"
61 #include "core/components_v2/inspector/inspector_constants.h"
62 
63 namespace OHOS::Ace::NG {
64 namespace {
65 constexpr double HALF = 0.5;
66 constexpr double PARENT_PAGE_OFFSET = 0.2;
67 constexpr double PARENT_TITLE_OFFSET = 0.02;
68 constexpr float REMOVE_CLIP_SIZE = 10000.0f;
69 constexpr int32_t MASK_DURATION = 350;
70 constexpr int32_t OPACITY_TITLE_OUT_DELAY = 17;
71 constexpr int32_t OPACITY_TITLE_IN_DELAY = 33;
72 constexpr int32_t OPACITY_TITLE_DURATION = 150;
73 constexpr int32_t OPACITY_BACKBUTTON_IN_DELAY = 150;
74 constexpr int32_t OPACITY_BACKBUTTON_IN_DURATION = 200;
75 constexpr int32_t OPACITY_BACKBUTTON_OUT_DURATION = 67;
76 constexpr int32_t DEFAULT_ANIMATION_DURATION = 450;
77 constexpr int32_t DEFAULT_REPLACE_DURATION = 150;
78 const Color MASK_COLOR = Color::FromARGB(25, 0, 0, 0);
79 const RefPtr<InterpolatingSpring> springCurve = AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 342.0f, 37.0f);
80 const RefPtr<CubicCurve> replaceCurve = AceType::MakeRefPtr<CubicCurve>(0.33, 0.0, 0.67, 1.0);
81 } // namespace
82 class InspectorFilter;
83 
GetOrCreateGroupNode(const std::string & tag,int32_t nodeId,const std::function<RefPtr<Pattern> (void)> & patternCreator)84 RefPtr<NavigationGroupNode> NavigationGroupNode::GetOrCreateGroupNode(
85     const std::string& tag, int32_t nodeId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
86 {
87     auto frameNode = GetFrameNode(tag, nodeId);
88     CHECK_NULL_RETURN(!frameNode, AceType::DynamicCast<NavigationGroupNode>(frameNode));
89     auto pattern = patternCreator ? patternCreator() : MakeRefPtr<Pattern>();
90     auto navigationGroupNode = AceType::MakeRefPtr<NavigationGroupNode>(tag, nodeId, pattern);
91     navigationGroupNode->InitializePatternAndContext();
92     ElementRegister::GetInstance()->AddUINode(navigationGroupNode);
93     return navigationGroupNode;
94 }
95 
~NavigationGroupNode()96 NavigationGroupNode::~NavigationGroupNode()
97 {
98     auto navigationPattern = GetPattern<NavigationPattern>();
99     const auto& navDestinationNodes = navigationPattern->GetAllNavDestinationNodes();
100     for (auto iter : navDestinationNodes) {
101         auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(GetNavDestinationNode(iter.second));
102         if (navDestinationNode) {
103             navDestinationNode->GetPattern<NavDestinationPattern>()->SetCustomNode(nullptr);
104         }
105     }
106     auto context = PipelineContext::GetCurrentContext();
107     CHECK_NULL_VOID(context);
108     auto stageManager = context->GetStageManager();
109     CHECK_NULL_VOID(stageManager);
110     RefPtr<FrameNode> pageNode = stageManager->GetLastPage();
111     CHECK_NULL_VOID(pageNode);
112     auto pagePattern = pageNode->GetPattern<PagePattern>();
113     CHECK_NULL_VOID(pagePattern);
114     CHECK_NULL_VOID(pagePattern->GetPageInfo());
115     int32_t pageId = pagePattern->GetPageInfo()->GetPageId();
116     context->RemoveNavigationNode(pageId, GetId());
117     context->DeleteNavigationNode(curId_);
118 }
119 
AddChildToGroup(const RefPtr<UINode> & child,int32_t slot)120 void NavigationGroupNode::AddChildToGroup(const RefPtr<UINode>& child, int32_t slot)
121 {
122     auto pattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
123     CHECK_NULL_VOID(pattern);
124     auto navBar = AceType::DynamicCast<NavBarNode>(GetNavBarNode());
125     CHECK_NULL_VOID(navBar);
126     auto contentNode = navBar->GetContentNode();
127     if (!contentNode) {
128         auto nodeId = ElementRegister::GetInstance()->MakeUniqueId();
129         contentNode = FrameNode::GetOrCreateFrameNode(
130             V2::NAVBAR_CONTENT_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(true); });
131         navBar->SetContentNode(contentNode);
132         navBar->AddChild(contentNode);
133 
134         if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
135             auto navBarContentNode = AceType::DynamicCast<FrameNode>(contentNode);
136             SafeAreaExpandOpts opts = { .type = SAFE_AREA_TYPE_SYSTEM | SAFE_AREA_TYPE_CUTOUT,
137                 .edges = SAFE_AREA_EDGE_ALL };
138             navBarContentNode->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
139         }
140     }
141     contentNode->AddChild(child);
142 }
143 
UpdateNavDestinationNodeWithoutMarkDirty(const RefPtr<UINode> & remainChild,bool modeChange)144 void NavigationGroupNode::UpdateNavDestinationNodeWithoutMarkDirty(const RefPtr<UINode>& remainChild, bool modeChange)
145 {
146     auto pattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
147     CHECK_NULL_VOID(pattern);
148     const auto& navDestinationNodes = pattern->GetAllNavDestinationNodes();
149 
150     auto navigationContentNode = AceType::DynamicCast<FrameNode>(GetContentNode());
151     CHECK_NULL_VOID(navigationContentNode);
152     bool hasChanged = false;
153     int32_t slot = 0;
154     int32_t beforeLastStandardIndex = lastStandardIndex_;
155     auto preLastStandardNode = AceType::DynamicCast<NavDestinationGroupNode>(
156         navigationContentNode->GetChildAtIndex(beforeLastStandardIndex));
157 
158     // save preLastStandardIndex_ before update and check whether standard page changed
159     preLastStandardIndex_ = lastStandardIndex_;
160     UpdateLastStandardIndex();
161 
162     TAG_LOGI(AceLogTag::ACE_NAVIGATION, "last standard page index is %{public}d", lastStandardIndex_);
163     if (!ReorderNavDestination(navDestinationNodes, navigationContentNode, slot, hasChanged)) {
164         return;
165     }
166 
167     for (uint32_t index = 0; index < navDestinationNodes.size(); index++) {
168         const auto& childNode = navDestinationNodes[index];
169         const auto& uiNode = childNode.second;
170         auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(GetNavDestinationNode(uiNode));
171         hasChanged = (UpdateNavDestinationVisibility(navDestination, remainChild, index,
172             navDestinationNodes.size(), preLastStandardNode) || hasChanged);
173     }
174 
175     RemoveRedundantNavDestination(
176         navigationContentNode, remainChild, static_cast<int32_t>(slot), hasChanged, preLastStandardNode);
177     if (modeChange) {
178         navigationContentNode->GetLayoutProperty()->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
179     } else if (hasChanged) {
180         navigationContentNode->GetLayoutProperty()->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
181     }
182 }
183 
ReorderNavDestination(const std::vector<std::pair<std::string,RefPtr<UINode>>> & navDestinationNodes,RefPtr<FrameNode> & navigationContentNode,int32_t & slot,bool & hasChanged)184 bool NavigationGroupNode::ReorderNavDestination(
185     const std::vector<std::pair<std::string, RefPtr<UINode>>>& navDestinationNodes,
186     RefPtr<FrameNode>& navigationContentNode, int32_t& slot, bool& hasChanged)
187 {
188     auto pattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
189     CHECK_NULL_RETURN(pattern, false);
190     for (uint32_t i = 0; i != navDestinationNodes.size(); ++i) {
191         const auto& childNode = navDestinationNodes[i];
192         const auto& uiNode = childNode.second;
193         auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(GetNavDestinationNode(uiNode));
194         if (navDestination == nullptr) {
195             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "get destination node failed");
196             return false;
197         }
198         auto navDestinationPattern = navDestination->GetPattern<NavDestinationPattern>();
199         CHECK_NULL_RETURN(navDestinationPattern, false);
200         navDestinationPattern->SetName(childNode.first);
201         navDestinationPattern->SetCustomNode(uiNode);
202         navDestinationPattern->SetIndex(static_cast<int32_t>(i));
203         SetBackButtonEvent(navDestination);
204         navDestination->SetIndex(i);
205         auto eventHub = navDestination->GetEventHub<NavDestinationEventHub>();
206         CHECK_NULL_RETURN(eventHub, false);
207         if (!eventHub->GetOnStateChange()) {
208             auto onStateChangeMap = pattern->GetOnStateChangeMap();
209             auto iter = onStateChangeMap.find(uiNode->GetId());
210             if (iter != onStateChangeMap.end()) {
211                 eventHub->SetOnStateChange(iter->second);
212                 pattern->DeleteOnStateChangeItem(iter->first);
213             }
214         }
215         int32_t childIndex = navigationContentNode->GetChildIndex(navDestination);
216         if (childIndex < 0) {
217             navDestination->MountToParent(navigationContentNode, slot);
218             hasChanged = true;
219         } else if (childIndex != slot) {
220             navDestination->MovePosition(slot);
221             hasChanged = true;
222         }
223         slot++;
224     }
225     return true;
226 }
227 
RemoveRedundantNavDestination(RefPtr<FrameNode> & navigationContentNode,const RefPtr<UINode> & remainChild,int32_t slot,bool & hasChanged,const RefPtr<NavDestinationGroupNode> & preLastStandardNode)228 void NavigationGroupNode::RemoveRedundantNavDestination(RefPtr<FrameNode>& navigationContentNode,
229     const RefPtr<UINode>& remainChild, int32_t slot, bool& hasChanged,
230     const RefPtr<NavDestinationGroupNode>& preLastStandardNode)
231 {
232     auto pattern = GetPattern<NavigationPattern>();
233     RefPtr<UINode> maxAnimatingDestination = nullptr;
234     RefPtr<UINode> remainDestination = GetNavDestinationNode(remainChild);
235     RefPtr<UINode> curTopDestination = navigationContentNode->GetChildAtIndex(slot - 1);
236     // record remove destination size
237     int32_t removeSize = 0;
238     bool hideNodesFinish = false;
239     // record animating destination size
240     int32_t animatingSize = 0;
241     int32_t remainNodeIndex = -1;
242     int32_t beforeLastStandardIndex = preLastStandardNode == nullptr ? -1 : preLastStandardNode->GetIndex();
243     while (slot + removeSize + animatingSize < static_cast<int32_t>(navigationContentNode->GetChildren().size())) {
244         // delete useless nodes that are not at the top
245         int32_t candidateIndex = static_cast<int32_t>(navigationContentNode->GetChildren().size()) - 1 - animatingSize;
246         auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(
247             navigationContentNode->GetChildAtIndex(candidateIndex));
248         if (!navDestination) {
249             navigationContentNode->RemoveChildAtIndex(candidateIndex);
250             hasChanged = true;
251             continue;
252         }
253         auto eventHub = navDestination->GetEventHub<NavDestinationEventHub>();
254         if (eventHub) {
255             eventHub->FireChangeEvent(false);
256         }
257         if (navDestination == remainDestination) {
258             if (pattern->IsCurTopNewInstance()) {
259                 // remain the last child for push animation, and this child
260                 // will be remove in push's animation finish callback
261                 navDestination->SetNeedRemoveInPush(true);
262                 remainNodeIndex = slot - 1;
263                 navDestination->MovePosition(remainNodeIndex);
264             } else {
265                 // remain the last child for pop animation
266                 remainNodeIndex = slot;
267                 navDestination->MovePosition(slot);
268             }
269             ++slot;
270             continue;
271         }
272         // The NavDestination in the EXIT animation needs to be cleaned in the animation onfinish callback.
273         if (navDestination->IsOnAnimation()) {
274             if (navDestination->GetTransitionType() == PageTransitionType::EXIT_POP) {
275                 ++animatingSize;
276                 continue;
277             }
278             if (navDestination->NeedRemoveInPush()) {
279                 if (maxAnimatingDestination == nullptr) {
280                     maxAnimatingDestination = navDestination;
281                 }
282                 ++animatingSize;
283                 continue;
284             }
285         }
286         // remove content child
287         auto navDestinationPattern = navDestination->GetPattern<NavDestinationPattern>();
288         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "remove child: %{public}s", navDestinationPattern->GetName().c_str());
289         if (navDestination->GetIndex() >= beforeLastStandardIndex && !hideNodesFinish) {
290             if (navDestination->GetNavDestinationMode() == NavDestinationMode::STANDARD
291                 && preLastStandardNode != navDestination) {
292                 hideNodesFinish = true;
293                 DealRemoveDestination(navDestination);
294                 hasChanged = true;
295                 continue;
296             }
297             hideNodes_.emplace_back(std::make_pair(navDestination, true));
298             navDestination->SetCanReused(false);
299             removeSize++;
300             auto index = slot + removeSize - 1;
301             // move current destination position to navigation stack size + remove navDestination nodes
302             if (index >= 0) {
303                 navDestination->MovePosition(remainNodeIndex);
304             }
305             continue;
306         }
307         DealRemoveDestination(navDestination);
308         hasChanged = true;
309     }
310     if (pattern->IsCurTopNewInstance()) {
311         ReorderAnimatingDestination(
312             navigationContentNode, maxAnimatingDestination, remainDestination, curTopDestination);
313     }
314 }
315 
ReorderAnimatingDestination(RefPtr<FrameNode> & navigationContentNode,RefPtr<UINode> & maxAnimatingDestination,RefPtr<UINode> & remainDestination,RefPtr<UINode> & curTopDestination)316 void NavigationGroupNode::ReorderAnimatingDestination(RefPtr<FrameNode>& navigationContentNode,
317     RefPtr<UINode>& maxAnimatingDestination, RefPtr<UINode>& remainDestination, RefPtr<UINode>& curTopDestination)
318 {
319     auto maxAnimatingIndex = navigationContentNode->GetChildIndex(maxAnimatingDestination);
320     if (maxAnimatingIndex != -1 && remainDestination) {
321         remainDestination->MovePosition(maxAnimatingIndex + 1);
322     }
323     auto remainIndex = navigationContentNode->GetChildIndex(remainDestination);
324     if (remainIndex != -1 && curTopDestination) {
325         curTopDestination->MovePosition(remainIndex + 1);
326     }
327 }
328 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const329 void NavigationGroupNode::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
330 {
331     FrameNode::ToJsonValue(json, filter);
332     auto navBarNode = AceType::DynamicCast<NavBarNode>(GetNavBarNode());
333     CHECK_NULL_VOID(navBarNode);
334     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navBarNode->GetTitleBarNode());
335     if (titleBarNode) {
336         std::string title = NavigationTitleUtil::GetTitleString(titleBarNode,
337             navBarNode->GetPrevTitleIsCustomValue(false));
338         std::string subtitle = NavigationTitleUtil::GetSubtitleString(titleBarNode);
339         json->PutExtAttr("title", title.c_str(), filter);
340         json->PutExtAttr("subtitle", subtitle.c_str(), filter);
341     }
342     json->PutExtAttr("menus", navBarNode->GetBarItemsString(true).c_str(), filter);
343     json->PutExtAttr("toolBar", navBarNode->GetBarItemsString(false).c_str(), filter);
344     auto navBarLayoutProperty = navBarNode->GetLayoutProperty<NavBarLayoutProperty>();
345     CHECK_NULL_VOID(navBarLayoutProperty);
346     json->PutExtAttr("titleMode", navBarLayoutProperty->GetTitleModeString().c_str(), filter);
347     json->PutExtAttr("hideBackButton", navBarLayoutProperty->GetHideBackButtonValue(false), filter);
348     json->PutExtAttr("hideTitleBar", navBarLayoutProperty->GetHideTitleBarValue(false), filter);
349     json->PutExtAttr("hideToolBar", navBarLayoutProperty->GetHideToolBarValue(false), filter);
350 }
351 
GetNavDestinationNode(RefPtr<UINode> uiNode)352 RefPtr<UINode> NavigationGroupNode::GetNavDestinationNode(RefPtr<UINode> uiNode)
353 {
354     if (!uiNode) {
355         return nullptr;
356     }
357     // create NavDestinationNode from uiNode stored in NavigationStack
358     while (uiNode) {
359         if (uiNode->GetTag() == V2::NAVDESTINATION_VIEW_ETS_TAG) {
360             // this is a navDestination node
361             return uiNode;
362         }
363         if (AceType::DynamicCast<UINode>(uiNode)) {
364             // this is an UINode, go deep further for navDestination node
365             auto children = uiNode->GetChildren();
366             uiNode = children.front();
367             continue;
368         }
369     }
370     CHECK_NULL_RETURN(uiNode, nullptr);
371     TAG_LOGI(AceLogTag::ACE_NAVIGATION, "get navDestination node failed: id: %{public}d, %{public}s",
372         uiNode->GetId(), uiNode->GetTag().c_str());
373     return nullptr;
374 }
375 
SetBackButtonEvent(const RefPtr<NavDestinationGroupNode> & navDestination)376 void NavigationGroupNode::SetBackButtonEvent(const RefPtr<NavDestinationGroupNode>& navDestination)
377 {
378     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navDestination->GetTitleBarNode());
379     CHECK_NULL_VOID(titleBarNode);
380     auto backButtonNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetBackButton());
381     CHECK_NULL_VOID(backButtonNode);
382     auto backButtonEventHub = backButtonNode->GetEventHub<EventHub>();
383     CHECK_NULL_VOID(backButtonEventHub);
384     auto onBackButtonEvent = [navDestinationWeak = WeakPtr<NavDestinationGroupNode>(navDestination),
385                                  navigationWeak = WeakClaim(this)](GestureEvent& /*info*/) -> bool {
386         auto navDestination = navDestinationWeak.Upgrade();
387         TAG_LOGD(AceLogTag::ACE_NAVIGATION, "click navigation back button");
388         CHECK_NULL_RETURN(navDestination, false);
389         auto eventHub = navDestination->GetEventHub<NavDestinationEventHub>();
390         CHECK_NULL_RETURN(eventHub, false);
391         eventHub->SetState(NavDestinationState::ON_BACKPRESS);
392         auto navdestinationPattern = navDestination->GetPattern<NavDestinationPattern>();
393         UIObserverHandler::GetInstance().NotifyNavigationStateChange(
394             navdestinationPattern, NavDestinationState::ON_BACKPRESS);
395         auto isOverride = eventHub->GetOnBackPressedEvent();
396         auto result = false;
397         if (isOverride) {
398             result = eventHub->FireOnBackPressedEvent();
399         }
400         if (result) {
401             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation user onBackPress return true");
402             return true;
403         }
404         auto navigation = navigationWeak.Upgrade();
405         CHECK_NULL_RETURN(navigation, false);
406         // if set hideNavBar and stack size is one, return false
407         auto navigationLayoutProperty = AceType::DynamicCast<NavigationLayoutProperty>(navigation->GetLayoutProperty());
408         auto pattern = AceType::DynamicCast<NavigationPattern>(navigation->GetPattern());
409         auto stack = pattern->GetNavigationStack();
410         CHECK_NULL_RETURN(stack, false);
411         if (navigationLayoutProperty->GetHideNavBarValue(false) && stack->Size() <= 1) {
412             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "set hideNavBar and stack size is no more than one");
413             return false;
414         }
415         auto isLastChild = stack->Size() == 1;
416         if (isOverride) {
417             result = navigation->HandleBack(navDestination, isLastChild, true);
418         } else {
419             result = navigation->HandleBack(navDestination, isLastChild, false);
420         }
421         // when js navigationStack is provided, modifyDone will be called by state manager.
422         auto navigationPattern = navigation->GetPattern<NavigationPattern>();
423         CHECK_NULL_RETURN(navigationPattern, false);
424         if (!navigationPattern->GetNavigationStackProvided()) {
425             navigation->MarkModifyDone();
426             navigation->MarkDirtyNode();
427         }
428 
429         return result;
430     }; // backButton event
431 
432     navDestination->SetNavDestinationBackButtonEvent(onBackButtonEvent);
433     backButtonEventHub->GetOrCreateGestureEventHub()->SetUserOnClick(onBackButtonEvent);
434 }
435 
GetTopDestination()436 RefPtr<FrameNode> NavigationGroupNode::GetTopDestination()
437 {
438     auto pattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
439     CHECK_NULL_RETURN(pattern, nullptr);
440     auto navigationStack = pattern->GetNavigationStack();
441     CHECK_NULL_RETURN(navigationStack, nullptr);
442     auto topNavdestination = AceType::DynamicCast<FrameNode>(GetNavDestinationNode(navigationStack->Get()));
443     return topNavdestination;
444 }
445 
CheckCanHandleBack(bool & isEntry)446 bool NavigationGroupNode::CheckCanHandleBack(bool& isEntry)
447 {
448     auto navigation = AceType::WeakClaim(this).Upgrade();
449     CHECK_NULL_RETURN(navigation, false);
450     auto navigationPattern = GetPattern<NavigationPattern>();
451     CHECK_NULL_RETURN(navigationPattern, false);
452 
453     auto navigationStack = navigationPattern->GetNavigationStack();
454     CHECK_NULL_RETURN(navigationStack, false);
455     auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(
456         NavigationGroupNode::GetNavDestinationNode(navigationStack->Get()));
457     if (!navDestination) {
458         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "can't find destination node to process back press");
459         return false;
460     }
461     if (!navigationPattern->IsFinishInteractiveAnimation()) {
462         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "can't handle back press during interactive animation");
463         return true;
464     }
465     auto navDestinationPattern = AceType::DynamicCast<NavDestinationPattern>(navDestination->GetPattern());
466     if (navDestinationPattern->OverlayOnBackPressed()) {
467         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navDestination's ovelay consume backPressed event: %{public}s",
468             navDestinationPattern->GetName().c_str());
469         return true;
470     }
471     auto navDestinationContext = navDestinationPattern->GetNavDestinationContext();
472     CHECK_NULL_RETURN(navDestinationContext, false);
473     auto navPathInfo = navDestinationContext->GetNavPathInfo();
474     CHECK_NULL_RETURN(navPathInfo, false);
475     auto isPathEntry = navPathInfo->GetIsEntry();
476     if (isPathEntry) {
477         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "%{public}s is entry navDestination, do not consume backPressed event",
478             navDestinationPattern->GetName().c_str());
479         navPathInfo->SetIsEntry(false);
480         auto index = navDestinationContext->GetIndex();
481         navigationStack->SetIsEntryByIndex(index, false);
482         isEntry = true;
483         return false;
484     }
485     TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navDestination consume back button event: %{public}s",
486         navDestinationPattern->GetName().c_str());
487     GestureEvent gestureEvent;
488     return navDestination->GetNavDestinationBackButtonEvent()(gestureEvent);
489 }
490 
HandleBack(const RefPtr<FrameNode> & node,bool isLastChild,bool isOverride)491 bool NavigationGroupNode::HandleBack(const RefPtr<FrameNode>& node, bool isLastChild, bool isOverride)
492 {
493     auto navigationPattern = GetPattern<NavigationPattern>();
494     if (!isOverride && !isLastChild) {
495         navigationPattern->RemoveNavDestination();
496         return true;
497     }
498     auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(node);
499     CHECK_NULL_RETURN(navDestination, false);
500 
501     auto mode = navigationPattern->GetNavigationMode();
502     auto layoutProperty = GetLayoutProperty<NavigationLayoutProperty>();
503     if (isLastChild && (mode == NavigationMode::SPLIT ||
504                            (mode == NavigationMode::STACK && layoutProperty->GetHideNavBar().value_or(false)))) {
505         return false;
506     }
507 
508     navigationPattern->RemoveNavDestination();
509     return true;
510 }
511 
TransitionWithPop(const RefPtr<FrameNode> & preNode,const RefPtr<FrameNode> & curNode,bool isNavBar)512 void NavigationGroupNode::TransitionWithPop(const RefPtr<FrameNode>& preNode, const RefPtr<FrameNode>& curNode,
513     bool isNavBar)
514 {
515     CHECK_NULL_VOID(preNode);
516 
517     auto preNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
518     CHECK_NULL_VOID(preNavDestination);
519     preNavDestination->SetTransitionType(PageTransitionType::EXIT_POP);
520 
521     /* obtain preTitle, preBackIcon and preFrameSize of preNavDestination */
522     auto preTitleNode = AceType::DynamicCast<TitleBarNode>(preNavDestination->GetTitleBarNode());
523     CHECK_NULL_VOID(preTitleNode);
524     auto preBackIcon = AceType::DynamicCast<FrameNode>(preTitleNode->GetBackButton());
525     CHECK_NULL_VOID(preBackIcon);
526 
527     auto preFrameSize = preNode->GetGeometryNode()->GetFrameSize();
528     RefPtr<TitleBarNode> curTitleBarNode;
529     if (!GetCurTitleBarNode(curTitleBarNode, curNode, isNavBar)) {
530         return;
531     }
532 
533     /* create animation finish callback */
534     CleanPopAnimations();
535     AnimationFinishCallback callback = [weakPreNode = WeakPtr<NavDestinationGroupNode>(preNavDestination),
536         weakPreTitle = WeakPtr<TitleBarNode>(preTitleNode),
537         weakPreBackIcon = WeakPtr<FrameNode>(preBackIcon),
538         weakNavigation = WeakClaim(this)] {
539             ACE_SCOPED_TRACE_COMMERCIAL("Navigation page pop transition end");
540             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation pop animation end");
541             PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH, true);
542             auto navigation = weakNavigation.Upgrade();
543             auto backIcon = weakPreBackIcon.Upgrade();
544             if (navigation) {
545                 navigation->isOnAnimation_ = false;
546                 auto id = navigation->GetTopDestination() ? navigation->GetTopDestination()->GetAccessibilityId() : -1;
547                 navigation->OnAccessibilityEvent(
548                     AccessibilityEventType::PAGE_CHANGE, id, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID);
549                 navigation->CleanPopAnimations();
550             }
551 
552             auto preNavDesNode = weakPreNode.Upgrade();
553             CHECK_NULL_VOID(preNavDesNode);
554             if (preNavDesNode->GetTransitionType() != PageTransitionType::EXIT_POP) {
555                 // has another transition, just return
556                 TAG_LOGW(AceLogTag::ACE_NAVIGATION, "preNavDesNode has another transition");
557                 return;
558             }
559             auto preNavDesPattern = preNavDesNode->GetPattern<NavDestinationPattern>();
560             CHECK_NULL_VOID(preNavDesPattern);
561             // NavRouter will restore the preNavDesNode and needs to set the initial state after the animation ends.
562             auto shallowBuilder = preNavDesPattern->GetShallowBuilder();
563             if (shallowBuilder && !preNavDesNode->IsCacheNode()) {
564                 shallowBuilder->MarkIsExecuteDeepRenderDone(false);
565             }
566             preNavDesNode->SetIsOnAnimation(false);
567             preNavDesNode->GetEventHub<EventHub>()->SetEnabledInternal(true);
568             preNavDesNode->GetRenderContext()->ClipWithRRect(RectF(0.0f, 0.0f, REMOVE_CLIP_SIZE, REMOVE_CLIP_SIZE),
569                 RadiusF(EdgeF(0.0f, 0.0f)));
570             preNavDesNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
571             auto preTitleNode = weakPreTitle.Upgrade();
572             if (preTitleNode) {
573                 preTitleNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
574                 preTitleNode->GetRenderContext()->SetOpacity(1.0);
575             }
576             if (!preNavDesNode->IsCacheNode() && preNavDesNode->GetContentNode()) {
577                 preNavDesNode->GetContentNode()->Clean();
578             }
579             if (backIcon)  {
580                 backIcon->GetRenderContext()->SetOpacity(1.0);
581             }
582             auto parent = preNavDesNode->GetParent();
583             CHECK_NULL_VOID(parent);
584             parent->RemoveChild(preNavDesNode);
585             auto context = PipelineContext::GetCurrentContext();
586             CHECK_NULL_VOID(context);
587             context->MarkNeedFlushMouseEvent();
588             parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
589         };
590 
591     /* set initial status of animation */
592     preNode->GetEventHub<EventHub>()->SetEnabledInternal(false);
593     preNode->GetRenderContext()->ClipWithRRect(RectF(0.0f, 0.0f, preFrameSize.Width(), REMOVE_CLIP_SIZE),
594         RadiusF(EdgeF(0.0f, 0.0f)));
595     preNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
596     preTitleNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
597     preNavDestination->SetIsOnAnimation(true);
598 
599     if (curNode) {
600         auto curFrameSize = curNode->GetGeometryNode()->GetFrameSize();
601         curNode->GetRenderContext()->ClipWithRRect(
602             RectF(0.0f, 0.0f, REMOVE_CLIP_SIZE, REMOVE_CLIP_SIZE), RadiusF(EdgeF(0.0f, 0.0f)));
603         float flag = CheckLanguageDirection();
604         curNode->GetRenderContext()->UpdateTranslateInXY({ -curFrameSize.Width() * PARENT_PAGE_OFFSET * flag, 0.0f });
605         curTitleBarNode->GetRenderContext()->UpdateTranslateInXY(
606             { curFrameSize.Width() * PARENT_TITLE_OFFSET * flag, 0.0f });
607     }
608 
609     /* start transition animation */
610     AnimationOption option = CreateAnimationOption(springCurve, FillMode::FORWARDS, DEFAULT_ANIMATION_DURATION,
611         callback);
612     auto newPopAnimation = AnimationUtils::StartAnimation(option, [
613         this, preNode, preTitleNode, preFrameSize, curNode, curTitleBarNode]() {
614             ACE_SCOPED_TRACE_COMMERCIAL("Navigation page pop transition start");
615             PerfMonitor::GetPerfMonitor()->Start(PerfConstants::ABILITY_OR_PAGE_SWITCH, PerfActionType::LAST_UP, "");
616             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation pop animation start");
617             /* preNode */
618             float flag = CheckLanguageDirection();
619             if (AceApplicationInfo::GetInstance().IsRightToLeft()) {
620                 preNode->GetRenderContext()->ClipWithRRect(
621                     RectF(0.0f, 0.0f, preFrameSize.Width() * HALF, REMOVE_CLIP_SIZE), RadiusF(EdgeF(0.0f, 0.0f)));
622             } else {
623                 preNode->GetRenderContext()->ClipWithRRect(
624                     RectF(preFrameSize.Width() * HALF, 0.0f, preFrameSize.Width(), REMOVE_CLIP_SIZE),
625                     RadiusF(EdgeF(0.0f, 0.0f)));
626             }
627             preNode->GetRenderContext()->UpdateTranslateInXY({ preFrameSize.Width() * HALF * flag, 0.0f });
628             preTitleNode->GetRenderContext()->UpdateTranslateInXY({ preFrameSize.Width() * HALF * flag, 0.0f });
629 
630             /* curNode */
631             if (curNode) {
632                 curNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
633                 curTitleBarNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
634             }
635     }, option.GetOnFinishEvent());
636     if (newPopAnimation) {
637         popAnimations_.emplace_back(newPopAnimation);
638     }
639 
640     /* opacity for title and backIcon */
641     auto titleOpacityAnimation = TitleOpacityAnimation(preTitleNode, true);
642     if (titleOpacityAnimation) {
643         popAnimations_.emplace_back(titleOpacityAnimation);
644     }
645     auto backButtonAnimation = BackButtonAnimation(preBackIcon, false);
646     if (backButtonAnimation) {
647         popAnimations_.emplace_back(backButtonAnimation);
648     }
649 
650     /* mask animation */
651     std::shared_ptr<AnimationUtils::Animation> maskAnimation;
652     if (curNode) {
653         AnimationOption maskOption = CreateAnimationOption(Curves::FRICTION, FillMode::FORWARDS, MASK_DURATION,
654             nullptr);
655         curNode->GetRenderContext()->SetActualForegroundColor(MASK_COLOR);
656         maskAnimation = AnimationUtils::StartAnimation(
657             maskOption, [curNode]() { curNode->GetRenderContext()->SetActualForegroundColor(Color::TRANSPARENT); });
658     }
659     if (maskAnimation) {
660         popAnimations_.emplace_back(maskAnimation);
661     }
662 
663     // clear this flag for navBar layout only
664     if (isNavBar) {
665         SetNeedSetInvisible(false);
666     }
667     isOnAnimation_ = true;
668 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
669     UiSessionManager::GetInstance().OnRouterChange(navigationPathInfo_, "navigationPopPage");
670 #endif
671 }
672 
TransitionWithPush(const RefPtr<FrameNode> & preNode,const RefPtr<FrameNode> & curNode,bool isNavBar)673 void NavigationGroupNode::TransitionWithPush(const RefPtr<FrameNode>& preNode, const RefPtr<FrameNode>& curNode,
674     bool isNavBar)
675 {
676     CHECK_NULL_VOID(preNode);
677     CHECK_NULL_VOID(curNode);
678 
679     RefPtr<FrameNode> preTitleNode;
680     if (isNavBar) {
681         auto navBarNode = AceType::DynamicCast<NavBarNode>(preNode);
682         navBarNode->SetTransitionType(PageTransitionType::EXIT_PUSH);
683         preTitleNode = navBarNode ? AceType::DynamicCast<TitleBarNode>(navBarNode->GetTitleBarNode()) : nullptr;
684     } else {
685         auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
686         navDestination->SetTransitionType(PageTransitionType::EXIT_PUSH);
687         preTitleNode = navDestination ? AceType::DynamicCast<TitleBarNode>(navDestination->GetTitleBarNode()) : nullptr;
688     }
689     CHECK_NULL_VOID(preTitleNode);
690 
691     auto mode = GetNavigationMode();
692     auto curNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
693     CHECK_NULL_VOID(curNavDestination);
694     curNavDestination->SetTransitionType(PageTransitionType::ENTER_PUSH);
695     auto curTitleNode = AceType::DynamicCast<TitleBarNode>(curNavDestination->GetTitleBarNode());
696     CHECK_NULL_VOID(curTitleNode);
697 
698     auto preFrameSize = preNode->GetGeometryNode()->GetFrameSize();
699     auto curFrameSize = curNode->GetGeometryNode()->GetFrameSize();
700 
701     /* Create animation callback */
702     CleanPushAnimations();
703     AnimationFinishCallback callback = [weakPreNode = WeakPtr<FrameNode>(preNode),
704         weakPreTitle = WeakPtr<FrameNode>(preTitleNode),
705         weakNavigation = WeakClaim(this),
706         weakCurNode = WeakPtr<FrameNode>(curNode),
707         isNavBar] {
708             ACE_SCOPED_TRACE_COMMERCIAL("Navigation page push transition end");
709             PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH, true);
710             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation push animation end");
711             auto navigation = weakNavigation.Upgrade();
712             CHECK_NULL_VOID(navigation);
713             auto preNode = weakPreNode.Upgrade();
714             while (preNode) {
715                 auto preDestination = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
716                 if (preDestination && preDestination->NeedRemoveInPush()) {
717                     navigation->hideNodes_.emplace_back(std::make_pair(preDestination, true));
718                     break;
719                 }
720                 auto preTitle = weakPreTitle.Upgrade();
721                 if (preTitle) {
722                     preTitle->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
723                 }
724                 preNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
725                 preNode->GetRenderContext()->SetActualForegroundColor(Color::TRANSPARENT);
726                 bool needSetInvisible = false;
727                 if (isNavBar) {
728                     auto navbar = AceType::DynamicCast<NavBarNode>(preNode);
729                     CHECK_NULL_VOID(navbar);
730                     needSetInvisible = AceType::DynamicCast<NavBarNode>(preNode)->GetTransitionType() ==
731                         PageTransitionType::EXIT_PUSH;
732                     // store this flag for navBar layout only
733                     navigation->SetNeedSetInvisible(needSetInvisible);
734                     bool isInvisible = navbar->IsNodeInvisible(navigation);
735                     if (needSetInvisible && isInvisible) {
736                         navbar->GetLayoutProperty()->UpdateVisibility(VisibleType::INVISIBLE);
737                         navbar->SetJSViewActive(false);
738                         navigation->NotifyPageHide();
739                     }
740                 } else {
741                     preDestination->SetIsOnAnimation(false);
742                     needSetInvisible = preDestination->GetTransitionType() == PageTransitionType::EXIT_PUSH;
743                     bool isInvisible = preDestination->IsNodeInvisible(navigation);
744                     if (needSetInvisible && isInvisible) {
745                         preDestination->GetLayoutProperty()->UpdateVisibility(VisibleType::INVISIBLE);
746                         preDestination->SetJSViewActive(false);
747                     }
748                 }
749                 break;
750             }
751             navigation->RemoveDialogDestination();
752             auto id = navigation->GetTopDestination() ? navigation->GetTopDestination()->GetAccessibilityId() : -1;
753             navigation->OnAccessibilityEvent(
754                 AccessibilityEventType::PAGE_CHANGE, id, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID);
755             auto curNode = weakCurNode.Upgrade();
756             if (curNode) {
757                 auto curNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
758                 CHECK_NULL_VOID(curNavDestination);
759                 if (curNavDestination->GetTransitionType() != PageTransitionType::ENTER_PUSH) {
760                     TAG_LOGW(AceLogTag::ACE_NAVIGATION, "curNode has another transition");
761                     return;
762                 }
763                 curNavDestination->SetIsOnAnimation(false);
764                 curNode->GetRenderContext()->RemoveClipWithRRect();
765             }
766             navigation->isOnAnimation_ = false;
767             navigation->CleanPushAnimations();
768             auto pattern = navigation->GetPattern<NavigationPattern>();
769             CHECK_NULL_VOID(pattern);
770             pattern->CheckContentNeedMeasure(navigation);
771         };
772 
773     /* set initial status of animation */
774     /* preNode */
775     preNode->GetRenderContext()->RemoveClipWithRRect();
776     preNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
777     preTitleNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
778     if (!isNavBar) {
779         auto preDestination = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
780         preDestination->SetIsOnAnimation(true);
781         if (preDestination->NeedRemoveInPush()) {
782             preNode->GetEventHub<EventHub>()->SetEnabledInternal(false);
783         }
784     }
785     /* curNode */
786     float flag = CheckLanguageDirection();
787     if (AceApplicationInfo::GetInstance().IsRightToLeft()) {
788         curNode->GetRenderContext()->ClipWithRRect(
789             RectF(0.0f, 0.0f, curFrameSize.Width() * HALF, REMOVE_CLIP_SIZE), RadiusF(EdgeF(0.0f, 0.0f)));
790     } else {
791         curNode->GetRenderContext()->ClipWithRRect(
792             RectF(curFrameSize.Width() * HALF, 0.0f, curFrameSize.Width(), REMOVE_CLIP_SIZE),
793             RadiusF(EdgeF(0.0f, 0.0f)));
794     }
795     curNode->GetRenderContext()->UpdateTranslateInXY({ curFrameSize.Width() * HALF * flag, 0.0f });
796     curTitleNode->GetRenderContext()->UpdateTranslateInXY({ curFrameSize.Width() * HALF * flag, 0.0f });
797     curNavDestination->SetIsOnAnimation(true);
798 
799     /* start transition animation */
800     AnimationOption option = CreateAnimationOption(springCurve, FillMode::FORWARDS, DEFAULT_ANIMATION_DURATION,
801         callback);
802     auto newPushAnimation = AnimationUtils::StartAnimation(option, [
803         this, preNode, preTitleNode, curNode, curTitleNode, preFrameSize, curFrameSize, mode]() {
804             ACE_SCOPED_TRACE_COMMERCIAL("Navigation page push transition start");
805             PerfMonitor::GetPerfMonitor()->Start(PerfConstants::ABILITY_OR_PAGE_SWITCH, PerfActionType::LAST_UP, "");
806             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation push animation start");
807             float flag = CheckLanguageDirection();
808             // preNode
809             preNode->GetRenderContext()->UpdateTranslateInXY(
810                 { -preFrameSize.Width() * PARENT_PAGE_OFFSET * flag, 0.0f });
811             preTitleNode->GetRenderContext()->UpdateTranslateInXY(
812                 { preFrameSize.Width() * PARENT_TITLE_OFFSET * flag, 0.0f });
813             // curNode
814             curNode->GetRenderContext()->ClipWithRRect(
815                 RectF(0.0f, 0.0f, curFrameSize.Width(), REMOVE_CLIP_SIZE), RadiusF(EdgeF(0.0f, 0.0f)));
816             curNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
817             curTitleNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
818     }, option.GetOnFinishEvent());
819     if (newPushAnimation) {
820         pushAnimations_.emplace_back(newPushAnimation);
821     }
822     auto maskAnimation = MaskAnimation(preNode->GetRenderContext());
823     if (maskAnimation) {
824         pushAnimations_.emplace_back(maskAnimation);
825     }
826 
827     // title opacity
828     auto titleOpacityAnimation = TitleOpacityAnimation(curTitleNode, false);
829     if (titleOpacityAnimation) {
830         pushAnimations_.emplace_back(titleOpacityAnimation);
831     }
832     // backIcon opacity
833     auto backIcon = AceType::DynamicCast<FrameNode>(curTitleNode->GetBackButton());
834     auto backButtonAnimation = BackButtonAnimation(backIcon, true);
835     if (backButtonAnimation) {
836         pushAnimations_.emplace_back(backButtonAnimation);
837     }
838     isOnAnimation_ = true;
839     if (AceChecker::IsPerformanceCheckEnabled()) {
840         int64_t startTime = GetSysTimestamp();
841         auto pipeline = AceType::DynamicCast<NG::PipelineContext>(PipelineContext::GetCurrentContext());
842         // After completing layout tasks at all nodes on the page, perform performance testing and management
843         pipeline->AddAfterLayoutTask([weakNav = WeakClaim(this), weakNode = WeakPtr<FrameNode>(curNode), startTime,
844                                          path = curNavDestination->GetNavDestinationPathInfo()]() {
845             auto navigation = weakNav.Upgrade();
846             CHECK_NULL_VOID(navigation);
847             auto curNode = weakNode.Upgrade();
848             int64_t endTime = GetSysTimestamp();
849             CHECK_NULL_VOID(curNode);
850             PerformanceCheckNodeMap nodeMap;
851             curNode->GetPerformanceCheckData(nodeMap);
852             AceScopedPerformanceCheck::RecordPerformanceCheckData(nodeMap, endTime - startTime, path);
853         });
854     }
855 #if !defined(ACE_UNITTEST)
856     TransparentNodeDetector::GetInstance().PostCheckNodeTransparentTask(curNode);
857 #endif
858 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
859     UiSessionManager::GetInstance().OnRouterChange(navigationPathInfo_, "navigationPushPage");
860 #endif
861 }
862 
BackButtonAnimation(const RefPtr<FrameNode> & backButtonNode,bool isTransitionIn)863 std::shared_ptr<AnimationUtils::Animation> NavigationGroupNode::BackButtonAnimation(
864     const RefPtr<FrameNode>& backButtonNode, bool isTransitionIn)
865 {
866     CHECK_NULL_RETURN(backButtonNode, nullptr);
867     AnimationOption transitionOption;
868     transitionOption.SetCurve(Curves::SHARP);
869     auto backButtonNodeContext = backButtonNode->GetRenderContext();
870     CHECK_NULL_RETURN(backButtonNodeContext, nullptr);
871     if (isTransitionIn) {
872         transitionOption.SetDelay(OPACITY_BACKBUTTON_IN_DELAY);
873         transitionOption.SetDuration(OPACITY_BACKBUTTON_IN_DURATION);
874         backButtonNodeContext->SetOpacity(0.0f);
875         return AnimationUtils::StartAnimation(transitionOption, [backButtonNodeContext]() {
876             CHECK_NULL_VOID(backButtonNodeContext);
877             backButtonNodeContext->SetOpacity(1.0f);
878         });
879     }
880     transitionOption.SetDuration(OPACITY_BACKBUTTON_OUT_DURATION);
881     // recover after transition animation.
882     backButtonNodeContext->SetOpacity(1.0f);
883     return AnimationUtils::StartAnimation(transitionOption, [backButtonNodeContext]() {
884         CHECK_NULL_VOID(backButtonNodeContext);
885         backButtonNodeContext->SetOpacity(0.0f);
886     });
887 }
888 
MaskAnimation(const RefPtr<RenderContext> & transitionOutNodeContext)889 std::shared_ptr<AnimationUtils::Animation> NavigationGroupNode::MaskAnimation(
890     const RefPtr<RenderContext>& transitionOutNodeContext)
891 {
892     AnimationOption maskOption;
893     maskOption.SetCurve(Curves::FRICTION);
894     maskOption.SetDuration(MASK_DURATION);
895     maskOption.SetFillMode(FillMode::FORWARDS);
896     transitionOutNodeContext->SetActualForegroundColor(Color::TRANSPARENT);
897     return AnimationUtils::StartAnimation(
898         maskOption, [transitionOutNodeContext]() { transitionOutNodeContext->SetActualForegroundColor(MASK_COLOR); },
899         maskOption.GetOnFinishEvent());
900 }
901 
TitleOpacityAnimation(const RefPtr<FrameNode> & node,bool isTransitionOut)902 std::shared_ptr<AnimationUtils::Animation> NavigationGroupNode::TitleOpacityAnimation(
903     const RefPtr<FrameNode>& node, bool isTransitionOut)
904 {
905     auto titleNode = AceType::DynamicCast<TitleBarNode>(node);
906     CHECK_NULL_RETURN(titleNode, nullptr);
907     auto titleRenderContext = titleNode->GetRenderContext();
908     CHECK_NULL_RETURN(titleRenderContext, nullptr);
909     AnimationOption opacityOption;
910     opacityOption.SetCurve(Curves::SHARP);
911     opacityOption.SetDuration(OPACITY_TITLE_DURATION);
912     if (isTransitionOut) {
913         opacityOption.SetDelay(OPACITY_TITLE_OUT_DELAY);
914         // recover after transition animation.
915         titleRenderContext->SetOpacity(1.0f);
916         return AnimationUtils::StartAnimation(opacityOption, [titleRenderContext]() {
917             CHECK_NULL_VOID(titleRenderContext);
918             titleRenderContext->SetOpacity(0.0f);
919         });
920     }
921     opacityOption.SetDelay(OPACITY_TITLE_IN_DELAY);
922     titleRenderContext->SetOpacity(0.0f);
923     return AnimationUtils::StartAnimation(opacityOption, [titleRenderContext]() {
924         CHECK_NULL_VOID(titleRenderContext);
925         titleRenderContext->SetOpacity(1.0f);
926     });
927 }
928 
TransitionWithReplace(const RefPtr<FrameNode> & preNode,const RefPtr<FrameNode> & curNode,bool isNavBar)929 void NavigationGroupNode::TransitionWithReplace(
930     const RefPtr<FrameNode>& preNode, const RefPtr<FrameNode>& curNode, bool isNavBar)
931 {
932     CHECK_NULL_VOID(preNode);
933     CHECK_NULL_VOID(curNode);
934     AnimationOption option;
935     option.SetCurve(replaceCurve);
936     option.SetFillMode(FillMode::FORWARDS);
937     option.SetDuration(DEFAULT_REPLACE_DURATION);
938     option.SetOnFinishEvent([weakPreNode = WeakPtr<FrameNode>(preNode), weakNavigation = WeakClaim(this),
939                                 isNavBar]() {
940         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation replace animation end");
941         ACE_SCOPED_TRACE_COMMERCIAL("Navigation page replace transition end");
942         PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH, true);
943         auto preNode = weakPreNode.Upgrade();
944         CHECK_NULL_VOID(preNode);
945         auto navigationNode = weakNavigation.Upgrade();
946         CHECK_NULL_VOID(navigationNode);
947         navigationNode->isOnAnimation_ = false;
948         auto id = navigationNode->GetTopDestination() ? navigationNode->GetTopDestination()->GetAccessibilityId() : -1;
949         navigationNode->OnAccessibilityEvent(
950             AccessibilityEventType::PAGE_CHANGE, id, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID);
951         navigationNode->DealNavigationExit(preNode, isNavBar);
952         auto context = PipelineContext::GetCurrentContext();
953         CHECK_NULL_VOID(context);
954         context->MarkNeedFlushMouseEvent();
955     });
956     preNode->GetEventHub<EventHub>()->SetEnabledInternal(false);
957     curNode->GetRenderContext()->UpdateOpacity(0.0f);
958     if (!isNavBar) {
959         auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
960         if (navDestination) {
961             navDestination->SetIsOnAnimation(true);
962         }
963     }
964     AnimationUtils::Animate(
965         option,
966         [curNode]() {
967             ACE_SCOPED_TRACE_COMMERCIAL("Navigation page replace transition start");
968             PerfMonitor::GetPerfMonitor()->Start(PerfConstants::ABILITY_OR_PAGE_SWITCH, PerfActionType::LAST_UP, "");
969             curNode->GetRenderContext()->UpdateOpacity(1.0f);
970         },
971         option.GetOnFinishEvent());
972     isOnAnimation_ = true;
973 }
974 
OnInspectorIdUpdate(const std::string & id)975 void NavigationGroupNode::OnInspectorIdUpdate(const std::string& id)
976 {
977     auto context = PipelineContext::GetCurrentContext();
978     CHECK_NULL_VOID(context);
979     context->AddOrReplaceNavigationNode(id, WeakClaim(this));
980     curId_ = id;
981 }
982 
DealNavigationExit(const RefPtr<FrameNode> & preNode,bool isNavBar,bool isAnimated)983 void NavigationGroupNode::DealNavigationExit(const RefPtr<FrameNode>& preNode, bool isNavBar, bool isAnimated)
984 {
985     CHECK_NULL_VOID(preNode);
986     if (preNode->GetEventHub<EventHub>()) {
987         preNode->GetEventHub<EventHub>()->SetEnabledInternal(true);
988     }
989     if (isNavBar && isAnimated) {
990         SetNeedSetInvisible(true);
991         return;
992     }
993     auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
994     CHECK_NULL_VOID(navDestinationNode);
995     navDestinationNode->SetIsOnAnimation(false);
996     auto navDestinationPattern = navDestinationNode->GetPattern<NavDestinationPattern>();
997     CHECK_NULL_VOID(navDestinationPattern);
998     auto navigationPattern = GetPattern<NavigationPattern>();
999     CHECK_NULL_VOID(navigationPattern);
1000     auto stack = navigationPattern->GetNavigationStack();
1001     bool isInStack = stack->FindIndex(navDestinationPattern->GetName(),
1002         navDestinationPattern->GetCustomNode(), true) != -1;
1003     if (isInStack) {
1004         RemoveDialogDestination(true);
1005         auto preContext = navDestinationNode->GetRenderContext();
1006         CHECK_NULL_VOID(preContext);
1007         preContext->UpdateZIndex(0);
1008         return;
1009     }
1010     auto shallowBuilder = navDestinationPattern->GetShallowBuilder();
1011     if (shallowBuilder) {
1012         shallowBuilder->MarkIsExecuteDeepRenderDone(false);
1013     }
1014     // remove old navdestination node
1015     if (navDestinationNode->GetContentNode()) {
1016         navDestinationNode->GetContentNode()->Clean();
1017     }
1018     auto parent = AceType::DynamicCast<FrameNode>(preNode->GetParent());
1019     CHECK_NULL_VOID(parent);
1020     parent->RemoveChild(preNode);
1021     RemoveDialogDestination(true);
1022     parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1023 }
1024 
NotifyPageHide()1025 void NavigationGroupNode::NotifyPageHide()
1026 {
1027     auto context = PipelineContext::GetCurrentContext();
1028     CHECK_NULL_VOID(context);
1029     auto stageManager = context->GetStageManager();
1030     CHECK_NULL_VOID(stageManager);
1031     auto container = Container::Current();
1032     CHECK_NULL_VOID(container);
1033     auto pageUrlChecker = container->GetPageUrlChecker();
1034     CHECK_NULL_VOID(pageUrlChecker);
1035     RefPtr<FrameNode> pageNode = stageManager->GetLastPage();
1036     CHECK_NULL_VOID(pageNode);
1037     auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
1038     CHECK_NULL_VOID(pagePattern);
1039     auto pageInfo = pagePattern->GetPageInfo();
1040     CHECK_NULL_VOID(pageInfo);
1041     pageUrlChecker->NotifyPageHide(pageInfo->GetPageUrl());
1042 }
1043 
UpdateLastStandardIndex()1044 void NavigationGroupNode::UpdateLastStandardIndex()
1045 {
1046     // remove the impact of last standard index
1047     lastStandardIndex_ = -1;
1048     auto navigationPattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1049     CHECK_NULL_VOID(navigationPattern);
1050     auto navigationStack = navigationPattern->GetNavigationStack();
1051     CHECK_NULL_VOID(navigationStack);
1052     const auto& navDestinationNodes = navigationStack->GetAllNavDestinationNodes();
1053     if (navDestinationNodes.size() == 0) {
1054         return;
1055     }
1056     for (int32_t index = static_cast<int32_t>(navDestinationNodes.size()) - 1; index >= 0; index--) {
1057         const auto& curPath = navDestinationNodes[index];
1058         const auto& uiNode = curPath.second;
1059         if (!uiNode) {
1060             continue;
1061         }
1062         auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(GetNavDestinationNode(uiNode));
1063         if (navDestinationNode && navDestinationNode->GetNavDestinationMode() == NavDestinationMode::STANDARD) {
1064             lastStandardIndex_ = index;
1065             return;
1066         }
1067     }
1068 }
1069 
UpdateNavDestinationVisibility(const RefPtr<NavDestinationGroupNode> & navDestination,const RefPtr<UINode> & remainChild,int32_t index,size_t destinationSize,const RefPtr<UINode> & preLastStandardNode)1070 bool NavigationGroupNode::UpdateNavDestinationVisibility(const RefPtr<NavDestinationGroupNode>& navDestination,
1071     const RefPtr<UINode>& remainChild, int32_t index, size_t destinationSize, const RefPtr<UINode>& preLastStandardNode)
1072 {
1073     auto eventHub = navDestination->GetEventHub<NavDestinationEventHub>();
1074     CHECK_NULL_RETURN(eventHub, false);
1075     if (index == static_cast<int32_t>(destinationSize) - 1) {
1076         // process shallow builder
1077         navDestination->ProcessShallowBuilder();
1078         navDestination->GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE, true);
1079         navDestination->SetJSViewActive(true);
1080         navDestination->GetEventHub<EventHub>()->SetEnabledInternal(true);
1081         // for the navDestination at the top, FireChangeEvent
1082         eventHub->FireChangeEvent(true);
1083         bool hasChanged = CheckNeedMeasure(navDestination->GetLayoutProperty()->GetPropertyChangeFlag());
1084         if (!hasChanged && NavigationLayoutAlgorithm::IsAutoHeight(GetLayoutProperty<NavigationLayoutProperty>())) {
1085             hasChanged = true;
1086         }
1087         return hasChanged;
1088     }
1089     if (index < lastStandardIndex_) {
1090         auto pattern = AceType::DynamicCast<NavDestinationPattern>(navDestination->GetPattern());
1091         if (navDestination->IsOnAnimation()) {
1092             return false;
1093         }
1094         if (!pattern || !pattern->GetIsOnShow()) {
1095             // push more than one standard navDestination, need to set invisible below newTopDestination
1096             auto navDestinationLayoutProperty = navDestination->GetLayoutProperty();
1097             CHECK_NULL_RETURN(navDestinationLayoutProperty, false);
1098             navDestinationLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
1099             navDestination->SetJSViewActive(false);
1100             return false;
1101         }
1102         eventHub->FireChangeEvent(false);
1103         if (pattern->GetCustomNode() != remainChild) {
1104             if (navDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG ||
1105                 navDestination == AceType::DynamicCast<NavDestinationGroupNode>(preLastStandardNode)) {
1106                 hideNodes_.insert(hideNodes_.begin(), std::pair(navDestination, false));
1107             } else {
1108                 navDestination->GetLayoutProperty()->UpdateVisibility(VisibleType::INVISIBLE);
1109                 auto pattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1110                 pattern->NotifyDestinationLifecycle(navDestination, NavDestinationLifecycle::ON_WILL_HIDE);
1111                 pattern->NotifyDestinationLifecycle(navDestination, NavDestinationLifecycle::ON_HIDE);
1112             }
1113         }
1114         return false;
1115     }
1116     auto pattern = AceType::DynamicCast<NavDestinationPattern>(navDestination->GetPattern());
1117     if (navDestination->GetPattern<NavDestinationPattern>()->GetCustomNode() != remainChild &&
1118         !navDestination->IsOnAnimation()) {
1119         navDestination->GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE);
1120         navDestination->SetJSViewActive(true);
1121     }
1122     return false;
1123 }
1124 
CreateAnimationOption(const RefPtr<Curve> & curve,FillMode mode,int32_t duration,const AnimationFinishCallback & callback)1125 AnimationOption NavigationGroupNode::CreateAnimationOption(const RefPtr<Curve>& curve, FillMode mode,
1126     int32_t duration, const AnimationFinishCallback& callback)
1127 {
1128     AnimationOption option;
1129     option.SetCurve(curve);
1130     option.SetFillMode(mode);
1131     option.SetDuration(duration);
1132     if (callback != nullptr) {
1133         option.SetOnFinishEvent(callback);
1134     }
1135     return option;
1136 }
1137 
GetNavigationMode()1138 NavigationMode NavigationGroupNode::GetNavigationMode()
1139 {
1140     auto navigationPattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1141     CHECK_NULL_RETURN(navigationPattern, NavigationMode::AUTO);
1142     return navigationPattern->GetNavigationMode();
1143 }
1144 
OnDetachFromMainTree(bool recursive,PipelineContext * context)1145 void NavigationGroupNode::OnDetachFromMainTree(bool recursive, PipelineContext* context)
1146 {
1147     auto pattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1148     if (pattern) {
1149         pattern->DetachNavigationStackFromParent();
1150         pattern->RemoveFromDumpManager();
1151     }
1152 
1153     GroupNode::OnDetachFromMainTree(recursive, context);
1154 }
1155 
FindNavigationParent(const std::string & parentName)1156 bool NavigationGroupNode::FindNavigationParent(const std::string& parentName)
1157 {
1158     auto parent = GetParent();
1159     while (parent) {
1160         if (parent->GetTag() == parentName) {
1161             AddDestinationNode(parent);
1162             return true;
1163         }
1164         parent = parent->GetParent();
1165     }
1166     return parent != nullptr;
1167 }
1168 
AddDestinationNode(const RefPtr<UINode> & parent)1169 void NavigationGroupNode::AddDestinationNode(const RefPtr<UINode>& parent)
1170 {
1171     auto destinationNode = AceType::DynamicCast<NavDestinationGroupNode>(parent);
1172     if (destinationNode) {
1173         parentDestinationNode_ = destinationNode;
1174     }
1175 }
1176 
OnAttachToMainTree(bool recursive)1177 void NavigationGroupNode::OnAttachToMainTree(bool recursive)
1178 {
1179     GroupNode::OnAttachToMainTree(recursive);
1180 
1181     auto pattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1182     if (pattern) {
1183         pattern->AttachNavigationStackToParent();
1184         pattern->AddToDumpManager();
1185     }
1186     auto parent = GetParent();
1187     while (parent) {
1188         if (parent->GetTag() == V2::JS_VIEW_ETS_TAG) {
1189             break;
1190         }
1191         parent = parent->GetParent();
1192     }
1193     if (parent) {
1194         pattern->SetParentCustomNode(parent);
1195     } else {
1196         TAG_LOGE(AceLogTag::ACE_NAVIGATION, "parent custom node is nullptr");
1197     }
1198     bool findNavdestination = FindNavigationParent(V2::NAVDESTINATION_VIEW_ETS_TAG);
1199     auto pipelineContext = PipelineContext::GetCurrentContext();
1200     CHECK_NULL_VOID(pipelineContext);
1201     auto stageManager = pipelineContext->GetStageManager();
1202     CHECK_NULL_VOID(stageManager);
1203     RefPtr<FrameNode> pageNode = stageManager->GetLastPage();
1204     CHECK_NULL_VOID(pageNode);
1205     auto pagePattern = pageNode->GetPattern<PagePattern>();
1206     CHECK_NULL_VOID(pagePattern);
1207     CHECK_NULL_VOID(pagePattern->GetPageInfo());
1208     int32_t pageId = pagePattern->GetPageInfo()->GetPageId();
1209     if (!findNavdestination) {
1210         pipelineContext->AddNavigationNode(pageId, WeakClaim(this));
1211     }
1212 }
1213 
FireHideNodeChange(NavDestinationLifecycle lifecycle)1214 void NavigationGroupNode::FireHideNodeChange(NavDestinationLifecycle lifecycle)
1215 {
1216     auto navigationPattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1217     for (auto iter = hideNodes_.begin(); iter != hideNodes_.end(); ++iter) {
1218         auto navDestination = iter->first;
1219         if (!navDestination) {
1220             continue;
1221         }
1222         if (lifecycle == NavDestinationLifecycle::ON_WILL_DISAPPEAR) {
1223             if (iter->second) {
1224                 navigationPattern->NotifyDestinationLifecycle(
1225                     navDestination, NavDestinationLifecycle::ON_WILL_DISAPPEAR);
1226             }
1227             continue;
1228         }
1229         auto pattern = AceType::DynamicCast<NavDestinationPattern>(navDestination->GetPattern());
1230         if (!pattern->GetIsOnShow()) {
1231             continue;
1232         }
1233         if (lifecycle == NavDestinationLifecycle::ON_WILL_HIDE) {
1234             navigationPattern->NotifyDestinationLifecycle(navDestination, NavDestinationLifecycle::ON_WILL_HIDE);
1235             continue;
1236         }
1237         if (lifecycle == NavDestinationLifecycle::ON_HIDE) {
1238             navigationPattern->NotifyDestinationLifecycle(navDestination, NavDestinationLifecycle::ON_HIDE);
1239         }
1240     }
1241 }
1242 
CheckLanguageDirection()1243 float NavigationGroupNode::CheckLanguageDirection()
1244 {
1245     bool isRightToLeft = AceApplicationInfo::GetInstance().IsRightToLeft();
1246     if (isRightToLeft) {
1247         return -1.0f;
1248     } else {
1249         return 1.0f;
1250     }
1251 }
GetCurTitleBarNode(RefPtr<TitleBarNode> & curTitleBarNode,const RefPtr<FrameNode> & curNode,bool isNavBar)1252 bool NavigationGroupNode::GetCurTitleBarNode(
1253     RefPtr<TitleBarNode>& curTitleBarNode, const RefPtr<FrameNode>& curNode, bool isNavBar)
1254 {
1255     if (curNode) {
1256         if (isNavBar) {
1257             auto navBarNode = AceType::DynamicCast<NavBarNode>(curNode);
1258             CHECK_NULL_RETURN(navBarNode, false);
1259             navBarNode->SetTransitionType(PageTransitionType::ENTER_POP);
1260             curTitleBarNode = navBarNode ? AceType::DynamicCast<TitleBarNode>(navBarNode->GetTitleBarNode()) : nullptr;
1261         } else {
1262             auto curNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
1263             CHECK_NULL_RETURN(curNavDestination, false);
1264             curNavDestination->SetTransitionType(PageTransitionType::ENTER_POP);
1265             curTitleBarNode =
1266                 curNavDestination ? AceType::DynamicCast<TitleBarNode>(curNavDestination->GetTitleBarNode()) : nullptr;
1267         }
1268         CHECK_NULL_RETURN(curTitleBarNode, false);
1269     }
1270     return true;
1271 }
1272 
RemoveDialogDestination(bool isReplace)1273 void NavigationGroupNode::RemoveDialogDestination(bool isReplace)
1274 {
1275     for (auto iter = hideNodes_.begin(); iter != hideNodes_.end(); iter++) {
1276         auto navDestination = iter->first;
1277         if (!navDestination) {
1278             continue;
1279         }
1280         if (!iter->second) {
1281             // navDestination node don't need to remove, update visibility invisible
1282             navDestination->GetLayoutProperty()->UpdateVisibility(VisibleType::INVISIBLE);
1283             navDestination->SetJSViewActive(false);
1284             if (!isReplace) {
1285                 continue;
1286             }
1287             auto context = navDestination->GetRenderContext();
1288             if (!context) {
1289                 continue;
1290             }
1291             context->UpdateZIndex(0);
1292             continue;
1293         }
1294         auto parent = navDestination->GetParent();
1295         if (!parent) {
1296             continue;
1297         }
1298         auto navDestinationPattern = AceType::DynamicCast<NavDestinationPattern>(navDestination->GetPattern());
1299         if (!navDestinationPattern) {
1300             continue;
1301         }
1302         auto shallowBuilder = navDestinationPattern->GetShallowBuilder();
1303         if (shallowBuilder) {
1304             shallowBuilder->MarkIsExecuteDeepRenderDone(false);
1305         }
1306         if (navDestination->GetContentNode()) {
1307             navDestination->GetContentNode()->Clean();
1308         }
1309         parent->RemoveChild(navDestination);
1310     }
1311     hideNodes_.clear();
1312 }
1313 
DealRemoveDestination(const RefPtr<NavDestinationGroupNode> & navDestination)1314 void NavigationGroupNode::DealRemoveDestination(const RefPtr<NavDestinationGroupNode>& navDestination)
1315 {
1316     // remove content child
1317     auto navDestinationPattern = navDestination->GetPattern<NavDestinationPattern>();
1318     auto pattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1319     if (navDestinationPattern->GetIsOnShow()) {
1320         pattern->NotifyDestinationLifecycle(navDestination, NavDestinationLifecycle::ON_WILL_HIDE);
1321         pattern->NotifyDestinationLifecycle(navDestination, NavDestinationLifecycle::ON_HIDE);
1322         navDestinationPattern->SetIsOnShow(false);
1323     }
1324     pattern->NotifyDestinationLifecycle(navDestination, NavDestinationLifecycle::ON_WILL_DISAPPEAR);
1325     auto shallowBuilder = navDestinationPattern->GetShallowBuilder();
1326     if (shallowBuilder) {
1327         shallowBuilder->MarkIsExecuteDeepRenderDone(false);
1328     }
1329     if (navDestination->GetContentNode()) {
1330         navDestination->GetContentNode()->Clean();
1331     }
1332     contentNode_->RemoveChild(navDestination, true);
1333 }
1334 
CreateAnimationWithDialogPop(const AnimationFinishCallback callback,const std::vector<WeakPtr<FrameNode>> preNavList,const std::vector<WeakPtr<FrameNode>> curNavList)1335 void NavigationGroupNode::CreateAnimationWithDialogPop(const AnimationFinishCallback callback,
1336     const std::vector<WeakPtr<FrameNode>> preNavList,
1337     const std::vector<WeakPtr<FrameNode>> curNavList)
1338 {
1339     // start transition animation
1340     AnimationOption option = CreateAnimationOption(springCurve, FillMode::FORWARDS, DEFAULT_ANIMATION_DURATION,
1341         callback);
1342     auto newPopAnimation = AnimationUtils::StartAnimation(option, [
1343        weakNavigation = WeakClaim(this), curNavList, preNavList]() {
1344             PerfMonitor::GetPerfMonitor()->Start(PerfConstants::ABILITY_OR_PAGE_SWITCH, PerfActionType::LAST_UP, "");
1345             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation dialog pop animation start");
1346 
1347             // do preNode transition
1348             auto navigation = weakNavigation.Upgrade();
1349             CHECK_NULL_VOID(navigation);
1350             for (auto iter: preNavList) {
1351                 auto preNode = iter.Upgrade();
1352                 CHECK_NULL_VOID(preNode);
1353                 auto preNavDesNode = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
1354                 if (preNavDesNode) {
1355                     preNavDesNode->StartSystemTransitionPop(false);
1356                 }
1357             }
1358 
1359             // do currentNode transition
1360             for (auto iter: curNavList) {
1361                 auto curNode = iter.Upgrade();
1362                 CHECK_NULL_VOID(curNode);
1363                 if (curNode->GetTag() == V2::NAVBAR_ETS_TAG) {
1364                     auto curNavbar = AceType::DynamicCast<NavBarNode>(curNode);
1365                     CHECK_NULL_VOID(curNavbar);
1366                     curNavbar->StartSystemTransitionPop();
1367                 } else {
1368                     auto curDestination = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
1369                     CHECK_NULL_VOID(curDestination);
1370                     curDestination->StartSystemTransitionPop(true);
1371                 }
1372             }
1373     }, option.GetOnFinishEvent());
1374     if (newPopAnimation) {
1375         popAnimations_.emplace_back(newPopAnimation);
1376     }
1377     isOnAnimation_ = true;
1378 }
1379 
TransitionWithDialogPop(const RefPtr<FrameNode> & preNode,const RefPtr<FrameNode> & curNode,bool isNavBar)1380 void NavigationGroupNode::TransitionWithDialogPop(const RefPtr<FrameNode>& preNode, const RefPtr<FrameNode>& curNode,
1381     bool isNavBar)
1382 {
1383     CHECK_NULL_VOID(preNode);
1384     std::vector<WeakPtr<FrameNode>> preNavList;
1385     InitPopPreList(preNode, preNavList);
1386     std::vector<WeakPtr<FrameNode>> curNavList;
1387     bool isNavbarNeedAnimation = lastStandardIndex_ == -1 || isNavBar;
1388     InitPopCurList(curNode, curNavList, isNavbarNeedAnimation);
1389 
1390     /* create animation finish callback */
1391     CleanPopAnimations();
1392     AnimationFinishCallback callback = [preNavList, weakNavigation = WeakClaim(this)] {
1393             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation dialog pop animation end");
1394             PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH, true);
1395             auto navigation = weakNavigation.Upgrade();
1396             CHECK_NULL_VOID(navigation);
1397             navigation->isOnAnimation_ = false;
1398             navigation->OnAccessibilityEvent(AccessibilityEventType::PAGE_CHANGE);
1399             navigation->CleanPopAnimations();
1400             for (auto iter = preNavList.rbegin(); iter != preNavList.rend(); ++iter) {
1401                 auto preNode = (*iter).Upgrade();
1402                 CHECK_NULL_VOID(preNode);
1403                 auto preNavDesNode = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
1404                 CHECK_NULL_VOID(preNavDesNode);
1405                 if (preNavDesNode->SystemTransitionPopCallback(false)) {
1406                     auto parent = preNavDesNode->GetParent();
1407                     CHECK_NULL_VOID(parent);
1408                     parent->RemoveChild(preNavDesNode);
1409                 }
1410                 navigation->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
1411             }
1412             navigation->RemoveDialogDestination();
1413             auto context = PipelineContext::GetCurrentContext();
1414             CHECK_NULL_VOID(context);
1415             context->MarkNeedFlushMouseEvent();
1416         };
1417     CreateAnimationWithDialogPop(callback, preNavList, curNavList);
1418 }
1419 
CreateAnimationWithDialogPush(const AnimationFinishCallback callback,const std::vector<WeakPtr<FrameNode>> prevNavList,const std::vector<WeakPtr<FrameNode>> curNavList)1420 void NavigationGroupNode::CreateAnimationWithDialogPush(const AnimationFinishCallback callback,
1421     const std::vector<WeakPtr<FrameNode>> prevNavList, const std::vector<WeakPtr<FrameNode>> curNavList)
1422 {
1423     // start transition animation
1424     AnimationOption option = CreateAnimationOption(springCurve, FillMode::FORWARDS, DEFAULT_ANIMATION_DURATION,
1425         callback);
1426     auto newPushAnimation = AnimationUtils::StartAnimation(option,
1427         [weakNavigation = WeakClaim(this), prevNavList, curNavList]() {
1428             PerfMonitor::GetPerfMonitor()->Start(PerfConstants::ABILITY_OR_PAGE_SWITCH, PerfActionType::LAST_UP, "");
1429             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation dialog push animation start");
1430             auto navigation = weakNavigation.Upgrade();
1431             CHECK_NULL_VOID(navigation);
1432 
1433             // preNode do EXIT PUSH animation
1434             for (auto iter : prevNavList) {
1435                 auto preNode = iter.Upgrade();
1436                 CHECK_NULL_VOID(preNode);
1437                 if (preNode->GetTag() == V2::NAVBAR_ETS_TAG &&
1438                     navigation->GetNavigationMode() == NavigationMode::STACK) {
1439                     auto navBarNode = AceType::DynamicCast<NavBarNode>(preNode);
1440                     CHECK_NULL_VOID(navBarNode);
1441                     navBarNode->StartSystemTransitionPush();
1442                 } else {
1443                     auto preDestination = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
1444                     CHECK_NULL_VOID(preDestination);
1445                     preDestination->StartSystemTransitionPush(false);
1446                 }
1447             }
1448             // curNode do ENTER PUSH animation
1449             for (auto iter : curNavList) {
1450                 auto curNode = iter.Upgrade();
1451                 CHECK_NULL_VOID(curNode);
1452                 auto curDestination = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
1453                 if (curDestination) {
1454                     curDestination->StartSystemTransitionPush(true);
1455                 }
1456             }
1457     }, option.GetOnFinishEvent());
1458     if (newPushAnimation) {
1459         pushAnimations_.emplace_back(newPushAnimation);
1460     }
1461     isOnAnimation_ = true;
1462 }
1463 
PreNodeFinishCallback(const RefPtr<FrameNode> & preNode)1464 void NavigationGroupNode::PreNodeFinishCallback(const RefPtr<FrameNode>& preNode)
1465 {
1466     CHECK_NULL_VOID(preNode);
1467     if (preNode->GetTag() == V2::NAVBAR_ETS_TAG) {
1468         auto preNavbar = AceType::DynamicCast<NavBarNode>(preNode);
1469         CHECK_NULL_VOID(preNavbar);
1470         preNavbar->SystemTransitionPushAction(false);
1471         bool needSetInvisible = preNavbar->GetTransitionType() == PageTransitionType::EXIT_PUSH;
1472         SetNeedSetInvisible(needSetInvisible);
1473         if (needSetInvisible && GetNavigationMode() == NavigationMode::STACK) {
1474             auto property = preNavbar->GetLayoutProperty();
1475             CHECK_NULL_VOID(property);
1476             property->UpdateVisibility(VisibleType::INVISIBLE);
1477             preNavbar->SetJSViewActive(false);
1478             NotifyPageHide();
1479         }
1480         return;
1481     }
1482     if (preNode->GetTag() == V2::NAVDESTINATION_VIEW_ETS_TAG) {
1483         auto preDestination = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
1484         if (preDestination && preDestination->NeedRemoveInPush()) {
1485             hideNodes_.emplace_back(std::make_pair(preDestination, true));
1486         }
1487         preDestination->SystemTransitionPushCallback(false);
1488     }
1489 }
1490 
TransitionWithDialogPush(const RefPtr<FrameNode> & preNode,const RefPtr<FrameNode> & curNode,bool isNavBar)1491 void NavigationGroupNode::TransitionWithDialogPush(const RefPtr<FrameNode>& preNode, const RefPtr<FrameNode>& curNode,
1492     bool isNavBar)
1493 {
1494     if (!preNode || !curNode) {
1495         TAG_LOGE(AceLogTag::ACE_NAVIGATION, "dialog push animation terminated");
1496         return;
1497     }
1498     CleanPushAnimations();
1499 
1500     // initialization
1501     bool isNavbarNeedAnimation = preLastStandardIndex_ == -1 || isNavBar;
1502     std::vector<WeakPtr<FrameNode>> prevNavList;
1503     InitPushPreList(preNode, prevNavList, isNavbarNeedAnimation);
1504     std::vector<WeakPtr<FrameNode>> curNavList;
1505     InitPushCurList(curNode, curNavList);
1506     AnimationFinishCallback callback = [weakNavigation = WeakClaim(this), prevNavList, curNavList] {
1507             PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH, true);
1508             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation dialog push animation end");
1509             auto navigation = weakNavigation.Upgrade();
1510             CHECK_NULL_VOID(navigation);
1511             for (auto iter : prevNavList) {
1512                 auto preNode = iter.Upgrade();
1513                 CHECK_NULL_VOID(preNode);
1514                 navigation->PreNodeFinishCallback(preNode);
1515             }
1516             for (auto iter : curNavList) {
1517                 auto curNode = iter.Upgrade();
1518                 CHECK_NULL_VOID(curNode);
1519                 auto curNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
1520                 CHECK_NULL_VOID(curNavDestination);
1521                 curNavDestination->SystemTransitionPushCallback(true);
1522             }
1523             navigation->RemoveDialogDestination();
1524             navigation->OnAccessibilityEvent(AccessibilityEventType::PAGE_CHANGE);
1525             navigation->isOnAnimation_ = false;
1526             navigation->CleanPushAnimations();
1527         };
1528     CreateAnimationWithDialogPush(callback, prevNavList, curNavList);
1529 }
1530 
InitDialogTransition(const RefPtr<NavDestinationGroupNode> & node,bool isTransitionIn)1531 void NavigationGroupNode::InitDialogTransition(const RefPtr<NavDestinationGroupNode>& node, bool isTransitionIn)
1532 {
1533     CHECK_NULL_VOID(node);
1534     auto contentNode = AceType::DynamicCast<FrameNode>(node->GetContentNode());
1535     CHECK_NULL_VOID(contentNode);
1536     auto context = contentNode->GetRenderContext();
1537     CHECK_NULL_VOID(context);
1538     if (isTransitionIn) {
1539         context->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
1540         return;
1541     }
1542     context->UpdateTransformTranslate({ 0.0f,
1543         contentNode->GetGeometryNode()->GetFrameSize().Height(), 0.0f });
1544 }
1545 
StartDialogtransition(const RefPtr<FrameNode> & preNode,const RefPtr<FrameNode> & curNode,bool isTransitionIn)1546 void NavigationGroupNode::StartDialogtransition(const RefPtr<FrameNode>& preNode,
1547     const RefPtr<FrameNode>& curNode, bool isTransitionIn)
1548 {
1549     AnimationOption option;
1550     const RefPtr<InterpolatingSpring> curve =
1551         AceType::MakeRefPtr<InterpolatingSpring>(0.0f, CURVE_MASS, CURVE_STIFFNESS, CURVE_DAMPING);
1552     const float defaultAmplitudePx = 0.005f;
1553     curve->UpdateMinimumAmplitudeRatio(defaultAmplitudePx);
1554     option.SetCurve(curve);
1555     option.SetFillMode(FillMode::FORWARDS);
1556     if (isTransitionIn) {
1557         DialogTransitionPushAnimation(preNode, curNode, option);
1558     } else {
1559         DialogTransitionPopAnimation(preNode, curNode, option);
1560     }
1561 }
1562 
DialogTransitionPushAnimation(const RefPtr<FrameNode> & preNode,const RefPtr<FrameNode> & curNode,AnimationOption option)1563 void NavigationGroupNode::DialogTransitionPushAnimation(const RefPtr<FrameNode>& preNode,
1564     const RefPtr<FrameNode>& curNode, AnimationOption option)
1565 {
1566     CHECK_NULL_VOID(curNode);
1567     auto curNavdestination = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
1568     CHECK_NULL_VOID(curNavdestination);
1569     int32_t end = curNavdestination->GetIndex();
1570     auto navigationPattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1571     CHECK_NULL_VOID(navigationPattern);
1572     const auto& navDestinationNodesCur = navigationPattern->GetAllNavDestinationNodes();
1573     int32_t start = 0;
1574     if (preNode && preNode->GetTag() == V2::NAVDESTINATION_VIEW_ETS_TAG) {
1575         auto navdestination = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
1576         CHECK_NULL_VOID(navdestination);
1577         start = navdestination->GetIndex() + 1;
1578     }
1579     // find the nodes need to do upward ENTER translation
1580     std::vector<WeakPtr<NavDestinationGroupNode>> curNavList;
1581     for (int32_t index = start; index <= end; index++) {
1582         auto navdestination = GetNavDestinationNode(navDestinationNodesCur[index].second);
1583         CHECK_NULL_VOID(navdestination);
1584         auto curNode = AceType::DynamicCast<FrameNode>(navdestination);
1585         CHECK_NULL_VOID(curNode);
1586         auto curNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
1587         CHECK_NULL_VOID(curNavDestination);
1588         curNavDestination->InitDialogTransition(false);
1589         curNavList.emplace_back(WeakPtr<NavDestinationGroupNode>(curNavDestination));
1590     }
1591     CleanPushAnimations();
1592     option.SetOnFinishEvent([weakNavigation = WeakClaim(this)] {
1593         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation dialog push animation end");
1594         auto navigation = weakNavigation.Upgrade();
1595         CHECK_NULL_VOID(navigation);
1596         navigation->CleanPushAnimations();
1597     });
1598     auto newPushAnimation = AnimationUtils::StartAnimation(option,
1599         [curNavList]() {
1600             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation dialog push animation start");
1601             for (auto iter: curNavList) {
1602                 auto curNode = iter.Upgrade();
1603                 if (curNode) {
1604                     curNode->InitDialogTransition(true);
1605                 }
1606             }
1607         },
1608     option.GetOnFinishEvent());
1609     if (newPushAnimation) {
1610         pushAnimations_.emplace_back(newPushAnimation);
1611     }
1612 }
1613 
FindNodesPoped(const RefPtr<FrameNode> & preNode,const RefPtr<FrameNode> & curNode)1614 std::vector<WeakPtr<NavDestinationGroupNode>> NavigationGroupNode::FindNodesPoped(
1615     const RefPtr<FrameNode>& preNode, const RefPtr<FrameNode>& curNode)
1616 {
1617     std::vector<WeakPtr<NavDestinationGroupNode>> preNavList;
1618     auto preNavdestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
1619     CHECK_NULL_RETURN(preNavdestinationNode, preNavList);
1620     auto end = preNavdestinationNode->GetIndex();
1621     auto navigationPattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1622     CHECK_NULL_RETURN(navigationPattern, preNavList);
1623     const auto& navDestinationNodesPre = navigationPattern->GetAllNavDestinationNodesPrev();
1624     int32_t start = 0;
1625     if (curNode && curNode->GetTag() == V2::NAVDESTINATION_VIEW_ETS_TAG) {
1626         auto curNavdestination = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
1627         CHECK_NULL_RETURN(curNavdestination, preNavList);
1628         start = curNavdestination->GetIndex() + 1;
1629     }
1630     // find the nodes need to do downward EXIT translation
1631     for (int32_t index = start; index <= end; index++) {
1632         auto node = GetNavDestinationNode(navDestinationNodesPre[index].second.Upgrade());
1633         if (node) {
1634             auto preNode = AceType::DynamicCast<FrameNode>(node);
1635             CHECK_NULL_RETURN(preNode, preNavList);
1636             auto preNavDesNode = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
1637             CHECK_NULL_RETURN(preNavDesNode, preNavList);
1638             preNavDesNode->InitDialogTransition(true);
1639             preNavList.emplace_back(WeakPtr<NavDestinationGroupNode>(preNavDesNode));
1640         }
1641     }
1642     return preNavList;
1643 }
1644 
DialogTransitionPopAnimation(const RefPtr<FrameNode> & preNode,const RefPtr<FrameNode> & curNode,AnimationOption option)1645 void NavigationGroupNode::DialogTransitionPopAnimation(const RefPtr<FrameNode>& preNode,
1646     const RefPtr<FrameNode>& curNode, AnimationOption option)
1647 {
1648     auto navigationPattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1649     CHECK_NULL_VOID(navigationPattern);
1650     auto preNavList = FindNodesPoped(preNode, curNode);
1651     CleanPopAnimations();
1652     option.SetOnFinishEvent(
1653         [preNavList, weakNavigation = WeakClaim(this)] {
1654             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation dialog pop animation end");
1655             for (auto iter: preNavList) {
1656                 auto preNode = iter.Upgrade();
1657                 CHECK_NULL_VOID(preNode);
1658                 auto parent = preNode->GetParent();
1659                 CHECK_NULL_VOID(parent);
1660                 parent->RemoveChild(preNode);
1661                 parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1662             }
1663             auto context = PipelineContext::GetCurrentContext();
1664             CHECK_NULL_VOID(context);
1665             context->MarkNeedFlushMouseEvent();
1666             auto navigation = weakNavigation.Upgrade();
1667             CHECK_NULL_VOID(navigation);
1668             navigation->CleanPopAnimations();
1669         });
1670     auto newPopAnimation = AnimationUtils::StartAnimation(
1671         option, [weakNavigation = WeakClaim(this), preNavList]() {
1672             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation dialog pop animation start");
1673             auto navigation = weakNavigation.Upgrade();
1674             CHECK_NULL_VOID(navigation);
1675             for (auto iter: preNavList) {
1676                 auto preNode = iter.Upgrade();
1677                 CHECK_NULL_VOID(preNode);
1678                 preNode->InitDialogTransition(false);
1679             }
1680     }, option.GetOnFinishEvent());
1681     if (newPopAnimation) {
1682         popAnimations_.emplace_back(newPopAnimation);
1683     }
1684 }
1685 
InitPopPreList(const RefPtr<FrameNode> & preNode,std::vector<WeakPtr<FrameNode>> & preNavList)1686 void NavigationGroupNode::InitPopPreList(const RefPtr<FrameNode>& preNode, std::vector<WeakPtr<FrameNode>>& preNavList)
1687 {
1688     // find all the nodes need to do EXIT_POP
1689     int32_t preStartIndex = preLastStandardIndex_;
1690     if (preStartIndex == -1) {
1691         // eg. clear + push page1
1692         preStartIndex = 0;
1693     }
1694     auto preNavdestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
1695     CHECK_NULL_VOID(preNavdestinationNode);
1696     auto navigationPattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1697     CHECK_NULL_VOID(navigationPattern);
1698     const auto& preNavDestinationNodes = navigationPattern->GetAllNavDestinationNodesPrev();
1699 
1700     // find the nodes need to do EXIT_POP
1701     for (int32_t index = preStartIndex; index < static_cast<int32_t>(preNavDestinationNodes.size()); index++) {
1702         auto node = GetNavDestinationNode(preNavDestinationNodes[index].second.Upgrade());
1703         CHECK_NULL_VOID(node);
1704         auto preNode = AceType::DynamicCast<FrameNode>(node);
1705         CHECK_NULL_VOID(preNode);
1706         auto preNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
1707         if (preNavDestination) {
1708             preNavDestination->InitSystemTransitionPop(false);
1709             preNavList.emplace_back(WeakPtr<FrameNode>(preNode));
1710         }
1711     }
1712 }
1713 
InitPopCurList(const RefPtr<FrameNode> & curNode,std::vector<WeakPtr<FrameNode>> & curNavList,bool isNavbarNeedAnimation)1714 void NavigationGroupNode::InitPopCurList(const RefPtr<FrameNode>& curNode, std::vector<WeakPtr<FrameNode>>& curNavList,
1715     bool isNavbarNeedAnimation)
1716 {
1717     auto navigationPattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1718     CHECK_NULL_VOID(navigationPattern);
1719     auto curNavdestionNodes = navigationPattern->GetAllNavDestinationNodes();
1720     auto curStartIndex = lastStandardIndex_;
1721 
1722     // navBar + D or navBar should be in animation
1723     if (isNavbarNeedAnimation) {
1724         curStartIndex = 0;
1725     }
1726     // if navBar should be in animation, do initialization and visibility should be true
1727     if (isNavbarNeedAnimation && navigationPattern->GetNavigationMode() == NavigationMode::STACK) {
1728         auto preNode = AceType::DynamicCast<FrameNode>(GetNavBarNode());
1729         if (preNode) {
1730             auto navBarNode = AceType::DynamicCast<NavBarNode>(preNode);
1731             CHECK_NULL_VOID(navBarNode);
1732             navBarNode->InitSystemTransitionPop();
1733             curNavList.emplace_back(WeakPtr<FrameNode>(preNode));
1734             SetNeedSetInvisible(false);
1735         }
1736     }
1737     int32_t size = static_cast<int32_t>(curNavdestionNodes.size());
1738     if (size == 0) {
1739         return;
1740     }
1741     // find the nodes need to do ENTER_POP
1742     for (int32_t index = curStartIndex; index < size; index++) {
1743         auto node = GetNavDestinationNode(curNavdestionNodes[index].second);
1744         CHECK_NULL_VOID(node);
1745         auto curNode = AceType::DynamicCast<FrameNode>(node);
1746         if (curNode) {
1747             auto navdestination = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
1748             CHECK_NULL_VOID(navdestination);
1749             navdestination->InitSystemTransitionPop(true);
1750             curNavList.emplace_back(WeakPtr<FrameNode>(curNode));
1751         }
1752     }
1753 }
1754 
InitPushPreList(const RefPtr<FrameNode> & preNode,std::vector<WeakPtr<FrameNode>> & prevNavList,bool isNavbarNeedAnimation)1755 void NavigationGroupNode::InitPushPreList(const RefPtr<FrameNode>& preNode,
1756     std::vector<WeakPtr<FrameNode>>& prevNavList, bool isNavbarNeedAnimation)
1757 {
1758     auto navigationPattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1759     CHECK_NULL_VOID(navigationPattern);
1760     auto stack = navigationPattern->GetNavigationStack();
1761     auto& preNavdestinationNodes = navigationPattern->GetAllNavDestinationNodesPrev();
1762     auto preStartIndex = preLastStandardIndex_;
1763 
1764     // find the pre last standard index, if there is no pre standard or pre node is single navbar
1765     if (isNavbarNeedAnimation) {
1766         preStartIndex = 0;
1767     }
1768     // if pre node is nav bar or one of preNodes is nav bar and only stack with navbar's animation
1769     if (isNavbarNeedAnimation&& navigationPattern->GetNavigationMode() == NavigationMode::STACK) {
1770         auto preNode = AceType::DynamicCast<FrameNode>(GetNavBarNode());
1771         CHECK_NULL_VOID(preNode);
1772         auto preNavbar = AceType::DynamicCast<NavBarNode>(preNode);
1773         if (preNavbar) {
1774             SetNeedSetInvisible(false);
1775             preNavbar->SystemTransitionPushAction(true);
1776             prevNavList.emplace_back(WeakPtr<FrameNode>(preNode));
1777         }
1778     }
1779     int32_t size = static_cast<int32_t>(preNavdestinationNodes.size());
1780     if (size == 0) {
1781         return;
1782     }
1783     // find the nodes need to do EXIT_PUSH
1784     for (int32_t index = preStartIndex; index < size; index++) {
1785         auto node = GetNavDestinationNode(preNavdestinationNodes[index].second.Upgrade());
1786         CHECK_NULL_VOID(node);
1787         auto preNode = AceType::DynamicCast<FrameNode>(node);
1788         CHECK_NULL_VOID(preNode);
1789         auto preNavdestination = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
1790         if (preNavdestination) {
1791             preNavdestination->InitSystemTransitionPush(false);
1792             prevNavList.emplace_back(WeakPtr<FrameNode>(preNode));
1793         }
1794     }
1795 }
1796 
InitPushCurList(const RefPtr<FrameNode> & curNode,std::vector<WeakPtr<FrameNode>> & curNavList)1797 void NavigationGroupNode::InitPushCurList(const RefPtr<FrameNode>& curNode, std::vector<WeakPtr<FrameNode>>& curNavList)
1798 {
1799     // find the nodes need to do ENTER_PUSH
1800     auto navigationPattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1801     CHECK_NULL_VOID(navigationPattern);
1802     auto curNavdestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
1803     CHECK_NULL_VOID(curNavdestinationNode);
1804     auto curEndIndex = curNavdestinationNode->GetIndex();
1805     auto curStartIndex = lastStandardIndex_;
1806     auto stack = navigationPattern->GetNavigationStack();
1807     for (int32_t index = curStartIndex; index <= curEndIndex; index++) {
1808         auto node = GetNavDestinationNode(stack->Get(index));
1809         CHECK_NULL_VOID(node);
1810         auto curNode = AceType::DynamicCast<FrameNode>(node);
1811         CHECK_NULL_VOID(curNode);
1812         auto curNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
1813         CHECK_NULL_VOID(curNavDestination);
1814         curNavDestination->InitSystemTransitionPush(true);
1815         curNavList.emplace_back(WeakPtr<FrameNode>(curNode));
1816     }
1817 }
1818 } // namespace OHOS::Ace::NG
1819