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