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