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