1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
17
18 #include "base/log/dump_log.h"
19 #include "base/log/event_report.h"
20 #include "base/perfmonitor/perf_constants.h"
21 #include "base/ressched/ressched_report.h"
22 #include "core/common/ime/input_method_manager.h"
23 #include "core/components_ng/manager/avoid_info/avoid_info_manager.h"
24 #include "core/components_ng/pattern/navigation/nav_bar_node.h"
25 #include "core/components_ng/pattern/navigation/nav_bar_pattern.h"
26 #include "core/components_ng/pattern/navigation/navigation_drag_bar_pattern.h"
27 #include "core/components_ng/pattern/navigation/navigation_model_data.h"
28 #include "core/components_ng/pattern/navigation/navigation_title_util.h"
29 #include "core/components_ng/pattern/navigation/title_bar_pattern.h"
30 #include "core/components_ng/pattern/navigation/tool_bar_node.h"
31 #include "core/components_ng/pattern/navigation/tool_bar_pattern.h"
32 #include "core/components_ng/pattern/divider/divider_render_property.h"
33
34 #ifdef WINDOW_SCENE_SUPPORTED
35 #include "core/components_ng/pattern/window_scene/helper/window_scene_helper.h"
36 #endif
37 namespace OHOS::Ace::NG {
38
39 constexpr int32_t NAVIMODE_CHANGE_ANIMATION_DURATION = 250;
40 constexpr int32_t OPACITY_ANIMATION_DURATION_APPEAR = 150;
41 constexpr int32_t OPACITY_ANIMATION_DURATION_DISAPPEAR = 250;
42 constexpr int32_t EMPTY_DESTINATION_CHILD_SIZE = 1;
43 constexpr Dimension DEFAULT_DRAG_REGION = 12.0_vp;
44 constexpr Dimension DEFAULT_DRAG_BAR_HOT_ZONE = 12.0_vp;
45 constexpr float DEFAULT_HALF = 2.0f;
46 const Color MASK_COLOR = Color::FromARGB(25, 0, 0, 0);
47 constexpr int32_t PAGE_NODES = 1000;
48 constexpr int32_t PAGE_DEPTH = 300;
49 constexpr int32_t HALF_POSITION = 50;
50 constexpr int32_t END_POSITION = 100;
51 constexpr Dimension DRAG_BAR_RADIUS = 6.0_vp;
52 constexpr Dimension DRAG_BAR_BLUR_RADIUS = 20.0_vp;
53 constexpr Dimension DRAG_BAR_ITEM_RADIUS = 1.0_vp;
54 constexpr int32_t SECOND_ZINDEX_VALUE = 2;
55 constexpr int32_t INVALID_ANIMATION_ID = -1;
56 namespace {
57 constexpr int32_t MODE_SWITCH_ANIMATION_DURATION = 500; // ms
58 const RefPtr<CubicCurve> MODE_SWITCH_CURVE = AceType::MakeRefPtr<CubicCurve>(0.2f, 0.2f, 0.1f, 1.0f);
59
CreatePercentGradientColor(int32_t percent,Color color)60 GradientColor CreatePercentGradientColor(int32_t percent, Color color)
61 {
62 NG::GradientColor gredient = GradientColor(color);
63 gredient.SetDimension(CalcDimension(percent, DimensionUnit::PERCENT));
64 return gredient;
65 }
66
BuildNavDestinationInfoFromContext(const std::string & navigationId,NavDestinationState state,const RefPtr<NavDestinationContext> & context,bool isFrom,std::optional<NavDestinationInfo> & info)67 void BuildNavDestinationInfoFromContext(const std::string& navigationId, NavDestinationState state,
68 const RefPtr<NavDestinationContext>& context, bool isFrom, std::optional<NavDestinationInfo>& info)
69 {
70 if (!context) {
71 info.reset();
72 return;
73 }
74
75 int32_t index = isFrom ? context->GetPreIndex() : context->GetIndex();
76 std::string navDestinationId = std::to_string(context->GetNavDestinationId());
77 std::string name;
78 napi_value param = nullptr;
79 auto pathInfo = context->GetNavPathInfo();
80 if (pathInfo) {
81 name = pathInfo->GetName();
82 param = pathInfo->GetParamObj();
83 }
84 NavDestinationMode mode = context->GetMode();
85 int32_t uniqueId = context->GetUniqueId();
86 info = std::make_optional<NavDestinationInfo>(navigationId, name, state, index, param,
87 navDestinationId, mode, uniqueId);
88 }
89
LogCustomAnimationStart(const RefPtr<NavDestinationGroupNode> & preTopDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,NavigationOperation operation)90 void LogCustomAnimationStart(const RefPtr<NavDestinationGroupNode>& preTopDestination,
91 const RefPtr<NavDestinationGroupNode>& newTopNavDestination, NavigationOperation operation)
92 {
93 RefPtr<NavDestinationPattern> prePattern =
94 preTopDestination ? preTopDestination->GetPattern<NavDestinationPattern>() : nullptr;
95 RefPtr<NavDestinationPattern> newPattern =
96 newTopNavDestination ? newTopNavDestination->GetPattern<NavDestinationPattern>() : nullptr;
97 TAG_LOGI(AceLogTag::ACE_NAVIGATION,
98 "custom animation start: operation: %{public}d, pre name: %{public}s, id: %{public}s."
99 "top name: %{public}s, id: %{public}s",
100 operation, prePattern ? prePattern->GetName().c_str() : "null",
101 prePattern ? std::to_string(prePattern->GetNavDestinationId()).c_str() : "null",
102 newPattern ? newPattern->GetName().c_str() : "null",
103 newPattern ? std::to_string(newPattern->GetNavDestinationId()).c_str() : "null");
104 }
105
TriggerNavDestinationTransition(const RefPtr<NavDestinationGroupNode> & navDestination,NavigationOperation operation,bool isEnter)106 int32_t TriggerNavDestinationTransition(const RefPtr<NavDestinationGroupNode>& navDestination,
107 NavigationOperation operation, bool isEnter)
108 {
109 CHECK_NULL_RETURN(navDestination, INVALID_ANIMATION_ID);
110 return navDestination->DoTransition(operation, isEnter);
111 }
112 } // namespace
113
NavigationPattern()114 NavigationPattern::NavigationPattern()
115 {
116 navigationController_ = std::make_shared<InnerNavigationController>(WeakClaim(this), Container::CurrentId());
117 }
118
GetTitleBarRenderContext()119 RefPtr<RenderContext> NavigationPattern::GetTitleBarRenderContext()
120 {
121 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
122 CHECK_NULL_RETURN(hostNode, nullptr);
123 auto layoutProperty = GetLayoutProperty<NavigationLayoutProperty>();
124 CHECK_NULL_RETURN(layoutProperty, nullptr);
125 auto contentNode = AceType::DynamicCast<FrameNode>(hostNode->GetContentNode());
126 CHECK_NULL_RETURN(contentNode, nullptr);
127 if (contentNode->FindChildNodeOfClass<NavDestinationGroupNode>()) {
128 auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
129 CHECK_NULL_RETURN(navBarNode, nullptr);
130 auto renderContext = navBarNode->GetRenderContext();
131 return renderContext;
132 } else {
133 auto renderContext = contentNode->GetRenderContext();
134 return renderContext;
135 }
136 }
137
DoAnimation(NavigationMode usrNavigationMode)138 void NavigationPattern::DoAnimation(NavigationMode usrNavigationMode)
139 {
140 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
141 CHECK_NULL_VOID(hostNode);
142 auto layoutProperty = GetLayoutProperty<NavigationLayoutProperty>();
143 CHECK_NULL_VOID(layoutProperty);
144
145 auto context = PipelineContext::GetCurrentContext();
146 CHECK_NULL_VOID(context);
147 layoutProperty->UpdateNavigationMode(navigationMode_);
148 hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
149 AnimationOption option = AnimationOption();
150 option.SetDuration(NAVIMODE_CHANGE_ANIMATION_DURATION);
151 option.SetCurve(Curves::FRICTION);
152 option.SetFillMode(FillMode::FORWARDS);
153 AnimationOption optionAlpha = AnimationOption();
154 optionAlpha.SetCurve(Curves::SHARP);
155 optionAlpha.SetFillMode(FillMode::FORWARDS);
156 auto renderContext = GetTitleBarRenderContext();
157 CHECK_NULL_VOID(renderContext);
158
159 std::function<void()> finishCallback = [optionAlpha, renderContext, hostNode]() {
160 renderContext->OpacityAnimation(optionAlpha, 0, 1);
161 hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
162 };
163
164 context->OpenImplicitAnimation(option, option.GetCurve(), finishCallback);
165 layoutProperty->UpdateNavigationMode(usrNavigationMode);
166 hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
167 context->FlushUITasks();
168 if (usrNavigationMode == NavigationMode::STACK || navigationMode_ == NavigationMode::SPLIT) {
169 optionAlpha.SetDuration(OPACITY_ANIMATION_DURATION_DISAPPEAR);
170 renderContext->OpacityAnimation(optionAlpha, 1, 0);
171 } else if (usrNavigationMode == NavigationMode::SPLIT || navigationMode_ == NavigationMode::STACK) {
172 optionAlpha.SetDuration(OPACITY_ANIMATION_DURATION_APPEAR);
173 renderContext->OpacityAnimation(optionAlpha, 0, 1);
174 }
175 context->CloseImplicitAnimation();
176 navigationMode_ = usrNavigationMode;
177 }
178
OnAttachToFrameNode()179 void NavigationPattern::OnAttachToFrameNode()
180 {
181 auto host = GetHost();
182 CHECK_NULL_VOID(host);
183 auto pipelineContext = PipelineContext::GetCurrentContext();
184 CHECK_NULL_VOID(pipelineContext);
185 pipelineContext->AddWindowStateChangedCallback(host->GetId());
186 pipelineContext->AddWindowSizeChangeCallback(host->GetId());
187
188 auto theme = NavigationGetTheme();
189 if (theme && theme->GetNavBarUnfocusEffectEnable()) {
190 pipelineContext->AddWindowFocusChangedCallback(host->GetId());
191 }
192 if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
193 SafeAreaExpandOpts opts = { .type = SAFE_AREA_TYPE_ALL, .edges = SAFE_AREA_EDGE_ALL };
194 host->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
195 }
196 }
197
OnDetachFromFrameNode(FrameNode * frameNode)198 void NavigationPattern::OnDetachFromFrameNode(FrameNode* frameNode)
199 {
200 auto id = frameNode->GetId();
201 auto pipeline = AceType::DynamicCast<PipelineContext>(PipelineBase::GetCurrentContext());
202 CHECK_NULL_VOID(pipeline);
203 pipeline->RemoveWindowStateChangedCallback(id);
204 pipeline->RemoveWindowSizeChangeCallback(id);
205 }
206
207
DoNavbarHideAnimation(const RefPtr<NavigationGroupNode> & hostNode)208 void NavigationPattern::DoNavbarHideAnimation(const RefPtr<NavigationGroupNode>& hostNode)
209 {
210 AnimationOption option;
211 option.SetCurve(MODE_SWITCH_CURVE);
212 option.SetFillMode(FillMode::FORWARDS);
213 option.SetDuration(MODE_SWITCH_ANIMATION_DURATION);
214 AnimationUtils::Animate(option, [weakHost = WeakPtr<NavigationGroupNode>(hostNode)]() {
215 auto hostNode = weakHost.Upgrade();
216 CHECK_NULL_VOID(hostNode);
217 auto layoutProperty = AceType::DynamicCast<NavigationLayoutProperty>(hostNode->GetLayoutProperty());
218 CHECK_NULL_VOID(layoutProperty);
219 bool hideNavBar = layoutProperty->GetHideNavBarValue(false);
220 auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
221 CHECK_NULL_VOID(navBarNode);
222 auto navBarLayoutProperty = navBarNode->GetLayoutProperty();
223 CHECK_NULL_VOID(navBarLayoutProperty);
224 navBarLayoutProperty->UpdateVisibility(hideNavBar ? VisibleType::INVISIBLE : VisibleType::VISIBLE, true);
225 hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
226 hostNode->GetContext()->FlushUITasks();
227 });
228 }
229
InitDragBarEvent()230 void NavigationPattern::InitDragBarEvent()
231 {
232 auto dragBarNode = AceType::DynamicCast<FrameNode>(GetDragBarNode());
233 CHECK_NULL_VOID(dragBarNode);
234 auto dragGestureHub = dragBarNode->GetOrCreateGestureEventHub();
235 CHECK_NULL_VOID(dragGestureHub);
236 InitDragBarPanEvent(dragGestureHub);
237 InitTouchEvent(dragGestureHub);
238
239 // clear divider hover and pan event
240 auto dividerNode = GetDividerNode();
241 CHECK_NULL_VOID(dividerNode);
242 auto dividerGestureHub = dividerNode->GetOrCreateGestureEventHub();
243 CHECK_NULL_VOID(dividerGestureHub);
244 auto dividerInputHub = dividerNode->GetOrCreateInputEventHub();
245 CHECK_NULL_VOID(dividerInputHub);
246 if (hoverEvent_) {
247 dividerInputHub->RemoveOnHoverEvent(hoverEvent_);
248 hoverEvent_.Reset();
249 }
250 if (panEvent_) {
251 dividerGestureHub->RemovePanEvent(panEvent_);
252 panEvent_.Reset();
253 }
254 }
255
ClearDragBarEvent()256 void NavigationPattern::ClearDragBarEvent()
257 {
258 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
259 CHECK_NULL_VOID(hostNode);
260 auto dragBarNode = AceType::DynamicCast<FrameNode>(GetDragBarNode());
261 CHECK_NULL_VOID(dragBarNode);
262 auto dragGestureHub = dragBarNode->GetOrCreateGestureEventHub();
263 CHECK_NULL_VOID(dragGestureHub);
264
265 // clear drag bar touch and pan event
266 if (touchEvent_) {
267 dragGestureHub->RemoveTouchEvent(touchEvent_);
268 touchEvent_.Reset();
269 }
270 if (dragBarPanEvent_) {
271 dragGestureHub->RemovePanEvent(dragBarPanEvent_);
272 dragBarPanEvent_.Reset();
273 }
274
275 hostNode->RemoveChild(dragBarNode);
276 hostNode->SetDragBarNode(nullptr);
277 }
278
BuildDragBar()279 void NavigationPattern::BuildDragBar()
280 {
281 if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TEN)) {
282 return;
283 }
284 if (enableDragBar_) {
285 if (GetDragBarNode()) {
286 // if dragBar is already in navigation, do nothing
287 return;
288 }
289 // create drag bar and init drag bar gesture event
290 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
291 CHECK_NULL_VOID(hostNode);
292 CreateDragBarNode(hostNode);
293 InitDragBarEvent();
294 return;
295 }
296 auto dividerNode = GetDividerNode();
297 CHECK_NULL_VOID(dividerNode);
298 auto dividerGestureHub = dividerNode->GetOrCreateGestureEventHub();
299 CHECK_NULL_VOID(dividerGestureHub);
300 auto dividerInputHub = dividerNode->GetOrCreateInputEventHub();
301 CHECK_NULL_VOID(dividerInputHub);
302 InitDividerPanEvent(dividerGestureHub);
303 InitDividerMouseEvent(dividerInputHub);
304 if (GetDragBarNode()) {
305 // clear drag bar gesture event and remove dragBar
306 ClearDragBarEvent();
307 }
308 }
309
OnModifyDone()310 void NavigationPattern::OnModifyDone()
311 {
312 // !!! Do not add operations about NavPathStack here, see @SyncWithJsStackIfNeeded
313 Pattern::OnModifyDone();
314 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
315 CHECK_NULL_VOID(hostNode);
316 auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
317 CHECK_NULL_VOID(navBarNode);
318 navBarNode->MarkModifyDone();
319 isRightToLeft_ = AceApplicationInfo::GetInstance().IsRightToLeft();
320
321 auto pipeline = PipelineContext::GetCurrentContext();
322 CHECK_NULL_VOID(pipeline);
323 BuildDragBar();
324
325 auto layoutProperty = hostNode->GetLayoutProperty<NavigationLayoutProperty>();
326 CHECK_NULL_VOID(layoutProperty);
327 auto curNavBarPosition = layoutProperty->GetNavBarPositionValue(NavBarPosition::START);
328 if (preNavBarPosition_.has_value() && preNavBarPosition_.value() != curNavBarPosition) {
329 MarkAllNavDestinationDirtyIfNeeded(hostNode);
330 }
331 preNavBarPosition_ = curNavBarPosition;
332
333 auto&& opts = layoutProperty->GetSafeAreaExpandOpts();
334 if (opts) {
335 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "Navigation SafArea expand as %{public}s", opts->ToString().c_str());
336 uint8_t ignoreExpandKeyboard = 0x11;
337 SafeAreaExpandOpts optsExceptKeyboard = { .type = opts->type & ignoreExpandKeyboard,
338 .edges = opts->edges };
339 navBarNode->GetLayoutProperty()->UpdateSafeAreaExpandOpts(optsExceptKeyboard);
340 navBarNode->MarkModifyDone();
341
342 auto navigationContentNode = AceType::DynamicCast<FrameNode>(hostNode->GetContentNode());
343 CHECK_NULL_VOID(navigationContentNode);
344 navigationContentNode->GetLayoutProperty()->UpdateSafeAreaExpandOpts(optsExceptKeyboard);
345 navigationContentNode->MarkModifyDone();
346
347 auto dividerNode = AceType::DynamicCast<FrameNode>(hostNode->GetDividerNode());
348 CHECK_NULL_VOID(dividerNode);
349 dividerNode->GetLayoutProperty()->UpdateSafeAreaExpandOpts(optsExceptKeyboard);
350 dividerNode->MarkModifyDone();
351 }
352
353 bool enableModeChangeAnimation = layoutProperty->GetEnableModeChangeAnimation().value_or(true);
354 if (enableModeChangeAnimation && GetNavigationMode() == NavigationMode::SPLIT && GetNavBarVisibilityChange()) {
355 DoNavbarHideAnimation(hostNode);
356 }
357
358 // AddRecoverableNavigation function will check inside whether current navigation can be recovered
359 pipeline->GetNavigationManager()->AddRecoverableNavigation(hostNode->GetCurId(), hostNode);
360 RestoreJsStackIfNeeded();
361 UpdateToobarFocusColor();
362 UpdateDividerBackgroundColor();
363 }
364
SetSystemBarStyle(const RefPtr<SystemBarStyle> & style)365 void NavigationPattern::SetSystemBarStyle(const RefPtr<SystemBarStyle>& style)
366 {
367 auto host = GetHost();
368 CHECK_NULL_VOID(host);
369 auto pipeline = host->GetContext();
370 CHECK_NULL_VOID(pipeline);
371 auto windowManager = pipeline->GetWindowManager();
372 CHECK_NULL_VOID(windowManager);
373 if (!backupStyle_.has_value()) {
374 backupStyle_ = windowManager->GetSystemBarStyle();
375 }
376 currStyle_ = style;
377
378 // The systemBarStyle may only take effect when navigation fills the entire page.
379 if (!isFullPageNavigation_) {
380 return;
381 }
382
383 // When there is NavDestination in the stack, the systemBarStyle set for Navigation does not take effect.
384 do {
385 if (!navigationStack_) {
386 break;
387 }
388 auto topPath = navigationStack_->GetTopNavPath();
389 if (!topPath.has_value()) {
390 break;
391 }
392 auto topNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(
393 NavigationGroupNode::GetNavDestinationNode(topPath->second));
394 if (topNavDestination) {
395 return;
396 }
397 } while (false);
398
399 /**
400 * When developers provide a valid style to systemBarStyle, we should set the style to window;
401 * when 'undefined' was provided, we should restore the style.
402 */
403 if (currStyle_.value() != nullptr) {
404 windowManager->SetSystemBarStyle(currStyle_.value());
405 } else {
406 TryRestoreSystemBarStyle(windowManager);
407 }
408 }
409
OnAttachToMainTree()410 void NavigationPattern::OnAttachToMainTree()
411 {
412 auto host = GetHost();
413 CHECK_NULL_VOID(host);
414 InitPageNode(host);
415 InitFoldState();
416 RegisterAvoidInfoChangeListener(host);
417 }
418
InitFoldState()419 void NavigationPattern::InitFoldState()
420 {
421 auto container = Container::Current();
422 CHECK_NULL_VOID(container);
423 container->InitIsFoldable();
424 if (container->IsFoldable()) {
425 currentFoldStatus_ = container->GetCurrentFoldStatus();
426 }
427 }
428
OnDetachFromMainTree()429 void NavigationPattern::OnDetachFromMainTree()
430 {
431 isFullPageNavigation_ = false;
432 auto host = GetHost();
433 CHECK_NULL_VOID(host);
434 UnregisterAvoidInfoChangeListener(host);
435 auto pipeline = host->GetContext();
436 CHECK_NULL_VOID(pipeline);
437 auto windowManager = pipeline->GetWindowManager();
438 CHECK_NULL_VOID(windowManager);
439 TryRestoreSystemBarStyle(windowManager);
440 backupStyle_.reset();
441 currStyle_.reset();
442 pageNode_ = nullptr;
443 }
444
IsTopNavDestination(const RefPtr<UINode> & node) const445 bool NavigationPattern::IsTopNavDestination(const RefPtr<UINode>& node) const
446 {
447 if (!navigationStack_) {
448 return false;
449 }
450 auto topPath = navigationStack_->GetTopNavPath();
451 if (!topPath.has_value()) {
452 return false;
453 }
454 auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(
455 NavigationGroupNode::GetNavDestinationNode(topPath->second));
456 return navDestination == node;
457 }
458
JudgeFoldStateChangeAndUpdateState()459 bool NavigationPattern::JudgeFoldStateChangeAndUpdateState()
460 {
461 auto container = Container::Current();
462 CHECK_NULL_RETURN(container, false);
463 auto foldStatus = container->GetCurrentFoldStatus();
464 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "newFoldStatus: %{public}d, currentFoldStatus: %{public}d.",
465 static_cast<int32_t>(foldStatus), static_cast<int32_t>(currentFoldStatus_));
466 if (foldStatus != currentFoldStatus_) {
467 currentFoldStatus_ = foldStatus;
468 return true;
469 }
470 return false;
471 }
472
UpdateIsFullPageNavigation(const RefPtr<FrameNode> & host)473 void NavigationPattern::UpdateIsFullPageNavigation(const RefPtr<FrameNode>& host)
474 {
475 CHECK_NULL_VOID(host);
476 auto geometryNode = host->GetGeometryNode();
477 CHECK_NULL_VOID(geometryNode);
478 auto frame = geometryNode->GetFrameRect();
479 auto pipeline = host->GetContext();
480 CHECK_NULL_VOID(pipeline);
481 auto windowManager = pipeline->GetWindowManager();
482 CHECK_NULL_VOID(windowManager);
483
484 bool isFullPage = false;
485 auto pageNode = pageNode_.Upgrade();
486 if (pageNode) {
487 auto pageNodeGeometryNode = pageNode->GetGeometryNode();
488 if (pageNodeGeometryNode) {
489 auto pageFrame = pageNodeGeometryNode->GetFrameRect();
490 isFullPage = pageFrame.GetSize() == frame.GetSize();
491 }
492 }
493 pageNode = nullptr;
494
495 if (isFullPage == isFullPageNavigation_) {
496 return;
497 }
498
499 isFullPageNavigation_ = isFullPage;
500 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "Navigation[%{public}d] change to %{public}s",
501 host->GetId(), isFullPageNavigation_ ? "FullPage" : "PartialPage");
502 MarkAllNavDestinationDirtyIfNeeded(host);
503 UpdateSystemBarStyleOnFullPageStateChange(windowManager);
504 if (isFullPageNavigation_) {
505 RegisterPageVisibilityChangeCallback();
506 }
507 }
508
UpdateSystemBarStyleOnFullPageStateChange(const RefPtr<WindowManager> & windowManager)509 void NavigationPattern::UpdateSystemBarStyleOnFullPageStateChange(const RefPtr<WindowManager>& windowManager)
510 {
511 // full page -> partial page
512 if (!isFullPageNavigation_) {
513 TryRestoreSystemBarStyle(windowManager);
514 return;
515 }
516
517 // partial page -> full page
518 auto topPath = navigationStack_->GetTopNavPath();
519 UpdateSystemBarStyleWithTopNavPath(windowManager, topPath);
520 }
521
UpdateSystemBarStyleOnTopNavPathChange(const std::optional<std::pair<std::string,RefPtr<UINode>>> & newTopNavPath)522 void NavigationPattern::UpdateSystemBarStyleOnTopNavPathChange(
523 const std::optional<std::pair<std::string, RefPtr<UINode>>>& newTopNavPath)
524 {
525 if (!isFullPageNavigation_) {
526 return;
527 }
528
529 auto host = GetHost();
530 CHECK_NULL_VOID(host);
531 auto pipeline = host->GetContext();
532 CHECK_NULL_VOID(pipeline);
533 auto windowManager = pipeline->GetWindowManager();
534 CHECK_NULL_VOID(windowManager);
535 UpdateSystemBarStyleWithTopNavPath(windowManager, newTopNavPath);
536 }
537
UpdateSystemBarStyleWithTopNavPath(const RefPtr<WindowManager> & windowManager,const std::optional<std::pair<std::string,RefPtr<UINode>>> & topNavPath)538 void NavigationPattern::UpdateSystemBarStyleWithTopNavPath(const RefPtr<WindowManager>& windowManager,
539 const std::optional<std::pair<std::string, RefPtr<UINode>>>& topNavPath)
540 {
541 if (ApplyTopNavPathSystemBarStyleOrRestore(windowManager, topNavPath)) {
542 return;
543 }
544
545 if (currStyle_.has_value() && currStyle_.value() != nullptr) {
546 windowManager->SetSystemBarStyle(currStyle_.value());
547 } else {
548 TryRestoreSystemBarStyle(windowManager);
549 }
550 }
551
TryRestoreSystemBarStyle(const RefPtr<WindowManager> & windowManager)552 void NavigationPattern::TryRestoreSystemBarStyle(const RefPtr<WindowManager>& windowManager)
553 {
554 if (backupStyle_.has_value()) {
555 windowManager->SetSystemBarStyle(backupStyle_.value());
556 }
557 }
558
UpdateSystemBarStyleOnPageVisibilityChange(bool show)559 void NavigationPattern::UpdateSystemBarStyleOnPageVisibilityChange(bool show)
560 {
561 if (!isFullPageNavigation_) {
562 return;
563 }
564
565 CHECK_NULL_VOID(navigationStack_);
566 auto host = GetHost();
567 CHECK_NULL_VOID(host);
568 auto pipeline = host->GetContext();
569 CHECK_NULL_VOID(pipeline);
570 auto windowManager = pipeline->GetWindowManager();
571 CHECK_NULL_VOID(windowManager);
572 if (show) {
573 // page containing Navigation, hide -> show
574 auto topPath = navigationStack_->GetTopNavPath();
575 UpdateSystemBarStyleWithTopNavPath(windowManager, topPath);
576 } else {
577 // page containing Navigation, show -> hide
578 TryRestoreSystemBarStyle(windowManager);
579 }
580 }
581
RegisterPageVisibilityChangeCallback()582 void NavigationPattern::RegisterPageVisibilityChangeCallback()
583 {
584 auto pageNode = pageNode_.Upgrade();
585 CHECK_NULL_VOID(pageNode);
586 RefPtr<PagePattern> pagePattern = pageNode->GetPattern<PagePattern>();
587 CHECK_NULL_VOID(pagePattern);
588 auto callback = [weak = WeakClaim(this)](bool show) {
589 auto pattern = weak.Upgrade();
590 CHECK_NULL_VOID(pattern);
591 // we need update the "systemBarStyle" at the beginning of the transition animation on the router page
592 pattern->UpdateSystemBarStyleOnPageVisibilityChange(show);
593 };
594 pagePattern->SetPageVisibilityChangeCallback(std::move(callback));
595 }
596
ApplyTopNavPathSystemBarStyleOrRestore(const RefPtr<WindowManager> & windowManager,const std::optional<std::pair<std::string,RefPtr<UINode>>> & topNavPath)597 bool NavigationPattern::ApplyTopNavPathSystemBarStyleOrRestore(
598 const RefPtr<WindowManager>& windowManager,
599 const std::optional<std::pair<std::string, RefPtr<UINode>>>& topNavPath)
600 {
601 if (!topNavPath.has_value()) {
602 return false;
603 }
604
605 auto topNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(
606 NavigationGroupNode::GetNavDestinationNode(topNavPath->second));
607 if (!topNavDestination) {
608 return false;
609 }
610
611 auto navDestinationPattern = topNavDestination->GetPattern<NavDestinationPattern>();
612 if (!navDestinationPattern) {
613 return false;
614 }
615 /**
616 * Backup is only performed when the developer sets the "systemBarStyle" attribute,
617 * and the entire Navigation is only backed up once.
618 * Therefore, when developer only set the "systemBarStyle" attribute to NavDestination, we need to
619 * save the attribute to Navigation.
620 */
621 auto backupFromNavDestination = navDestinationPattern->GetBackupStyle();
622 if (!backupStyle_.has_value() && backupFromNavDestination.has_value()) {
623 backupStyle_ = backupFromNavDestination;
624 }
625
626 auto destCurrStyle = navDestinationPattern->GetCurrentStyle();
627 if (destCurrStyle.has_value() && destCurrStyle.value() != nullptr) {
628 windowManager->SetSystemBarStyle(destCurrStyle.value());
629 } else {
630 TryRestoreSystemBarStyle(windowManager);
631 }
632 return true;
633 }
634
InitPageNode(const RefPtr<FrameNode> & host)635 void NavigationPattern::InitPageNode(const RefPtr<FrameNode>& host)
636 {
637 CHECK_NULL_VOID(host);
638 auto parent = host->GetParent();
639 CHECK_NULL_VOID(parent);
640 RefPtr<FrameNode> pageNode = nullptr;
641 while (parent) {
642 if (parent->GetTag() == V2::PAGE_ETS_TAG) {
643 pageNode = AceType::DynamicCast<FrameNode>(parent);
644 break;
645 }
646 parent = parent->GetParent();
647 }
648 if (!pageNode) {
649 TAG_LOGE(AceLogTag::ACE_NAVIGATION, "Failed to find PageNode of Navigation");
650 } else {
651 pageNode_ = WeakPtr<FrameNode>(pageNode);
652 }
653 }
654
OnLanguageConfigurationUpdate()655 void NavigationPattern::OnLanguageConfigurationUpdate()
656 {
657 bool isRightToLeft = AceApplicationInfo::GetInstance().IsRightToLeft();
658 if (isRightToLeft != isRightToLeft_) {
659 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
660 CHECK_NULL_VOID(hostNode);
661 hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
662 isRightToLeft_ = isRightToLeft;
663 }
664 }
665
SyncWithJsStackIfNeeded()666 void NavigationPattern::SyncWithJsStackIfNeeded()
667 {
668 if (!needSyncWithJsStack_) {
669 TAG_LOGI(AceLogTag::ACE_NAVIGATION,
670 "not need SyncWithJsStack, needSyncWithJsStack_ %{public}d", needSyncWithJsStack_);
671 return;
672 }
673 CHECK_NULL_VOID(navigationStack_);
674 needSyncWithJsStack_ = false;
675 if (!isFinishInteractiveAnimation_) {
676 TAG_LOGI(AceLogTag::ACE_NAVIGATION,
677 "not need SyncWithJsStack, interactive animation: %{public}d", isFinishInteractiveAnimation_);
678 return;
679 }
680 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
681 CHECK_NULL_VOID(hostNode);
682 TAG_LOGI(AceLogTag::ACE_NAVIGATION,
683 "sync with js stack, id: %{public}s, UINodeId: %{public}d, preStackSize: %{public}d, newStackSize: %{public}d",
684 hostNode->GetCurId().c_str(), hostNode->GetId(), navigationStack_->PreSize(),
685 static_cast<int32_t>(navigationStack_->GetAllPathName().size()));
686 preTopNavPath_ = navigationStack_->GetPreTopNavPath();
687 preStackSize_ = navigationStack_->PreSize();
688 preContext_ = nullptr;
689 if (preTopNavPath_.has_value()) {
690 auto preDestination = AceType::DynamicCast<NavDestinationGroupNode>(
691 NavigationGroupNode::GetNavDestinationNode(preTopNavPath_->second));
692 if (preDestination) {
693 auto pattern = AceType::DynamicCast<NavDestinationPattern>(preDestination->GetPattern());
694 preContext_ = pattern->GetNavDestinationContext();
695 if (preContext_) {
696 preContext_->SetPreIndex(preStackSize_ - 1);
697 }
698 }
699 }
700 if (isCustomAnimation_) {
701 navigationStack_->UpdateRecoveryList();
702 }
703 navigationStack_->SavePreNavList();
704 UpdateNavPathList();
705 auto newTopNavPath = navigationStack_->GetTopNavPath();
706 auto replaceValue = navigationStack_->GetReplaceValue();
707 if (preTopNavPath_ != newTopNavPath || replaceValue == 1) {
708 isReplace_ = replaceValue != 0;
709 UpdateIsAnimation(preTopNavPath_);
710 lastPreIndex_ = 0;
711 if (preTopNavPath_.has_value()) {
712 lastPreIndex_ = navigationStack_->FindIndex(preTopNavPath_->first, preTopNavPath_->second, true);
713 }
714 FireInterceptionEvent(true, newTopNavPath);
715 if (needSyncWithJsStack_) {
716 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "sync with js stack in before interception");
717 UpdateNavPathList();
718 needSyncWithJsStack_ = false;
719 }
720 }
721 RefreshNavDestination();
722 }
723
UpdateNavPathList()724 void NavigationPattern::UpdateNavPathList()
725 {
726 CHECK_NULL_VOID(navigationStack_);
727 auto pathNames = navigationStack_->GetAllPathName();
728 auto indexes = navigationStack_->GetAllPathIndex();
729 topFromSingletonMoved_ = navigationStack_->IsTopFromSingletonMoved();
730 navigationStack_->ResetSingletonMoved();
731 navigationStack_->InitNavPathIndex(pathNames);
732 auto cacheNodes = navigationStack_->GetAllCacheNodes();
733 NavPathList navPathList;
734 int32_t pathListSize = static_cast<int32_t>(pathNames.size());
735 isCurTopNewInstance_ = false;
736 // lastRecoveredStandardIndex will be only used in recovery case
737 int32_t lastRecoveredStandardIndex = 0;
738 int32_t removeSize = 0; // push destination failed size
739 bool isCurForceSetList = false;
740 for (int32_t index = 0; index < pathListSize; ++index) {
741 auto pathName = pathNames[index];
742 RefPtr<UINode> uiNode = nullptr;
743 int32_t arrayIndex = index - removeSize;
744 if (navigationStack_->IsFromRecovery(arrayIndex)) {
745 if (navigationStack_->GetRecoveredDestinationMode(arrayIndex) ==
746 static_cast<int32_t>(NavDestinationMode::STANDARD)) {
747 lastRecoveredStandardIndex = arrayIndex;
748 }
749 navPathList.emplace_back(std::make_pair(pathName, uiNode));
750 // only create recovery node when it is at top
751 if (index == pathListSize - 1) {
752 removeSize += GenerateUINodeFromRecovery(lastRecoveredStandardIndex, navPathList);
753 }
754 continue;
755 }
756 auto pathIndex = indexes[index];
757 if (navigationStack_->NeedBuildNewInstance(arrayIndex)) {
758 // if marked NEW_INSTANCE when push/replace in frontend, build a new instance anyway
759 if (!GenerateUINodeByIndex(arrayIndex, uiNode)) {
760 removeSize++;
761 continue;
762 }
763 navPathList.emplace_back(std::make_pair(pathName, uiNode));
764 navigationStack_->SetNeedBuildNewInstance(arrayIndex, false);
765 if (index == pathListSize - 1) {
766 isCurTopNewInstance_ = true;
767 }
768 continue;
769 }
770 bool isPageForceSet = navigationStack_->GetIsForceSet(arrayIndex);
771 if (isPageForceSet) {
772 isCurForceSetList = true;
773 }
774 auto navDestinationId = navigationStack_->GetNavDestinationIdInt(arrayIndex);
775 if (index == pathListSize - 1 && addByNavRouter_) {
776 addByNavRouter_ = false;
777 uiNode = navigationStack_->Get();
778 } else if (isPageForceSet && navDestinationId != -1) {
779 uiNode = FindNavDestinationNodeInPreList(navDestinationId);
780 } else {
781 uiNode = navigationStack_->Get(pathIndex);
782 }
783 if (uiNode) {
784 TAG_LOGD(AceLogTag::ACE_NAVIGATION, "find in list, navigation stack reserve node, "
785 "old index: %{public}d, index: %{public}d, removeSize: %{public}d, name: %{public}s.",
786 pathIndex, index, removeSize, pathName.c_str());
787 /**
788 * If we call the function pushPath/pushDestination with singleton mode(
789 * LaunchMode == MOVE_TO_TOP_SINGLETON/POP_TO_SINGLETON), and the top NavDestination of stack
790 * is the NavDestination which we need to push(NavDestination's name == NavPathInfo's name),
791 * then wee need to update the NavDestination's parameters.
792 */
793 navigationStack_->UpdatePathInfoIfNeeded(uiNode, arrayIndex);
794 auto navDestinationGroupNode = AceType::DynamicCast<NavDestinationGroupNode>(
795 NavigationGroupNode::GetNavDestinationNode(uiNode));
796 if (navDestinationGroupNode && navDestinationGroupNode->GetCanReused()) {
797 navigationStack_->ResetIsForceSetFlag(arrayIndex);
798 navPathList.emplace_back(std::make_pair(pathName, uiNode));
799 continue;
800 }
801 }
802 uiNode = navigationStack_->GetFromCacheNode(cacheNodes, pathName);
803 if (uiNode) {
804 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "find in cached node, navigation stack reserve node, "
805 "index: %{public}d, removeSize: %{public}d, name: %{public}s.", index, removeSize, pathName.c_str());
806 navPathList.emplace_back(std::make_pair(pathName, uiNode));
807 navigationStack_->RemoveCacheNode(cacheNodes, pathName, uiNode);
808 auto navDestination =
809 DynamicCast<NavDestinationGroupNode>(NavigationGroupNode::GetNavDestinationNode(uiNode));
810 if (navDestination) {
811 navDestination->SetInCurrentStack(true);
812 auto eventHub = navDestination->GetEventHub<EventHub>();
813 CHECK_NULL_VOID(eventHub);
814 eventHub->SetEnabledInternal(true);
815 navigationStack_->ResetIsForceSetFlag(arrayIndex);
816 }
817 continue;
818 }
819 if (isPageForceSet) {
820 navPathList.emplace_back(std::make_pair(pathName, uiNode));
821 continue;
822 }
823 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "find in nowhere, navigation stack create new node, "
824 "index: %{public}d, removeSize: %{public}d, name: %{public}s.", index, removeSize, pathName.c_str());
825 if (!GenerateUINodeByIndex(arrayIndex, uiNode)) {
826 std::string replacedName = "";
827 int32_t replacedIndex = -1;
828 if (navigationStack_->CheckIsReplacedDestination(arrayIndex, replacedName, replacedIndex)) {
829 navigationStack_->SetRecoveryFromReplaceDestination(arrayIndex, false);
830 pathNames[index] = replacedName;
831 indexes[index] = replacedIndex;
832 index--;
833 continue;
834 }
835 removeSize++;
836 continue;
837 }
838 navPathList.emplace_back(std::make_pair(pathName, uiNode));
839 }
840 if (isCurForceSetList) {
841 GenerateLastStandardPage(navPathList);
842 }
843 navigationStack_->SetNavPathList(navPathList);
844 navigationStack_->SetIsCurForceSetList(isCurForceSetList);
845 }
846
RefreshNavDestination()847 void NavigationPattern::RefreshNavDestination()
848 {
849 isChanged_ = false;
850 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
851 CHECK_NULL_VOID(hostNode);
852 auto pipeline = PipelineContext::GetCurrentContext();
853 CHECK_NULL_VOID(pipeline);
854 auto preTopNavPath = std::move(preTopNavPath_);
855 auto preLastStandardIndex = hostNode->GetLastStandardIndex();
856 auto& navPathList = navigationStack_->GetAllNavDestinationNodes();
857 hostNode->UpdateNavDestinationNodeWithoutMarkDirty(
858 preTopNavPath.has_value() ? preTopNavPath->second : nullptr, navigationModeChange_);
859 auto newTopNavPath = navigationStack_->GetTopNavPath();
860 #if defined(ENABLE_NAV_SPLIT_MODE)
861 isBackPage_ = newTopNavPath.has_value() ?
862 navigationStack_->isLastListContains(newTopNavPath->first, newTopNavPath->second) : false;
863 #endif
864 if (topFromSingletonMoved_) {
865 FireOnNewParam(newTopNavPath.has_value() ? newTopNavPath->second : nullptr);
866 }
867 CheckTopNavPathChange(preTopNavPath, newTopNavPath, preLastStandardIndex);
868
869 // close keyboard
870 #if defined(ENABLE_STANDARD_INPUT)
871 RefPtr<FrameNode> targetNode = newTopNavPath.has_value() ? AceType::DynamicCast<FrameNode>(
872 NavigationGroupNode::GetNavDestinationNode(newTopNavPath->second)) :
873 AceType::DynamicCast<FrameNode>(hostNode->GetNavBarNode());
874 if (isChanged_ && GetIsFocusable(targetNode)) {
875 InputMethodManager::GetInstance()->CloseKeyboard();
876 }
877 #endif
878
879 #if defined(ENABLE_NAV_SPLIT_MODE)
880 navigationStack_->SetLastNavPathList(navPathList);
881 #endif
882
883 /* if first navDestination is removed, the new one will be refreshed */
884 if (!navPathList.empty()) {
885 auto firstNavDesNode = AceType::DynamicCast<NavDestinationGroupNode>(
886 NavigationGroupNode::GetNavDestinationNode(navPathList.front().second));
887 CHECK_NULL_VOID(firstNavDesNode);
888 firstNavDesNode->MarkModifyDone();
889 }
890
891 std::string navDestinationName = newTopNavPath.has_value() ? newTopNavPath->first : "";
892 pipeline->AddPredictTask([weak = WeakClaim(this), weakNode = WeakPtr<FrameNode>(hostNode),
893 navDestinationName](int64_t deadline, bool canUseLongPredictTask) {
894 auto navigationPattern = weak.Upgrade();
895 CHECK_NULL_VOID(navigationPattern);
896 auto navigationNode = weakNode.Upgrade();
897 CHECK_NULL_VOID(navigationNode);
898 int32_t count = 0;
899 int32_t depth = 0;
900 navigationNode->GetPageNodeCountAndDepth(&count, &depth);
901 navigationPattern->PerformanceEventReport(count, depth, navDestinationName);
902 });
903 }
904
CheckTopNavPathChange(const std::optional<std::pair<std::string,RefPtr<UINode>>> & preTopNavPath,const std::optional<std::pair<std::string,RefPtr<UINode>>> & newTopNavPath,int32_t preLastStandardIndex)905 void NavigationPattern::CheckTopNavPathChange(
906 const std::optional<std::pair<std::string, RefPtr<UINode>>>& preTopNavPath,
907 const std::optional<std::pair<std::string, RefPtr<UINode>>>& newTopNavPath,
908 int32_t preLastStandardIndex)
909 {
910 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
911 CHECK_NULL_VOID(hostNode);
912 if (preTopNavPath != newTopNavPath) {
913 UpdateSystemBarStyleOnTopNavPathChange(newTopNavPath);
914 }
915 auto replaceValue = navigationStack_->GetReplaceValue();
916 if (preTopNavPath == newTopNavPath) {
917 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "page is not change. don't transition");
918 auto currentProxy = GetTopNavigationProxy();
919 if (currentProxy) {
920 currentProxy->SetIsSuccess(false);
921 }
922 hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_WILL_HIDE);
923 NotifyDialogChange(NavDestinationLifecycle::ON_WILL_SHOW, true);
924 auto pipeline = PipelineContext::GetCurrentContext();
925 CHECK_NULL_VOID(pipeline);
926 pipeline->AddAfterLayoutTask([weakPattern = WeakClaim(this)]() {
927 auto pattern = weakPattern.Upgrade();
928 CHECK_NULL_VOID(pattern);
929 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(pattern->GetHost());
930 CHECK_NULL_VOID(hostNode);
931 hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_HIDE);
932 hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_WILL_DISAPPEAR);
933 pattern->NotifyDialogChange(NavDestinationLifecycle::ON_SHOW, true);
934 hostNode->RemoveDialogDestination();
935 });
936 ClearRecoveryList();
937 return;
938 }
939
940 isChanged_ = true;
941 UpdateIsAnimation(preTopNavPath);
942 isReplace_ = replaceValue != 0;
943 if (replaceValue == 1) {
944 const int32_t replaceAnimation = 2;
945 navigationStack_->UpdateReplaceValue(replaceAnimation);
946 }
947 auto context = PipelineContext::GetCurrentContext();
948 CHECK_NULL_VOID(context);
949 // close the text selection menu before transition.
950 auto selectOverlayManager = context->GetSelectOverlayManager();
951 if (selectOverlayManager) {
952 selectOverlayManager->ResetSelectionAndDestroySelectOverlay();
953 }
954 // fire onHidden and lostFocus event
955 RefPtr<NavDestinationGroupNode> preTopNavDestination;
956 int32_t lastPreIndex = -1;
957 bool isPopPage = false;
958 if (preTopNavPath.has_value()) {
959 // pre page is not in the current stack
960 lastPreIndex = navigationStack_->FindIndex(preTopNavPath->first, preTopNavPath->second, true);
961 isPopPage |= lastPreIndex == -1;
962 preTopNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(
963 NavigationGroupNode::GetNavDestinationNode(preTopNavPath->second));
964 }
965 if (isCurTopNewInstance_) {
966 isPopPage = false;
967 }
968 RefPtr<NavDestinationGroupNode> newTopNavDestination;
969 if (newTopNavPath.has_value()) {
970 newTopNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(
971 NavigationGroupNode::GetNavDestinationNode(newTopNavPath->second));
972 do {
973 if (!newTopNavDestination) {
974 break;
975 }
976 if (!GetIsFocusable(newTopNavDestination)) {
977 break;
978 }
979 auto navDestinationPattern = newTopNavDestination->GetPattern<NavDestinationPattern>();
980 auto navDestinationFocusView = AceType::DynamicCast<FocusView>(navDestinationPattern);
981 CHECK_NULL_VOID(navDestinationFocusView);
982 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TWELVE)) {
983 navDestinationFocusView->SetIsViewRootScopeFocused(false);
984 }
985 navDestinationFocusView->FocusViewShow();
986 } while (0);
987 } else {
988 // back to navBar case
989 auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
990 CHECK_NULL_VOID(navBarNode);
991 auto navigationLayoutProperty = AceType::DynamicCast<NavigationLayoutProperty>(hostNode->GetLayoutProperty());
992 if (!navigationLayoutProperty->GetHideNavBarValue(false)) {
993 navBarNode->GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE);
994 navBarNode->SetJSViewActive(true);
995 }
996 ProcessPageShowEvent();
997 navBarNode->GetEventHub<EventHub>()->SetEnabledInternal(true);
998 if (GetIsFocusable(navBarNode)) {
999 auto navBarFocusView = navBarNode->GetPattern<FocusView>();
1000 CHECK_NULL_VOID(navBarFocusView);
1001 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1002 navBarFocusView->SetIsViewRootScopeFocused(false);
1003 }
1004 navBarFocusView->FocusViewShow();
1005 }
1006 }
1007 bool isShow = false;
1008 bool isDialog =
1009 (preTopNavDestination && preTopNavDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG) ||
1010 (newTopNavDestination && newTopNavDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG);
1011 if (preTopNavDestination && isDialog) {
1012 auto lastStandardIndex = hostNode->GetLastStandardIndex();
1013 isShow = (lastPreIndex != -1) && (lastPreIndex >= lastStandardIndex);
1014 hostNode->SetNeedSetInvisible(lastStandardIndex >= 0);
1015 if (lastStandardIndex < 0) {
1016 auto navBarNode = AceType::DynamicCast<FrameNode>(hostNode->GetNavBarNode());
1017 auto layoutProperty = navBarNode->GetLayoutProperty();
1018 layoutProperty->UpdateVisibility(VisibleType::VISIBLE, true);
1019 navBarNode->SetJSViewActive(true);
1020 }
1021 }
1022 bool disableAllAnimation = navigationStack_->GetDisableAnimation();
1023 bool animated = navigationStack_->GetAnimatedValue();
1024 TAG_LOGI(AceLogTag::ACE_NAVIGATION,
1025 "transition start, disableAllAnimation: %{public}d, animated: %{public}d, isPopPage: %{public}d, isDialog: "
1026 "%{public}d, isReplace: %{public}d, isCustomAnimation: %{public}d",
1027 disableAllAnimation, animated, isPopPage, isDialog, isReplace_, isCustomAnimation_);
1028 if (disableAllAnimation || !animated) {
1029 // transition without animation need to run before layout for geometryTransition.
1030 StartTransition(preTopNavDestination, newTopNavDestination, false, isPopPage, isShow);
1031 navigationStack_->UpdateAnimatedValue(true);
1032 hostNode->GetLayoutProperty()->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
1033 return;
1034 }
1035 if (isDialog && !isCustomAnimation_) {
1036 bool isNeedAnimation =
1037 AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_THIRTEEN) ?
1038 true : false;
1039 StartTransition(preTopNavDestination, newTopNavDestination, isNeedAnimation, isPopPage, isShow);
1040 hostNode->GetLayoutProperty()->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
1041 return;
1042 }
1043
1044 // before the animation of navDes replacing, update the zIndex of the previous navDes node
1045 UpdatePreNavDesZIndex(preTopNavDestination, newTopNavDestination, preLastStandardIndex);
1046 // transition with animation need to run after layout task
1047 StartTransition(preTopNavDestination, newTopNavDestination, true, isPopPage, isShow);
1048 hostNode->GetLayoutProperty()->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
1049 }
1050
FireNavDestinationStateChange(NavDestinationLifecycle lifecycle)1051 int32_t NavigationPattern::FireNavDestinationStateChange(NavDestinationLifecycle lifecycle)
1052 {
1053 const auto& navDestinationNodes = navigationStack_->GetAllNavDestinationNodes();
1054 auto errIndex = static_cast<int32_t>(navDestinationNodes.size());
1055 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1056 CHECK_NULL_RETURN(hostNode, errIndex);
1057 NotifyDialogChange(lifecycle, true);
1058 return hostNode->GetLastStandardIndex();
1059 }
1060
FireNavigationStateChange(const RefPtr<UINode> & node,bool isShow)1061 void NavigationPattern::FireNavigationStateChange(const RefPtr<UINode>& node, bool isShow)
1062 {
1063 if (isShow) {
1064 NavigationPattern::FireNavigationLifecycleChange(node, NavDestinationLifecycle::ON_SHOW);
1065 return;
1066 }
1067 NavigationPattern::FireNavigationLifecycleChange(node, NavDestinationLifecycle::ON_HIDE);
1068 }
1069
CheckParentDestinationIsOnhide(const RefPtr<NavDestinationGroupNode> & destinationNode)1070 bool NavigationPattern::CheckParentDestinationIsOnhide(const RefPtr<NavDestinationGroupNode>& destinationNode)
1071 {
1072 CHECK_NULL_RETURN(destinationNode, false);
1073 auto destinationNodePattern = destinationNode->GetPattern<NavDestinationPattern>();
1074 CHECK_NULL_RETURN(destinationNodePattern, false);
1075 return !destinationNodePattern->GetIsOnShow();
1076 }
1077
CheckParentDestinationInactive()1078 bool NavigationPattern::CheckParentDestinationInactive()
1079 {
1080 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1081 CHECK_NULL_RETURN(hostNode, false);
1082 auto parentDestination = hostNode->GetParentDestinationNode().Upgrade();
1083 CHECK_NULL_RETURN(parentDestination, false);
1084 auto pattern = parentDestination->GetPattern<NavDestinationPattern>();
1085 CHECK_NULL_RETURN(pattern, false);
1086 return !pattern->IsActive();
1087 }
1088
CheckDestinationIsPush(const RefPtr<NavDestinationGroupNode> & destinationNode)1089 bool NavigationPattern::CheckDestinationIsPush(const RefPtr<NavDestinationGroupNode>& destinationNode)
1090 {
1091 CHECK_NULL_RETURN(destinationNode, false);
1092 return destinationNode->GetIndex() != -1 || destinationNode->GetNavDestinationCustomNode();
1093 }
1094
FireNavigationInner(const RefPtr<UINode> & node,bool isOnShow)1095 void NavigationPattern::FireNavigationInner(const RefPtr<UINode>& node, bool isOnShow)
1096 {
1097 CHECK_NULL_VOID(node);
1098 auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(node);
1099 if (!navigationNode) {
1100 NavigationPattern::FireNavigationChange(node, isOnShow, false);
1101 return;
1102 }
1103 auto navigationPattern = navigationNode->GetPattern<NavigationPattern>();
1104 CHECK_NULL_VOID(navigationPattern);
1105 CHECK_NULL_VOID(navigationPattern->navigationStack_);
1106 const auto& navDestinationNodes = navigationPattern->navigationStack_->GetAllNavDestinationNodes();
1107 auto lastStandardIndex = navigationNode->GetLastStandardIndex();
1108 int32_t standardIndex = lastStandardIndex >= 0 ? lastStandardIndex : 0;
1109 int32_t start = standardIndex;
1110 int32_t end = navigationPattern->navigationStack_->Size();
1111 auto pipeline = PipelineContext::GetCurrentContext();
1112 CHECK_NULL_VOID(pipeline);
1113 auto overlayManager = pipeline->GetOverlayManager();
1114 if (isOnShow) {
1115 if (overlayManager && overlayManager->HasModalPage()) {
1116 return;
1117 }
1118 for (int32_t index = start; index < end; index++) {
1119 const auto& curPath = navDestinationNodes[index];
1120 auto curDestination = AceType::DynamicCast<NavDestinationGroupNode>(
1121 navigationNode->GetNavDestinationNode(curPath.second));
1122 if (!curDestination || !curDestination->GetLayoutProperty()) {
1123 continue;
1124 }
1125 auto navDestinationPattern = curDestination->GetPattern<NavDestinationPattern>();
1126 CHECK_NULL_VOID(navDestinationPattern);
1127 auto property = curDestination->GetLayoutProperty();
1128 if (property->GetVisibilityValue(VisibleType::VISIBLE) != VisibleType::VISIBLE ||
1129 !curDestination->IsActive() || navDestinationPattern->GetIsOnShow() == isOnShow) {
1130 continue;
1131 }
1132 auto eventHub = curDestination->GetEventHub<NavDestinationEventHub>();
1133 CHECK_NULL_VOID(eventHub);
1134 auto param = Recorder::EventRecorder::Get().IsPageParamRecordEnable() ?
1135 navigationPattern->navigationStack_->GetRouteParam() : "";
1136 eventHub->FireOnShownEvent(navDestinationPattern->GetName(), param);
1137 navDestinationPattern->SetIsOnShow(true);
1138 NavigationPattern::FireNavigationChange(curDestination, true, false);
1139 NavigationPattern::NotifyPerfMonitorPageMsg(navDestinationPattern->GetName());
1140 }
1141 return;
1142 }
1143 for (int32_t index = end - 1; index >= 0 && index >= start; index--) {
1144 const auto& curPath = navDestinationNodes[index];
1145 auto curDestination = AceType::DynamicCast<NavDestinationGroupNode>(
1146 navigationNode->GetNavDestinationNode(curPath.second));
1147 if (!curDestination || !curDestination->GetLayoutProperty()) {
1148 continue;
1149 }
1150 auto navDestinationPattern = curDestination->GetPattern<NavDestinationPattern>();
1151 CHECK_NULL_VOID(navDestinationPattern);
1152 auto property = curDestination->GetLayoutProperty();
1153 if (property->GetVisibilityValue(VisibleType::VISIBLE) != VisibleType::VISIBLE ||
1154 !curDestination->IsActive() || navDestinationPattern->GetIsOnShow() == isOnShow) {
1155 continue;
1156 }
1157 auto eventHub = curDestination->GetEventHub<NavDestinationEventHub>();
1158 CHECK_NULL_VOID(eventHub);
1159 eventHub->FireOnHiddenEvent(navDestinationPattern->GetName());
1160 navDestinationPattern->SetIsOnShow(false);
1161 NavigationPattern::FireNavigationChange(curDestination, false, false);
1162 }
1163 }
1164
FireNavigationChange(const RefPtr<UINode> & node,bool isOnShow,bool isFirst)1165 void NavigationPattern::FireNavigationChange(const RefPtr<UINode>& node, bool isOnShow, bool isFirst)
1166 {
1167 CHECK_NULL_VOID(node);
1168 if (isFirst) {
1169 FireNavigationInner(node, isOnShow);
1170 return;
1171 }
1172 const auto children = node->GetChildren();
1173 for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
1174 auto& child = *iter;
1175 FireNavigationInner(child, isOnShow);
1176 }
1177 }
1178
FireNavigationLifecycleChange(const RefPtr<UINode> & node,NavDestinationLifecycle lifecycle)1179 void NavigationPattern::FireNavigationLifecycleChange(const RefPtr<UINode>& node, NavDestinationLifecycle lifecycle)
1180 {
1181 CHECK_NULL_VOID(node);
1182 const auto children = node->GetChildren(true);
1183 for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
1184 auto& child = *iter;
1185 auto navigation = AceType::DynamicCast<NavigationGroupNode>(child);
1186 if (navigation) {
1187 auto destinationNode = navigation->GetParentDestinationNode().Upgrade();
1188 if ((lifecycle == NavDestinationLifecycle::ON_SHOW) && CheckParentDestinationIsOnhide(destinationNode) &&
1189 CheckDestinationIsPush(destinationNode)) {
1190 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation parent is onhide");
1191 continue;
1192 }
1193 auto navigationPattern = AceType::DynamicCast<NavigationPattern>(navigation->GetPattern());
1194 CHECK_NULL_VOID(navigationPattern);
1195 navigationPattern->FireNavDestinationStateChange(lifecycle);
1196 } else {
1197 NavigationPattern::FireNavigationLifecycleChange(child, lifecycle);
1198 }
1199 }
1200 }
1201
NotifyPageHide(const std::string & pageName)1202 void NavigationPattern::NotifyPageHide(const std::string& pageName)
1203 {
1204 auto container = Container::Current();
1205 CHECK_NULL_VOID(container);
1206 auto pageUrlChecker = container->GetPageUrlChecker();
1207 CHECK_NULL_VOID(pageUrlChecker);
1208 pageUrlChecker->NotifyPageHide(pageName);
1209 }
1210
NotifyPageShow(const std::string & pageName)1211 void NavigationPattern::NotifyPageShow(const std::string& pageName)
1212 {
1213 auto container = Container::Current();
1214 CHECK_NULL_VOID(container);
1215 auto pageUrlChecker = container->GetPageUrlChecker();
1216 CHECK_NULL_VOID(pageUrlChecker);
1217 pageUrlChecker->NotifyPageShow(pageName);
1218 if (PerfMonitor::GetPerfMonitor() != nullptr) {
1219 PerfMonitor::GetPerfMonitor()->SetPageName(pageName);
1220 }
1221 }
1222
ProcessPageShowEvent()1223 void NavigationPattern::ProcessPageShowEvent()
1224 {
1225 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1226 CHECK_NULL_VOID(hostNode);
1227 auto context = hostNode->GetContext();
1228 CHECK_NULL_VOID(context);
1229 auto stageManager = context->GetStageManager();
1230 if (stageManager) {
1231 RefPtr<FrameNode> pageNode = stageManager->GetLastPage();
1232 CHECK_NULL_VOID(pageNode);
1233 auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
1234 CHECK_NULL_VOID(pagePattern);
1235 auto pageInfo = pagePattern->GetPageInfo();
1236 CHECK_NULL_VOID(pageInfo);
1237 NotifyPageShow(pageInfo->GetPageUrl());
1238 }
1239 }
1240
ReplaceAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination)1241 void NavigationPattern::ReplaceAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
1242 const RefPtr<NavDestinationGroupNode>& newTopNavDestination)
1243 {
1244 auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1245 CHECK_NULL_VOID(navigationNode);
1246 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationNode->GetNavBarNode());
1247 CHECK_NULL_VOID(navBarNode);
1248 bool preUseCustomTransition = TriggerNavDestinationTransition(
1249 preTopNavDestination, NavigationOperation::REPLACE, false) != INVALID_ANIMATION_ID;
1250 TriggerNavDestinationTransition(newTopNavDestination, NavigationOperation::REPLACE, true);
1251 if (newTopNavDestination && preTopNavDestination && !preUseCustomTransition) {
1252 navigationNode->DealNavigationExit(preTopNavDestination, false, false);
1253 } else if (newTopNavDestination && navigationMode_ == NavigationMode::STACK) {
1254 navigationNode->DealNavigationExit(navBarNode, true, false);
1255 }
1256 navigationNode->RemoveDialogDestination();
1257 auto id = navigationNode->GetTopDestination() ? navigationNode->GetTopDestination()->GetAccessibilityId() : -1;
1258 navigationNode->OnAccessibilityEvent(
1259 AccessibilityEventType::PAGE_CHANGE, id, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID);
1260 navigationStack_->UpdateReplaceValue(0);
1261 }
1262
TransitionWithOutAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage,bool needVisible)1263 void NavigationPattern::TransitionWithOutAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
1264 const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage, bool needVisible)
1265 {
1266 ClearRecoveryList();
1267 auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1268 CHECK_NULL_VOID(navigationNode);
1269 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationNode->GetNavBarNode());
1270 CHECK_NULL_VOID(navBarNode);
1271
1272 // replace
1273 auto replaceVal = navigationStack_->GetReplaceValue();
1274 if (replaceVal != 0) {
1275 ReplaceAnimation(preTopNavDestination, newTopNavDestination);
1276 return;
1277 }
1278
1279 // navDestination push/pop navDestination
1280 if (newTopNavDestination && preTopNavDestination) {
1281 if (isPopPage) {
1282 newTopNavDestination->SetTransitionType(PageTransitionType::ENTER_POP);
1283 preTopNavDestination->CleanContent(false, true);
1284 auto parent = preTopNavDestination->GetParent();
1285 CHECK_NULL_VOID(parent);
1286 parent->RemoveChild(preTopNavDestination, true);
1287 parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1288 } else {
1289 preTopNavDestination->GetRenderContext()->RemoveClipWithRRect();
1290 preTopNavDestination->SetTransitionType(PageTransitionType::EXIT_PUSH);
1291 newTopNavDestination->SetTransitionType(PageTransitionType::ENTER_PUSH);
1292 DealTransitionVisibility(preTopNavDestination, needVisible, false);
1293 if (preTopNavDestination->NeedRemoveInPush()) {
1294 preTopNavDestination->CleanContent(false, true);
1295 auto parent = preTopNavDestination->GetParent();
1296 CHECK_NULL_VOID(parent);
1297 parent->RemoveChild(preTopNavDestination, true);
1298 parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1299 }
1300 }
1301 navigationNode->RemoveDialogDestination();
1302 auto id = navigationNode->GetTopDestination() ? navigationNode->GetTopDestination()->GetAccessibilityId() : -1;
1303 navigationNode->OnAccessibilityEvent(
1304 AccessibilityEventType::PAGE_CHANGE, id, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID);
1305 return;
1306 }
1307
1308 // navBar push navDestination
1309 if (newTopNavDestination && newTopNavDestination->GetNavDestinationMode() == NavDestinationMode::STANDARD) {
1310 newTopNavDestination->SetTransitionType(PageTransitionType::ENTER_PUSH);
1311 auto navBar = AceType::DynamicCast<NavBarNode>(navBarNode);
1312 // current mode is stack, set navBar invisible
1313 if (navigationMode_ == NavigationMode::STACK && navBar) {
1314 navBar->SetTransitionType(PageTransitionType::EXIT_PUSH);
1315 DealTransitionVisibility(navBarNode, false, true);
1316 }
1317 // if current mode is auto, need set navBar need set invisible true
1318 navigationNode->SetNeedSetInvisible(true);
1319 }
1320
1321 // navDestination pop to navBar
1322 if (preTopNavDestination) {
1323 preTopNavDestination->CleanContent(false, true);
1324 auto parent = preTopNavDestination->GetParent();
1325 CHECK_NULL_VOID(parent);
1326 parent->RemoveChild(preTopNavDestination, true);
1327 navigationNode->SetNeedSetInvisible(false);
1328 auto navBar = AceType::DynamicCast<NavBarNode>(navBarNode);
1329 if (navBar) {
1330 navBar->SetTransitionType(PageTransitionType::ENTER_POP);
1331 }
1332 parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1333 }
1334 navigationNode->RemoveDialogDestination();
1335 auto id = navigationNode->GetTopDestination() ? navigationNode->GetTopDestination()->GetAccessibilityId() : -1;
1336 navigationNode->OnAccessibilityEvent(
1337 AccessibilityEventType::PAGE_CHANGE, id, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID);
1338 }
1339
TransitionWithAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage,bool isNeedVisible)1340 void NavigationPattern::TransitionWithAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
1341 const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage, bool isNeedVisible)
1342 {
1343 auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1344 CHECK_NULL_VOID(navigationNode);
1345 auto layoutProperty = navigationNode->GetLayoutProperty<NavigationLayoutProperty>();
1346 CHECK_NULL_VOID(layoutProperty);
1347 if (layoutProperty->GetHideNavBarValue(false) && (!newTopNavDestination || !preTopNavDestination)) {
1348 // hide navBarNode and need to do animation with navBarNode
1349 if (preTopNavDestination) {
1350 // remove preTopNavDestination node in pop
1351 auto parent = preTopNavDestination->GetParent();
1352 CHECK_NULL_VOID(parent);
1353 preTopNavDestination->CleanContent();
1354 parent->RemoveChild(preTopNavDestination);
1355 parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1356 }
1357 navigationNode->RemoveDialogDestination();
1358 ClearRecoveryList();
1359 return;
1360 }
1361 if (isCustomAnimation_ && TriggerCustomAnimation(preTopNavDestination, newTopNavDestination, isPopPage)) {
1362 auto operation = NavigationOperation::REPLACE;
1363 if (navigationStack_->GetReplaceValue() == 0) {
1364 operation = isPopPage ? NavigationOperation::POP : NavigationOperation::PUSH;
1365 }
1366 TriggerNavDestinationTransition(preTopNavDestination, operation, false);
1367 TriggerNavDestinationTransition(newTopNavDestination, operation, true);
1368 return;
1369 }
1370 StartDefaultAnimation(preTopNavDestination, newTopNavDestination, isPopPage, isNeedVisible);
1371 }
1372
DialogAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage,bool isNeedVisible)1373 void NavigationPattern::DialogAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
1374 const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage, bool isNeedVisible)
1375 {
1376 if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_THIRTEEN)) {
1377 TransitionWithDialogAnimation(preTopNavDestination, newTopNavDestination, isPopPage);
1378 } else {
1379 TransitionWithOutAnimation(preTopNavDestination, newTopNavDestination, isPopPage, isNeedVisible);
1380 }
1381 }
1382
StartDefaultAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage,bool isNeedVisible)1383 void NavigationPattern::StartDefaultAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
1384 const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage, bool isNeedVisible)
1385 {
1386 auto currentProxy = GetTopNavigationProxy();
1387 if (currentProxy) {
1388 currentProxy->SetIsFinished(true);
1389 }
1390 ClearRecoveryList();
1391 bool isPreDialog = preTopNavDestination &&
1392 preTopNavDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG;
1393 bool isNewDialog = newTopNavDestination &&
1394 newTopNavDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG;
1395 if (isPreDialog || isNewDialog) {
1396 DialogAnimation(preTopNavDestination, newTopNavDestination, isPopPage, isNeedVisible);
1397 return;
1398 }
1399 auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1400 CHECK_NULL_VOID(navigationNode);
1401 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationNode->GetNavBarNode());
1402 CHECK_NULL_VOID(navBarNode);
1403 // replace
1404 auto replaceValue = navigationStack_->GetReplaceValue();
1405 if (replaceValue != 0) {
1406 if (newTopNavDestination && preTopNavDestination) {
1407 navigationNode->TransitionWithReplace(preTopNavDestination, newTopNavDestination, false);
1408 } else if (newTopNavDestination && navigationMode_ == NavigationMode::STACK) {
1409 navigationNode->TransitionWithReplace(navBarNode, newTopNavDestination, true);
1410 }
1411 navigationStack_->UpdateReplaceValue(0);
1412 return;
1413 }
1414 // navDestination push/pop navDestination
1415 if (newTopNavDestination && preTopNavDestination) {
1416 if (isPopPage) {
1417 navigationNode->TransitionWithPop(preTopNavDestination, newTopNavDestination);
1418 } else {
1419 navigationNode->TransitionWithPush(preTopNavDestination, newTopNavDestination);
1420 }
1421 return;
1422 }
1423 // navBar push navDestination
1424 if (newTopNavDestination && navigationMode_ == NavigationMode::STACK) {
1425 navigationNode->TransitionWithPush(navBarNode, newTopNavDestination, true);
1426 return;
1427 }
1428 // navDestination pop to navBar
1429 if (preTopNavDestination) {
1430 if (navigationMode_ == NavigationMode::SPLIT) {
1431 navigationNode->TransitionWithPop(preTopNavDestination, nullptr);
1432 }
1433 if (navigationMode_ == NavigationMode::STACK) {
1434 navigationNode->TransitionWithPop(preTopNavDestination, navBarNode, true);
1435 }
1436 }
1437 }
1438
OnVisibleChange(bool isVisible)1439 void NavigationPattern::OnVisibleChange(bool isVisible)
1440 {
1441 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1442 CHECK_NULL_VOID(hostNode);
1443 auto eventHub = hostNode->GetEventHub<NavigationEventHub>();
1444 CHECK_NULL_VOID(eventHub);
1445 eventHub->FireNavBarStateChangeEvent(isVisible);
1446 }
1447
OnNavBarStateChange(bool modeChange)1448 void NavigationPattern::OnNavBarStateChange(bool modeChange)
1449 {
1450 auto layoutProperty = GetLayoutProperty<NavigationLayoutProperty>();
1451 CHECK_NULL_VOID(layoutProperty);
1452 auto visibilityValue = layoutProperty->GetVisibilityValue(VisibleType::VISIBLE);
1453 if (visibilityValue != VisibleType::VISIBLE) {
1454 return;
1455 }
1456
1457 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1458 CHECK_NULL_VOID(hostNode);
1459 auto eventHub = hostNode->GetEventHub<NavigationEventHub>();
1460 CHECK_NULL_VOID(eventHub);
1461 auto currentNavigationMode = GetNavigationMode();
1462
1463 auto lastStandardIndex = hostNode->GetLastStandardIndex();
1464 if (modeChange) {
1465 bool navbarIsHidden = (currentNavigationMode == NavigationMode::STACK && lastStandardIndex >= 0) ||
1466 layoutProperty->GetHideNavBar().value_or(false);
1467 eventHub->FireNavBarStateChangeEvent(!navbarIsHidden);
1468 SetNavBarVisibilityChange(false);
1469 return;
1470 }
1471
1472 if (GetNavBarVisibilityChange()) {
1473 if (!layoutProperty->GetHideNavBarValue(false)) {
1474 eventHub->FireNavBarStateChangeEvent(true);
1475 } else {
1476 eventHub->FireNavBarStateChangeEvent(false);
1477 }
1478 SetNavBarVisibilityChange(false);
1479 return;
1480 }
1481
1482 if (currentNavigationMode == NavigationMode::STACK) {
1483 bool navbarIsHidden = (lastStandardIndex >= 0) || layoutProperty->GetHideNavBar().value_or(false);
1484 eventHub->FireNavBarStateChangeEvent(!navbarIsHidden);
1485 }
1486 }
1487
OnNavigationModeChange(bool modeChange)1488 void NavigationPattern::OnNavigationModeChange(bool modeChange)
1489 {
1490 if (!modeChange) {
1491 return;
1492 }
1493 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1494 CHECK_NULL_VOID(hostNode);
1495 auto eventHub = hostNode->GetEventHub<NavigationEventHub>();
1496 CHECK_NULL_VOID(eventHub);
1497 eventHub->FireNavigationModeChangeEvent(navigationMode_);
1498 // fire navigation stack navigation mode change event
1499 navigationStack_->FireNavigationModeChange(navigationMode_);
1500 }
1501
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)1502 bool NavigationPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
1503 {
1504 if (config.skipMeasure && config.skipLayout) {
1505 return false;
1506 }
1507 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1508 CHECK_NULL_RETURN(hostNode, false);
1509 UpdateIsFullPageNavigation(hostNode);
1510 if (navigationModeChange_) {
1511 if (NavigationMode::STACK == navigationMode_) {
1512 // Set focus on navDestination when mode changes to STACK
1513 RefreshFocusToDestination();
1514 }
1515 AbortAnimation(hostNode);
1516 }
1517 auto context = PipelineContext::GetCurrentContext();
1518 if (context) {
1519 context->GetTaskExecutor()->PostTask(
1520 [weak = WeakClaim(this), navigationStackWeak = WeakPtr<NavigationStack>(navigationStack_),
1521 navigationWeak = WeakPtr<NavigationGroupNode>(hostNode)] {
1522 auto pattern = weak.Upgrade();
1523 CHECK_NULL_VOID(pattern);
1524 auto navigationGroupNode = navigationWeak.Upgrade();
1525 CHECK_NULL_VOID(navigationGroupNode);
1526 auto navigationLayoutProperty =
1527 AceType::DynamicCast<NavigationLayoutProperty>(navigationGroupNode->GetLayoutProperty());
1528 CHECK_NULL_VOID(navigationLayoutProperty);
1529 auto navigationStack = navigationStackWeak.Upgrade();
1530 CHECK_NULL_VOID(navigationStack);
1531 auto curTopNavPath = navigationStack->GetTopNavPath();
1532 if (curTopNavPath.has_value()) {
1533 // considering backButton visibility
1534 auto curTopNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(
1535 NavigationGroupNode::GetNavDestinationNode(curTopNavPath->second));
1536 pattern->UpdateContextRect(curTopNavDestination, navigationGroupNode);
1537 }
1538 // considering navBar visibility
1539 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationGroupNode->GetNavBarNode());
1540 CHECK_NULL_VOID(navBarNode);
1541 auto navBarLayoutProperty = navBarNode->GetLayoutProperty<NavBarLayoutProperty>();
1542 CHECK_NULL_VOID(navBarLayoutProperty);
1543 auto lastStandardIndex = navigationGroupNode->GetLastStandardIndex();
1544 bool isSetInvisible = navigationGroupNode->GetNeedSetInvisible() && navigationStack->Size() != 0 &&
1545 lastStandardIndex >= 0;
1546 if (navigationLayoutProperty->GetHideNavBar().value_or(false) ||
1547 (pattern->GetNavigationMode() == NavigationMode::STACK && isSetInvisible)) {
1548 navBarLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
1549 navBarNode->SetJSViewActive(false);
1550 } else {
1551 navBarNode->GetRenderContext()->UpdateOpacity(1.0f);
1552 navBarLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
1553 navBarNode->SetJSViewActive(true);
1554 }
1555 auto navigationContentNode = AceType::DynamicCast<FrameNode>(navigationGroupNode->GetContentNode());
1556 CHECK_NULL_VOID(navigationContentNode);
1557 auto navDestinationNode =
1558 AceType::DynamicCast<NavDestinationGroupNode>(navigationContentNode->GetLastChild());
1559 CHECK_NULL_VOID(navDestinationNode);
1560 auto navDestinationPattern = navDestinationNode->GetPattern<NavDestinationPattern>();
1561 auto navDestinationFocusHub = navDestinationNode->GetFocusHub();
1562 CHECK_NULL_VOID(navDestinationFocusHub);
1563 auto defaultFocusHub = navDestinationFocusHub->GetChildFocusNodeByType(FocusNodeType::DEFAULT);
1564 if (!defaultFocusHub && navDestinationNode->GetChildren(true).size() <= EMPTY_DESTINATION_CHILD_SIZE &&
1565 navDestinationPattern->GetBackButtonState()) {
1566 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navDestinationNode->GetTitleBarNode());
1567 CHECK_NULL_VOID(titleBarNode);
1568 auto backButtonNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetBackButton());
1569 backButtonNode->GetOrCreateFocusHub()->SetIsDefaultFocus(true);
1570 auto navigation = pattern->GetHost();
1571 CHECK_NULL_VOID(navigation);
1572 auto navigationFocusHub = navigation->GetFocusHub();
1573 CHECK_NULL_VOID(navigationFocusHub);
1574 auto navDestinationFocusView = navDestinationNode->GetPattern<FocusView>();
1575 if (navigationFocusHub->IsCurrentFocus() && navDestinationFocusView) {
1576 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1577 navDestinationFocusView->SetIsViewRootScopeFocused(false);
1578 }
1579 navDestinationFocusView->FocusViewShow();
1580 }
1581 }
1582 },
1583 TaskExecutor::TaskType::UI, "ArkUINavigationDirtyLayoutWrapperSwap",
1584 TaskExecutor::GetPriorityTypeWithCheck(PriorityType::VIP));
1585 }
1586 auto navigationLayoutProperty = AceType::DynamicCast<NavigationLayoutProperty>(hostNode->GetLayoutProperty());
1587 CHECK_NULL_RETURN(navigationLayoutProperty, false);
1588 UpdateTitleModeChangeEventHub(hostNode);
1589 FireNavBarWidthChangeEvent(dirty);
1590 AddDragBarHotZoneRect();
1591 AddDividerHotZoneRect();
1592 ifNeedInit_ = false;
1593 return false;
1594 }
1595
AbortAnimation(RefPtr<NavigationGroupNode> & hostNode)1596 void NavigationPattern::AbortAnimation(RefPtr<NavigationGroupNode>& hostNode)
1597 {
1598 TAG_LOGD(AceLogTag::ACE_NAVIGATION, "Aborting navigation animations");
1599 if (!hostNode->GetPushAnimations().empty()) {
1600 auto pushAnimations = hostNode->GetPushAnimations();
1601 for (const auto& animation : pushAnimations) {
1602 if (animation) {
1603 AnimationUtils::StopAnimation(animation);
1604 }
1605 }
1606 }
1607 if (!hostNode->GetPopAnimations().empty()) {
1608 auto popAnimations = hostNode->GetPopAnimations();
1609 for (const auto& animation : popAnimations) {
1610 if (animation) {
1611 AnimationUtils::StopAnimation(animation);
1612 }
1613 }
1614 }
1615 hostNode->CleanPushAnimations();
1616 hostNode->CleanPopAnimations();
1617 }
1618
UpdateContextRect(const RefPtr<NavDestinationGroupNode> & curDestination,const RefPtr<NavigationGroupNode> & hostNode)1619 void NavigationPattern::UpdateContextRect(
1620 const RefPtr<NavDestinationGroupNode>& curDestination, const RefPtr<NavigationGroupNode>& hostNode)
1621 {
1622 CHECK_NULL_VOID(curDestination);
1623 CHECK_NULL_VOID(hostNode);
1624 auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
1625 CHECK_NULL_VOID(navBarNode);
1626 auto navigationPattern = AceType::DynamicCast<NavigationPattern>(hostNode->GetPattern());
1627 CHECK_NULL_VOID(navigationPattern);
1628
1629 if (navigationPattern->GetNavigationMode() == NavigationMode::STACK) {
1630 curDestination->GetRenderContext()->SetActualForegroundColor(Color::TRANSPARENT);
1631 return;
1632 }
1633 auto navigationLayoutProperty = hostNode->GetLayoutProperty<NavigationLayoutProperty>();
1634 CHECK_NULL_VOID(navigationLayoutProperty);
1635 auto navBarProperty = navBarNode->GetLayoutProperty();
1636 navBarProperty->UpdateVisibility(VisibleType::VISIBLE);
1637 navBarNode->SetJSViewActive(true);
1638 if (!curDestination->IsOnAnimation()) {
1639 curDestination->GetRenderContext()->UpdateTranslateInXY(OffsetF { 0.0f, 0.0f });
1640 curDestination->GetRenderContext()->SetActualForegroundColor(Color::TRANSPARENT);
1641 navBarNode->GetEventHub<EventHub>()->SetEnabledInternal(true);
1642 auto titleBarNode = DynamicCast<TitleBarNode>(navBarNode->GetTitleBarNode());
1643 CHECK_NULL_VOID(titleBarNode);
1644 auto titleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
1645 CHECK_NULL_VOID(titleNode);
1646 titleNode->GetRenderContext()->UpdateTranslateInXY(OffsetF { 0.0f, 0.0f });
1647 }
1648 }
1649
UpdateTitleModeChangeEventHub(const RefPtr<NavigationGroupNode> & hostNode)1650 bool NavigationPattern::UpdateTitleModeChangeEventHub(const RefPtr<NavigationGroupNode>& hostNode)
1651 {
1652 auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
1653 CHECK_NULL_RETURN(navBarNode, false);
1654 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navBarNode->GetTitleBarNode());
1655 CHECK_NULL_RETURN(titleBarNode, false);
1656 auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
1657 CHECK_NULL_RETURN(titleBarLayoutProperty, false);
1658 auto eventHub = hostNode->GetEventHub<NavigationEventHub>();
1659 CHECK_NULL_RETURN(eventHub, false);
1660 if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) == NavigationTitleMode::FREE) {
1661 auto titleBarPattern = AceType::DynamicCast<TitleBarPattern>(titleBarNode->GetPattern());
1662 CHECK_NULL_RETURN(titleBarPattern, false);
1663 NavigationTitleMode titleMode = titleBarPattern->GetNavigationTitleMode();
1664 if (titleMode != NavigationTitleMode::FREE && titleMode_ != titleMode) {
1665 NavigationTitleModeChangeEvent navigationTitleModeChange(titleMode == NavigationTitleMode::MINI);
1666 eventHub->FireChangeEvent(&navigationTitleModeChange);
1667 titleMode_ = titleMode;
1668 }
1669 }
1670 return true;
1671 }
1672
FireNavBarWidthChangeEvent(const RefPtr<LayoutWrapper> & layoutWrapper)1673 void NavigationPattern::FireNavBarWidthChangeEvent(const RefPtr<LayoutWrapper>& layoutWrapper)
1674 {
1675 auto host = GetHost();
1676 CHECK_NULL_VOID(host);
1677 auto geometryNode = host->GetGeometryNode();
1678 CHECK_NULL_VOID(geometryNode);
1679 auto frameSize = geometryNode->GetFrameSize();
1680 auto frameWidth = frameSize.Width();
1681 auto navigationLayoutProperty = GetLayoutProperty<NavigationLayoutProperty>();
1682 CHECK_NULL_VOID(navigationLayoutProperty);
1683 auto userSetDimensionUnit = navigationLayoutProperty->GetNavBarWidthValue(DEFAULT_NAV_BAR_WIDTH).Unit();
1684 CHECK_NULL_VOID(layoutWrapper);
1685 auto layoutAlgorithm = layoutWrapper->GetLayoutAlgorithm();
1686 CHECK_NULL_VOID(layoutAlgorithm);
1687 auto navigationLayoutAlgorithm = AceType::DynamicCast<NavigationLayoutAlgorithm>(
1688 layoutAlgorithm->GetLayoutAlgorithm());
1689 CHECK_NULL_VOID(navigationLayoutAlgorithm);
1690 auto realBavBarWidth = navigationLayoutAlgorithm->GetRealNavBarWidth();
1691 auto realNavBarWidthDimension = Dimension(realBavBarWidth, DimensionUnit::PX);
1692 Dimension usrSetUnitWidth = Dimension(0.0, userSetDimensionUnit);
1693 if (!NearZero(frameWidth)) {
1694 usrSetUnitWidth = DimensionUnit::PERCENT == userSetDimensionUnit ?
1695 Dimension(realBavBarWidth / frameWidth, DimensionUnit::PERCENT) :
1696 Dimension(realNavBarWidthDimension.GetNativeValue(userSetDimensionUnit), userSetDimensionUnit);
1697 }
1698 auto eventHub = host->GetEventHub<NavigationEventHub>();
1699 CHECK_NULL_VOID(eventHub);
1700 eventHub->FireNavBarWidthChangeEvent(usrSetUnitWidth);
1701 }
1702
GenerateUINodeFromRecovery(int32_t lastStandardIndex,NavPathList & navPathList)1703 int32_t NavigationPattern::GenerateUINodeFromRecovery(int32_t lastStandardIndex, NavPathList& navPathList)
1704 {
1705 /**
1706 * In case several pages at the top of stack are dialog pages.
1707 * We need to recovery node until a standard page created.
1708 * And the creation process should be bottom-up to satisfy the order of life-cycle.
1709 */
1710 int32_t jsStackSize = static_cast<int32_t>(navPathList.size());
1711 int32_t removeSize = 0;
1712 for (int32_t index = lastStandardIndex; index < jsStackSize; ++ index) {
1713 if (navPathList[index].second || !navigationStack_->IsFromRecovery(index)) {
1714 continue;
1715 }
1716 if (!GenerateUINodeByIndex(index - removeSize, navPathList[index].second)) {
1717 removeSize++;
1718 continue;
1719 }
1720 navigationStack_->SetFromRecovery(index, false);
1721 auto navdestination = AceType::DynamicCast<NavDestinationGroupNode>(
1722 NavigationGroupNode::GetNavDestinationNode(navPathList[index].second));
1723 navdestination->SetNeedAppearFromRecovery(true);
1724 }
1725 return removeSize;
1726 }
1727
GenerateUINodeByIndex(int32_t index,RefPtr<UINode> & node)1728 bool NavigationPattern::GenerateUINodeByIndex(int32_t index, RefPtr<UINode>& node)
1729 {
1730 auto host = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1731 do {
1732 if (parentNode_.Upgrade() || !host) {
1733 break;
1734 }
1735 auto context = host->GetContext();
1736 // Avoid the loading problem of atomicservice on the home page
1737 if ((context && !context->GetInstallationFree()) || !context) {
1738 break;
1739 }
1740 RefPtr<UINode> parentCustomNode;
1741 auto curNode = host->GetParent();
1742 while (curNode) {
1743 auto curTag = curNode->GetTag();
1744 if (curTag == V2::JS_VIEW_ETS_TAG) {
1745 parentCustomNode = curNode;
1746 break;
1747 }
1748 curNode = curNode->GetParent();
1749 }
1750 auto pattern = host->GetPattern<NavigationPattern>();
1751 if (pattern && parentCustomNode) {
1752 pattern->SetParentCustomNode(parentCustomNode);
1753 }
1754 } while (false);
1755 bool isCreate = navigationStack_->CreateNodeByIndex(index, parentNode_, node);
1756 if (node) {
1757 node->SetFreeze(true, true);
1758 }
1759 auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(
1760 NavigationGroupNode::GetNavDestinationNode(node));
1761 CHECK_NULL_RETURN(navDestinationNode, isCreate);
1762 // set navigation id
1763 auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1764 auto navDestinationPattern = AceType::DynamicCast<NavDestinationPattern>(navDestinationNode->GetPattern());
1765 if (navigationNode && navDestinationPattern) {
1766 navDestinationPattern->SetNavigationNode(navigationNode);
1767 navDestinationPattern->SetNavigationId(navigationNode->GetInspectorId().value_or(""));
1768 }
1769 auto eventHub = navDestinationNode->GetEventHub<NavDestinationEventHub>();
1770 CHECK_NULL_RETURN(eventHub, isCreate);
1771 eventHub->FireOnWillAppear();
1772 return isCreate;
1773 }
1774
InitDividerMouseEvent(const RefPtr<InputEventHub> & inputHub)1775 void NavigationPattern::InitDividerMouseEvent(const RefPtr<InputEventHub>& inputHub)
1776 {
1777 CHECK_NULL_VOID(inputHub);
1778 CHECK_NULL_VOID(!hoverEvent_);
1779
1780 auto hoverTask = [weak = WeakClaim(this)](bool isHover) {
1781 auto pattern = weak.Upgrade();
1782 if (pattern) {
1783 pattern->OnHover(isHover);
1784 }
1785 };
1786 hoverEvent_ = MakeRefPtr<InputEvent>(std::move(hoverTask));
1787 inputHub->AddOnHoverEvent(hoverEvent_);
1788 }
1789
HandleDragStart()1790 void NavigationPattern::HandleDragStart()
1791 {
1792 preNavBarWidth_ = realNavBarWidth_;
1793 if (!isDividerDraggable_) {
1794 return;
1795 }
1796 isInDividerDrag_ = true;
1797 if (!enableDragBar_) {
1798 SetMouseStyle(MouseFormat::RESIZE_LEFT_RIGHT);
1799 }
1800 }
1801
HandleDragUpdate(float xOffset)1802 void NavigationPattern::HandleDragUpdate(float xOffset)
1803 {
1804 auto navigationLayoutProperty = GetLayoutProperty<NavigationLayoutProperty>();
1805 CHECK_NULL_VOID(navigationLayoutProperty);
1806 auto host = GetHost();
1807 CHECK_NULL_VOID(host);
1808 auto geometryNode = host->GetGeometryNode();
1809 CHECK_NULL_VOID(geometryNode);
1810 auto frameSize = geometryNode->GetFrameSize();
1811 auto frameWidth = frameSize.Width();
1812 auto constraint = navigationLayoutProperty->GetLayoutConstraint();
1813 auto parentSize = CreateIdealSize(constraint.value(), Axis::HORIZONTAL, MeasureType::MATCH_PARENT);
1814
1815 float minNavBarWidthPx = minNavBarWidthValue_.ConvertToPxWithSize(parentSize.Width().value_or(0.0f));
1816 float maxNavBarWidthPx = maxNavBarWidthValue_.ConvertToPxWithSize(parentSize.Width().value_or(0.0f));
1817 float minContentWidthPx = minContentWidthValue_.ConvertToPxWithSize(parentSize.Width().value_or(0.0f));
1818 auto dividerWidth = static_cast<float>(DIVIDER_WIDTH.ConvertToPx());
1819
1820 auto navigationPosition = navigationLayoutProperty->GetNavBarPosition().value_or(NavBarPosition::START);
1821 bool isNavBarStart = navigationPosition == NavBarPosition::START;
1822 auto navBarLine = isRightToLeft_ ? preNavBarWidth_ + (isNavBarStart ? -xOffset : xOffset)
1823 : preNavBarWidth_ + (isNavBarStart ? xOffset : -xOffset);
1824 float currentNavBarWidth = realNavBarWidth_;
1825
1826 if (maxNavBarWidthPx + dividerWidth + minContentWidthPx > frameWidth) {
1827 maxNavBarWidthPx = frameWidth - minContentWidthPx - dividerWidth;
1828 }
1829 navBarLine = std::min(navBarLine, maxNavBarWidthPx);
1830
1831 if (userSetMinContentFlag_ && !userSetNavBarRangeFlag_) {
1832 if (minContentWidthPx >= frameWidth) {
1833 realNavBarWidth_ = 0.0f;
1834 } else if (navBarLine + dividerWidth + minContentWidthPx <= frameWidth) {
1835 realNavBarWidth_ = navBarLine;
1836 } else {
1837 realNavBarWidth_ = frameWidth - minContentWidthPx - dividerWidth;
1838 }
1839 } else {
1840 realDividerWidth_ = dividerWidth;
1841 float remainingSpace = frameWidth - navBarLine - dividerWidth;
1842 if (remainingSpace >= minContentWidthPx) {
1843 realNavBarWidth_ = navBarLine;
1844 } else if (remainingSpace < minContentWidthPx && navBarLine > minNavBarWidthPx) {
1845 realNavBarWidth_ = frameWidth - minContentWidthPx - dividerWidth;
1846 } else {
1847 realNavBarWidth_ = minNavBarWidthPx;
1848 }
1849 }
1850 realNavBarWidth_ = std::min(realNavBarWidth_, frameWidth);
1851 realNavBarWidth_ = std::min(realNavBarWidth_, maxNavBarWidthPx);
1852 realNavBarWidth_ = std::max(realNavBarWidth_, minNavBarWidthPx);
1853 // MEASURE
1854 if (realNavBarWidth_ != currentNavBarWidth) {
1855 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
1856 }
1857 }
1858
HandleDragEnd()1859 void NavigationPattern::HandleDragEnd()
1860 {
1861 preNavBarWidth_ = realNavBarWidth_;
1862 if (!isDividerDraggable_) {
1863 return;
1864 }
1865 isInDividerDrag_ = false;
1866 SetMouseStyle(MouseFormat::DEFAULT);
1867 }
1868
InitDividerPanEvent(const RefPtr<GestureEventHub> & gestureHub)1869 void NavigationPattern::InitDividerPanEvent(const RefPtr<GestureEventHub>& gestureHub)
1870 {
1871 CHECK_NULL_VOID(!panEvent_);
1872 auto actionStartTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1873 auto pattern = weak.Upgrade();
1874 CHECK_NULL_VOID(pattern);
1875 pattern->HandleDragStart();
1876 };
1877 auto actionUpdateTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1878 auto pattern = weak.Upgrade();
1879 CHECK_NULL_VOID(pattern);
1880 pattern->HandleDragUpdate(static_cast<float>(info.GetOffsetX()));
1881 };
1882 auto actionEndTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1883 auto pattern = weak.Upgrade();
1884 CHECK_NULL_VOID(pattern);
1885 pattern->HandleDragEnd();
1886 };
1887 auto actionCancelTask = [weak = WeakClaim(this)]() {
1888 auto pattern = weak.Upgrade();
1889 CHECK_NULL_VOID(pattern);
1890 pattern->HandleDragEnd();
1891 };
1892 panEvent_ = MakeRefPtr<PanEvent>(
1893 std::move(actionStartTask), std::move(actionUpdateTask), std::move(actionEndTask), std::move(actionCancelTask));
1894 PanDirection panDirection = { .type = PanDirection::HORIZONTAL };
1895 gestureHub->AddPanEvent(panEvent_, panDirection, DEFAULT_PAN_FINGER, DEFAULT_PAN_DISTANCE);
1896 }
1897
InitDragBarPanEvent(const RefPtr<GestureEventHub> & gestureHub)1898 void NavigationPattern::InitDragBarPanEvent(const RefPtr<GestureEventHub>& gestureHub)
1899 {
1900 CHECK_NULL_VOID(!dragBarPanEvent_);
1901 auto actionStartTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1902 auto pattern = weak.Upgrade();
1903 CHECK_NULL_VOID(pattern);
1904 pattern->HandleDragStart();
1905 };
1906 auto actionUpdateTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1907 auto pattern = weak.Upgrade();
1908 CHECK_NULL_VOID(pattern);
1909 pattern->HandleDragUpdate(static_cast<float>(info.GetOffsetX()));
1910 };
1911 auto actionEndTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1912 auto pattern = weak.Upgrade();
1913 CHECK_NULL_VOID(pattern);
1914 pattern->HandleDragEnd();
1915 };
1916 auto actionCancelTask = [weak = WeakClaim(this)]() {
1917 auto pattern = weak.Upgrade();
1918 CHECK_NULL_VOID(pattern);
1919 pattern->HandleDragEnd();
1920 };
1921 dragBarPanEvent_ = MakeRefPtr<PanEvent>(
1922 std::move(actionStartTask), std::move(actionUpdateTask), std::move(actionEndTask), std::move(actionCancelTask));
1923 PanDirection panDirection = { .type = PanDirection::HORIZONTAL };
1924 gestureHub->AddPanEvent(dragBarPanEvent_, panDirection, DEFAULT_PAN_FINGER, DEFAULT_PAN_DISTANCE);
1925 }
1926
OnHover(bool isHover)1927 void NavigationPattern::OnHover(bool isHover)
1928 {
1929 if (isInDividerDrag_) {
1930 return;
1931 }
1932 auto layoutProperty = GetLayoutProperty<NavigationLayoutProperty>();
1933 CHECK_NULL_VOID(layoutProperty);
1934 auto userSetMinNavBarWidthValue = layoutProperty->GetMinNavBarWidthValue(Dimension(0.0));
1935 auto userSetMaxNavBarWidthValue = layoutProperty->GetMaxNavBarWidthValue(Dimension(0.0));
1936 bool navBarWidthRangeEqual = userSetMinNavBarWidthValue.Value() >= userSetMaxNavBarWidthValue.Value();
1937 if ((userSetNavBarWidthFlag_ && !userSetNavBarRangeFlag_) || (userSetNavBarRangeFlag_ && navBarWidthRangeEqual)) {
1938 isDividerDraggable_ = false;
1939 return;
1940 }
1941 isDividerDraggable_ = true;
1942 MouseFormat format = isHover ? MouseFormat::RESIZE_LEFT_RIGHT : MouseFormat::DEFAULT;
1943 SetMouseStyle(format);
1944 }
1945
GetDividerNode() const1946 RefPtr<FrameNode> NavigationPattern::GetDividerNode() const
1947 {
1948 auto host = GetHost();
1949 CHECK_NULL_RETURN(host, nullptr);
1950 auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(host);
1951 CHECK_NULL_RETURN(navigationNode, nullptr);
1952 auto dividerFrameNode = AceType::DynamicCast<FrameNode>(navigationNode->GetDividerNode());
1953 CHECK_NULL_RETURN(dividerFrameNode, nullptr);
1954 return dividerFrameNode;
1955 }
1956
GetDragBarNode() const1957 RefPtr<FrameNode> NavigationPattern::GetDragBarNode() const
1958 {
1959 auto host = GetHost();
1960 CHECK_NULL_RETURN(host, nullptr);
1961 auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(host);
1962 CHECK_NULL_RETURN(navigationNode, nullptr);
1963 auto dragBarNode = AceType::DynamicCast<FrameNode>(navigationNode->GetDragBarNode());
1964 CHECK_NULL_RETURN(dragBarNode, nullptr);
1965 return dragBarNode;
1966 }
1967
BeforeSyncGeometryProperties(const DirtySwapConfig &)1968 void NavigationPattern::BeforeSyncGeometryProperties(const DirtySwapConfig& /* config */)
1969 {
1970 AddDividerHotZoneRect();
1971 }
1972
AddDividerHotZoneRect()1973 void NavigationPattern::AddDividerHotZoneRect()
1974 {
1975 if (NearZero(realDividerWidth_)) {
1976 return;
1977 }
1978 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
1979 CHECK_NULL_VOID(hostNode);
1980 auto navBarNode = AceType::DynamicCast<FrameNode>(hostNode->GetNavBarNode());
1981 CHECK_NULL_VOID(navBarNode);
1982 auto geometryNode = navBarNode->GetGeometryNode();
1983 CHECK_NULL_VOID(geometryNode);
1984
1985 OffsetF hotZoneOffset;
1986 hotZoneOffset.SetX(-DEFAULT_DIVIDER_HOT_ZONE_HORIZONTAL_PADDING.ConvertToPx());
1987 hotZoneOffset.SetY(DEFAULT_DIVIDER_START_MARGIN.ConvertToPx());
1988 SizeF hotZoneSize;
1989 hotZoneSize.SetWidth(realDividerWidth_ + DIVIDER_HOT_ZONE_HORIZONTAL_PADDING_NUM *
1990 DEFAULT_DIVIDER_HOT_ZONE_HORIZONTAL_PADDING.ConvertToPx());
1991 hotZoneSize.SetHeight(geometryNode->GetFrameSize().Height());
1992 DimensionRect hotZoneRegion;
1993 auto paintHeight = GetPaintRectHeight(navBarNode);
1994 if (navigationMode_ == NavigationMode::STACK || enableDragBar_) {
1995 hotZoneRegion.SetSize(DimensionSize(Dimension(0.0f), Dimension(0.0f)));
1996 } else {
1997 hotZoneRegion.SetSize(DimensionSize(
1998 Dimension(hotZoneSize.Width()), Dimension(NearZero(paintHeight) ? hotZoneSize.Height() : paintHeight)));
1999 }
2000 hotZoneRegion.SetOffset(DimensionOffset(Dimension(hotZoneOffset.GetX()), Dimension(hotZoneOffset.GetY())));
2001
2002 std::vector<DimensionRect> mouseRegion;
2003 mouseRegion.emplace_back(hotZoneRegion);
2004
2005 auto dividerFrameNode = GetDividerNode();
2006 CHECK_NULL_VOID(dividerFrameNode);
2007 auto dividerGestureHub = dividerFrameNode->GetOrCreateGestureEventHub();
2008 CHECK_NULL_VOID(dividerGestureHub);
2009 dividerGestureHub->SetMouseResponseRegion(mouseRegion);
2010
2011 auto dragRectOffset = geometryNode->GetMarginFrameOffset();
2012 dragRectOffset.SetX(-DEFAULT_DRAG_REGION.ConvertToPx());
2013 dragRect_.SetOffset(dragRectOffset);
2014 if (navigationMode_ == NavigationMode::STACK || enableDragBar_) {
2015 dragRect_.SetSize(SizeF(0.0f, 0.0f));
2016 } else {
2017 dragRect_.SetSize(SizeF(DEFAULT_DRAG_REGION.ConvertToPx() * DEFAULT_HALF + realDividerWidth_,
2018 NearZero(paintHeight) ? geometryNode->GetFrameSize().Height() : paintHeight));
2019 }
2020
2021 std::vector<DimensionRect> responseRegion;
2022 DimensionOffset responseOffset(dragRectOffset);
2023 DimensionRect responseRect(Dimension(dragRect_.Width(), DimensionUnit::PX),
2024 Dimension(dragRect_.Height(), DimensionUnit::PX), responseOffset);
2025 responseRegion.emplace_back(responseRect);
2026 dividerGestureHub->SetResponseRegion(responseRegion);
2027 }
2028
AddDragBarHotZoneRect()2029 void NavigationPattern::AddDragBarHotZoneRect()
2030 {
2031 if (NearZero(realDividerWidth_)) {
2032 return;
2033 }
2034 auto dargBarNode = GetDragBarNode();
2035 CHECK_NULL_VOID(dargBarNode);
2036 auto geometryNode = dargBarNode->GetGeometryNode();
2037 CHECK_NULL_VOID(geometryNode);
2038 auto dragBarGestureHub = dargBarNode->GetOrCreateGestureEventHub();
2039 CHECK_NULL_VOID(dragBarGestureHub);
2040
2041 auto dragRectOffset = geometryNode->GetMarginFrameOffset();
2042 dragRectOffset.SetX(-DEFAULT_DRAG_BAR_HOT_ZONE.ConvertToPx());
2043 dragRectOffset.SetY(0.0f);
2044 dragBarRect_.SetOffset(dragRectOffset);
2045 if (navigationMode_ == NavigationMode::STACK) {
2046 dragBarRect_.SetSize(SizeF(0.0f, 0.0f));
2047 } else {
2048 dragBarRect_.SetSize(SizeF(DEFAULT_DRAG_BAR_HOT_ZONE.ConvertToPx() * DEFAULT_HALF +
2049 geometryNode->GetFrameSize().Width(), geometryNode->GetFrameSize().Height()));
2050 }
2051 std::vector<DimensionRect> responseRegion;
2052 DimensionOffset responseOffset(dragRectOffset);
2053 DimensionRect responseRect(Dimension(dragBarRect_.Width(), DimensionUnit::PX),
2054 Dimension(dragBarRect_.Height(), DimensionUnit::PX), responseOffset);
2055 responseRegion.emplace_back(responseRect);
2056 dragBarGestureHub->SetResponseRegion(responseRegion);
2057 }
2058
NotifyDialogChange(NavDestinationLifecycle lifecycle,bool isFromStandardIndex)2059 void NavigationPattern::NotifyDialogChange(NavDestinationLifecycle lifecycle, bool isFromStandardIndex)
2060 {
2061 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2062 CHECK_NULL_VOID(hostNode);
2063 const auto& navDestinationNodes = navigationStack_->GetAllNavDestinationNodes();
2064 int32_t lastStandardIndex = hostNode->GetLastStandardIndex();
2065 int32_t standardIndex = lastStandardIndex >= 0 ? lastStandardIndex : 0;
2066 int32_t start = isFromStandardIndex ? standardIndex : 0;
2067 int32_t end = isFromStandardIndex ? navigationStack_->Size() : standardIndex;
2068 bool isShow = (lifecycle == NavDestinationLifecycle::ON_SHOW)
2069 || (lifecycle == NavDestinationLifecycle::ON_WILL_SHOW);
2070 if (isShow) {
2071 for (int32_t index = start; index < end; index++) {
2072 NotifyDestinationLifecycle(navDestinationNodes[index].second, lifecycle);
2073 }
2074 } else {
2075 for (int32_t index = end - 1; index >= 0 && index >= start; index--) {
2076 NotifyDestinationLifecycle(navDestinationNodes[index].second, lifecycle);
2077 }
2078 }
2079 }
2080
DumpInfo()2081 void NavigationPattern::DumpInfo()
2082 {
2083 if (!navigationStack_) {
2084 return;
2085 }
2086 DumpLog::GetInstance().AddDesc(std::string("size").append(std::to_string(navigationStack_->Size())));
2087 }
2088
TriggerCustomAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage)2089 bool NavigationPattern::TriggerCustomAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
2090 const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage)
2091 {
2092 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "will trigger navigation custom animation");
2093 if ((!preTopNavDestination && !newTopNavDestination) || !onTransition_) {
2094 return false;
2095 }
2096 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2097 CHECK_NULL_RETURN(hostNode, false);
2098 hostNode->SetIsOnAnimation(true);
2099 if (!newTopNavDestination) {
2100 // pop animation with top navDestination, recover navBar visible tag
2101 hostNode->SetNeedSetInvisible(false);
2102 }
2103 auto proxy = AceType::MakeRefPtr<NavigationTransitionProxy>();
2104 proxy->SetPreDestination(preTopNavDestination);
2105 proxy->SetTopDestination(newTopNavDestination);
2106 auto proxyId = proxy->GetProxyId();
2107 proxyList_.emplace_back(proxy);
2108 auto navigationTransition = ExecuteTransition(preTopNavDestination, newTopNavDestination, isPopPage);
2109 if (!navigationTransition.isValid) {
2110 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "custom transition value is invalid, do default animation");
2111 return false;
2112 }
2113 ExecuteAddAnimation(preTopNavDestination, newTopNavDestination, isPopPage, proxy, navigationTransition);
2114 ACE_SCOPED_TRACE_COMMERCIAL("Navigation page custom transition start");
2115 if (navigationTransition.interactive) {
2116 PerfMonitor::GetPerfMonitor()->Start(PerfConstants::ABILITY_OR_PAGE_SWITCH_INTERACTIVE,
2117 PerfActionType::FIRST_MOVE, "");
2118 auto finishCallback = [weakNavigation = WeakClaim(this),
2119 weakPreNavDestination = WeakPtr<NavDestinationGroupNode>(preTopNavDestination),
2120 weakNewNavDestination = WeakPtr<NavDestinationGroupNode>(newTopNavDestination),
2121 isPopPage, proxyId]() {
2122 auto pattern = weakNavigation.Upgrade();
2123 CHECK_NULL_VOID(pattern);
2124 auto proxy = pattern->GetProxyById(proxyId);
2125 if (proxy == nullptr) {
2126 return;
2127 }
2128 if (!proxy->GetInteractive()) {
2129 pattern->RemoveProxyById(proxyId);
2130 return;
2131 }
2132 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "interactive animation is finish: %{public}d", proxy->GetIsSuccess());
2133 pattern->isFinishInteractiveAnimation_ = true;
2134 auto preDestination = weakPreNavDestination.Upgrade();
2135 auto topDestination = weakNewNavDestination.Upgrade();
2136 proxy->SetIsFinished(true);
2137 // this flag will be update in cancelTransition or finishTransition
2138 ACE_SCOPED_TRACE_COMMERCIAL("navigation page custom transition end");
2139 PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH_INTERACTIVE, true);
2140 if (proxy->GetIsSuccess()) {
2141 pattern->ClearRecoveryList();
2142 pattern->OnCustomAnimationFinish(preDestination, topDestination, isPopPage);
2143 } else {
2144 // fire page cancel transition
2145 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "interactive animation canceled");
2146 pattern->RecoveryToLastStack(preDestination, topDestination);
2147 pattern->SyncWithJsStackIfNeeded();
2148 }
2149 proxy->FireEndCallback();
2150 pattern->RemoveProxyById(proxyId);
2151 };
2152 auto pipelineContext = hostNode->GetContext();
2153 CHECK_NULL_RETURN(pipelineContext, false);
2154 auto navigationManager = pipelineContext->GetNavigationManager();
2155 CHECK_NULL_RETURN(navigationManager, false);
2156 navigationManager->SetInteractive(hostNode->GetId());
2157 proxy->SetInteractiveAnimation(AnimationUtils::CreateInteractiveAnimation(
2158 nullptr, finishCallback), finishCallback);
2159 navigationTransition.transition(proxy);
2160 isFinishInteractiveAnimation_ = false;
2161 navigationManager->FinishInteractiveAnimation();
2162 proxy->StartAnimation();
2163 } else {
2164 PerfMonitor::GetPerfMonitor()->Start(PerfConstants::ABILITY_OR_PAGE_SWITCH, PerfActionType::LAST_UP, "");
2165 ClearRecoveryList();
2166 navigationTransition.transition(proxy);
2167 // enable render group for text node during custom animation to reduce
2168 // unnecessary redrawing
2169 if (isPopPage && preTopNavDestination) {
2170 preTopNavDestination->UpdateTextNodeListAsRenderGroup(isPopPage, proxy);
2171 }
2172 if (!isPopPage && newTopNavDestination) {
2173 newTopNavDestination->UpdateTextNodeListAsRenderGroup(isPopPage, proxy);
2174 }
2175 }
2176
2177 RefPtr<EventHub> eventHub;
2178 if (!preTopNavDestination && navigationMode_ == NavigationMode::STACK) {
2179 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2180 CHECK_NULL_RETURN(hostNode, true);
2181 auto navBarNode = AceType::DynamicCast<FrameNode>(hostNode->GetNavBarNode());
2182 CHECK_NULL_RETURN(navBarNode, true);
2183 eventHub = navBarNode->GetEventHub<EventHub>();
2184 }
2185 if (preTopNavDestination) {
2186 eventHub = preTopNavDestination->GetEventHub<EventHub>();
2187 }
2188 CHECK_NULL_RETURN(eventHub, true);
2189 eventHub->SetEnabledInternal(false);
2190 return true;
2191 }
2192
OnCustomAnimationFinish(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage)2193 void NavigationPattern::OnCustomAnimationFinish(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
2194 const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage)
2195 {
2196 if (!preTopNavDestination && !newTopNavDestination) {
2197 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "preDestination and topDestination is invalid");
2198 return;
2199 }
2200 ACE_SCOPED_TRACE_COMMERCIAL("Navigation page custom transition end");
2201 PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH, true);
2202 auto replaceValue = navigationStack_->GetReplaceValue();
2203 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2204 CHECK_NULL_VOID(hostNode);
2205 hostNode->SetIsOnAnimation(false);
2206 auto id = hostNode->GetTopDestination() ? hostNode->GetTopDestination()->GetAccessibilityId() : -1;
2207 hostNode->OnAccessibilityEvent(
2208 AccessibilityEventType::PAGE_CHANGE, id, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID);
2209 do {
2210 if (replaceValue != 0) {
2211 if (preTopNavDestination) {
2212 preTopNavDestination->SetIsOnAnimation(false);
2213 }
2214 if (newTopNavDestination) {
2215 newTopNavDestination->SetIsOnAnimation(false);
2216 }
2217 hostNode->DealNavigationExit(preTopNavDestination, preTopNavDestination == nullptr);
2218 navigationStack_->UpdateReplaceValue(0);
2219 break;
2220 }
2221 if ((newTopNavDestination && preTopNavDestination && isPopPage) ||
2222 (preTopNavDestination && !newTopNavDestination)) {
2223 PageTransitionType preNodeTransitionType = preTopNavDestination->GetTransitionType();
2224 if (preNodeTransitionType != PageTransitionType::EXIT_POP) {
2225 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "previous destination node is executing another transition");
2226 return;
2227 }
2228 preTopNavDestination->SetIsOnAnimation(false);
2229 if (newTopNavDestination && newTopNavDestination->GetTransitionType() == PageTransitionType::ENTER_POP) {
2230 newTopNavDestination->SetIsOnAnimation(false);
2231 }
2232 auto preDestinationPattern = preTopNavDestination->GetPattern<NavDestinationPattern>();
2233 CHECK_NULL_VOID(preDestinationPattern);
2234 auto shallowBuilder = preDestinationPattern->GetShallowBuilder();
2235 if (shallowBuilder) {
2236 shallowBuilder->MarkIsExecuteDeepRenderDone(false);
2237 }
2238 auto parent = preTopNavDestination->GetParent();
2239 CHECK_NULL_VOID(parent);
2240 parent->RemoveChild(preTopNavDestination);
2241 parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
2242 break;
2243 }
2244 if ((newTopNavDestination && preTopNavDestination && !isPopPage) ||
2245 (!preTopNavDestination && newTopNavDestination && navigationMode_ == NavigationMode::STACK)) {
2246 hostNode->SetNeedSetInvisible(true);
2247 RefPtr<FrameNode> node;
2248 PageTransitionType preNodeTransitionType;
2249 if (preTopNavDestination) {
2250 preNodeTransitionType = preTopNavDestination->GetTransitionType();
2251 node = preTopNavDestination;
2252 } else {
2253 // pre destination is nullptr, preNode is navBarNode
2254 auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
2255 CHECK_NULL_VOID(navBarNode);
2256 preNodeTransitionType = navBarNode->GetTransitionType();
2257 node = AceType::DynamicCast<FrameNode>(hostNode->GetNavBarNode());
2258 CHECK_NULL_VOID(node);
2259 }
2260 if (newTopNavDestination && newTopNavDestination->GetTransitionType() == PageTransitionType::ENTER_PUSH) {
2261 newTopNavDestination->SetIsOnAnimation(false);
2262 }
2263 if (preNodeTransitionType != PageTransitionType::EXIT_PUSH) {
2264 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "previous destination node is executing another transition");
2265 return;
2266 }
2267 if (preTopNavDestination) {
2268 preTopNavDestination->SetIsOnAnimation(false);
2269 }
2270 // recover event hub
2271 auto eventHub = node->GetEventHub<EventHub>();
2272 if (eventHub) {
2273 eventHub->SetEnabledInternal(true);
2274 }
2275 bool isDialog = newTopNavDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG;
2276 if (isDialog) {
2277 return;
2278 }
2279 auto property = node->GetLayoutProperty();
2280 property->UpdateVisibility(VisibleType::INVISIBLE);
2281 node->SetJSViewActive(false);
2282 if (!preTopNavDestination) {
2283 hostNode->NotifyPageHide();
2284 }
2285 }
2286 } while (0);
2287 hostNode->RemoveDialogDestination();
2288 auto context = PipelineContext::GetCurrentContext();
2289 CHECK_NULL_VOID(context);
2290 context->MarkNeedFlushMouseEvent();
2291 }
2292
ExecuteTransition(const RefPtr<NavDestinationGroupNode> & preTopDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage)2293 NavigationTransition NavigationPattern::ExecuteTransition(const RefPtr<NavDestinationGroupNode>& preTopDestination,
2294 const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage)
2295 {
2296 NavigationTransition navigationTransition;
2297 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2298 CHECK_NULL_RETURN(hostNode, navigationTransition);
2299 NavigationOperation operation;
2300 auto currentProxy = GetTopNavigationProxy();
2301 auto preInfo = currentProxy->GetPreDestinationContext();
2302 auto topInfo = currentProxy->GetTopDestinationContext();
2303 auto replaceValue = navigationStack_->GetReplaceValue();
2304 if (replaceValue != 0) {
2305 operation = NavigationOperation::REPLACE;
2306 } else if (!preTopDestination) {
2307 operation = NavigationOperation::PUSH;
2308 // if animated with navBarNode, recover navBar visibility
2309 hostNode->SetNeedSetInvisible(false);
2310 } else {
2311 operation = (!newTopNavDestination || isPopPage) ? NavigationOperation::POP : NavigationOperation::PUSH;
2312 }
2313 /* set transition animation flag fro navBarNode or navDestinationNode */
2314 if (operation == NavigationOperation::PUSH) {
2315 if (preTopDestination != nullptr) {
2316 preTopDestination->SetTransitionType(PageTransitionType::EXIT_PUSH);
2317 } else {
2318 // preTopDestination is nullptr, previous node is navBar node
2319 auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
2320 CHECK_NULL_RETURN(navBarNode, navigationTransition);
2321 navBarNode->SetTransitionType(PageTransitionType::EXIT_PUSH);
2322 }
2323 if (newTopNavDestination != nullptr) {
2324 newTopNavDestination->SetTransitionType(PageTransitionType::ENTER_PUSH);
2325 }
2326 }
2327 if (operation == NavigationOperation::POP) {
2328 if (preTopDestination != nullptr) {
2329 preTopDestination->SetTransitionType(PageTransitionType::EXIT_POP);
2330 }
2331 if (newTopNavDestination != nullptr) {
2332 newTopNavDestination->SetTransitionType(PageTransitionType::ENTER_POP);
2333 } else {
2334 // newTopNavDestination is nullptr, current node is navBar node
2335 auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
2336 CHECK_NULL_RETURN(navBarNode, navigationTransition);
2337 navBarNode->SetTransitionType(PageTransitionType::ENTER_POP);
2338 }
2339 }
2340 LogCustomAnimationStart(preTopDestination, newTopNavDestination, operation);
2341 return onTransition_(preInfo, topInfo, operation);
2342 }
2343
OnColorConfigurationUpdate()2344 void NavigationPattern::OnColorConfigurationUpdate()
2345 {
2346 UpdateDividerBackgroundColor();
2347
2348 auto dragBarNode = GetDragBarNode();
2349 CHECK_NULL_VOID(dragBarNode);
2350 auto dragPattern = dragBarNode->GetPattern<NavigationDragBarPattern>();
2351 CHECK_NULL_VOID(dragPattern);
2352 dragPattern->UpdateDefaultColor();
2353 }
2354
UpdateDividerBackgroundColor()2355 void NavigationPattern::UpdateDividerBackgroundColor()
2356 {
2357 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2358 CHECK_NULL_VOID(navigationGroupNode);
2359 auto dividerNode = GetDividerNode();
2360 CHECK_NULL_VOID(dividerNode);
2361 auto theme = NavigationGetTheme(navigationGroupNode->GetThemeScopeId());
2362 CHECK_NULL_VOID(theme);
2363 dividerNode->GetRenderContext()->UpdateBackgroundColor(theme->GetNavigationDividerColor());
2364 dividerNode->MarkDirtyNode();
2365 }
2366
UpdateToobarFocusColor()2367 void NavigationPattern::UpdateToobarFocusColor()
2368 {
2369 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2370 CHECK_NULL_VOID(navigationGroupNode);
2371 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationGroupNode->GetNavBarNode());
2372 CHECK_NULL_VOID(navBarNode);
2373 auto toolBarNode = AceType::DynamicCast<NavToolbarNode>(navBarNode->GetPreToolBarNode());
2374 CHECK_NULL_VOID(toolBarNode);
2375 auto containerNode = AceType::DynamicCast<FrameNode>(toolBarNode->GetToolbarContainerNode());
2376 CHECK_NULL_VOID(containerNode);
2377 auto toolBarItemNodes = containerNode->GetChildren();
2378 auto theme = NavigationGetTheme(navigationGroupNode->GetThemeScopeId());
2379 CHECK_NULL_VOID(theme);
2380 for (auto& toolBarItemNode : toolBarItemNodes) {
2381 auto buttonNode = AceType::DynamicCast<FrameNode>(toolBarItemNode);
2382 CHECK_NULL_VOID(buttonNode);
2383 auto buttonPattern = AceType::DynamicCast<ButtonPattern>(buttonNode->GetPattern());
2384 CHECK_NULL_VOID(buttonPattern);
2385 buttonPattern->SetFocusBorderColor(theme->GetToolBarItemFocusColor());
2386 auto focusHub = buttonNode->GetFocusHub();
2387 CHECK_NULL_VOID(focusHub);
2388 focusHub->SetPaintColor(theme->GetToolBarItemFocusColor());
2389 }
2390 }
2391
OnThemeScopeUpdate(int32_t themeScopeId)2392 bool NavigationPattern::OnThemeScopeUpdate(int32_t themeScopeId)
2393 {
2394 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2395 CHECK_NULL_RETURN(navigationGroupNode, false);
2396 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationGroupNode->GetNavBarNode());
2397 CHECK_NULL_RETURN(navBarNode, false);
2398
2399 auto dividerNode = AceType::DynamicCast<FrameNode>(navBarNode->GetToolBarDividerNode());
2400 CHECK_NULL_RETURN(dividerNode, false);
2401
2402 auto theme = NavigationGetTheme(themeScopeId);
2403 CHECK_NULL_RETURN(theme, false);
2404
2405 auto dividerRenderProperty = dividerNode->GetPaintProperty<DividerRenderProperty>();
2406 CHECK_NULL_RETURN(dividerRenderProperty, false);
2407 dividerRenderProperty->UpdateDividerColor(theme->GetToolBarDividerColor());
2408
2409 navigationGroupNode->MarkModifyDone();
2410 return false;
2411 }
2412
UpdatePreNavDesZIndex(const RefPtr<FrameNode> & preTopNavDestination,const RefPtr<FrameNode> & newTopNavDestination,int32_t preLastStandardIndex)2413 void NavigationPattern::UpdatePreNavDesZIndex(const RefPtr<FrameNode> &preTopNavDestination,
2414 const RefPtr<FrameNode> &newTopNavDestination, int32_t preLastStandardIndex)
2415 {
2416 auto replaceVal = navigationStack_->GetReplaceValue();
2417 if (replaceVal != 0 && preTopNavDestination && newTopNavDestination) {
2418 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2419 CHECK_NULL_VOID(hostNode);
2420 auto navigationContentNode = AceType::DynamicCast<FrameNode>(hostNode->GetContentNode());
2421 CHECK_NULL_VOID(navigationContentNode);
2422 auto newDesNodeContext = newTopNavDestination->GetRenderContext();
2423 CHECK_NULL_VOID(newDesNodeContext);
2424 std::optional<int32_t> newNodeZIndex = newDesNodeContext->GetZIndex();
2425 int32_t standardIndex = newNodeZIndex.value_or(0) - 1;
2426 auto hideNodes = hostNode->GetHideNodes();
2427 for (auto iter = hideNodes.begin(); iter != hideNodes.end(); ++iter) {
2428 // if navdestination nodes is not need removed, default zIndex is satisfied, don't need change
2429 if (!iter->second) {
2430 continue;
2431 }
2432 auto navDestination = iter->first;
2433 if (!navDestination) {
2434 continue;
2435 }
2436 auto navDestinationContext = navDestination->GetRenderContext();
2437 if (!navDestinationContext) {
2438 continue;
2439 }
2440 // get navDestination index in hideNodes, use navdestination index in pre navigation stack
2441 int32_t hideNodesIndex =
2442 static_cast<int32_t>(hideNodes.size()) - (navDestination->GetIndex() - preLastStandardIndex);
2443 navDestinationContext->UpdateZIndex(standardIndex - hideNodesIndex);
2444 }
2445 auto preDesNodeContext = preTopNavDestination->GetRenderContext();
2446 CHECK_NULL_VOID(preDesNodeContext);
2447 preDesNodeContext->UpdateZIndex(standardIndex);
2448 navigationContentNode->RebuildRenderContextTree();
2449 auto context = PipelineContext::GetCurrentContext();
2450 CHECK_NULL_VOID(context);
2451 context->RequestFrame();
2452 }
2453 }
2454
SetNavigationStack(const RefPtr<NavigationStack> & navigationStack)2455 void NavigationPattern::SetNavigationStack(const RefPtr<NavigationStack>& navigationStack)
2456 {
2457 if (navigationStack_) {
2458 navigationStack_->SetOnStateChangedCallback(nullptr);
2459 }
2460 navigationStack_ = navigationStack;
2461 if (navigationStack_) {
2462 navigationStack_->SetNavigationNode(GetHost());
2463 WeakPtr<NavigationPattern> weakPattern = WeakClaim(this);
2464 auto id = Container::CurrentId();
2465 auto callback = [weakPattern, id]() {
2466 ContainerScope scope(id);
2467 auto pattern = weakPattern.Upgrade();
2468 CHECK_NULL_VOID(pattern);
2469 if (pattern->NeedSyncWithJsStackMarked()) {
2470 return;
2471 }
2472 pattern->MarkNeedSyncWithJsStack();
2473 auto context = PipelineContext::GetCurrentContext();
2474 CHECK_NULL_VOID(context);
2475 context->AddBuildFinishCallBack([weakPattern]() {
2476 auto pattern = weakPattern.Upgrade();
2477 CHECK_NULL_VOID(pattern);
2478 pattern->SyncWithJsStackIfNeeded();
2479 auto host = pattern->GetHost();
2480 CHECK_NULL_VOID(host);
2481 host->MarkDirtyNode();
2482 });
2483 context->RequestFrame();
2484 };
2485 navigationStack_->SetOnStateChangedCallback(callback);
2486 }
2487 }
2488
GetParentNavigationPattern()2489 RefPtr<NavigationPattern> NavigationPattern::GetParentNavigationPattern()
2490 {
2491 RefPtr<UINode> node = GetHost();
2492 CHECK_NULL_RETURN(node, nullptr);
2493 node = node->GetParent();
2494 while (node) {
2495 if (node->GetTag() == V2::NAVIGATION_VIEW_ETS_TAG) {
2496 break;
2497 }
2498 node = node->GetParent();
2499 }
2500 auto groupNode = AceType::DynamicCast<NavigationGroupNode>(node);
2501 CHECK_NULL_RETURN(groupNode, nullptr);
2502 return AceType::DynamicCast<NavigationPattern>(groupNode->GetPattern());
2503 }
2504
AttachNavigationStackToParent()2505 void NavigationPattern::AttachNavigationStackToParent()
2506 {
2507 CHECK_NULL_VOID(navigationStack_);
2508 auto parentPattern = GetParentNavigationPattern();
2509 CHECK_NULL_VOID(parentPattern);
2510 auto parentStack = parentPattern->GetNavigationStack();
2511 if (parentStack) {
2512 navigationStack_->OnAttachToParent(parentStack);
2513 }
2514 }
2515
DetachNavigationStackFromParent()2516 void NavigationPattern::DetachNavigationStackFromParent()
2517 {
2518 if (navigationStack_) {
2519 navigationStack_->OnDetachFromParent();
2520 }
2521 }
2522
DealTransitionVisibility(const RefPtr<FrameNode> & node,bool isVisible,bool isNavBar)2523 void NavigationPattern::DealTransitionVisibility(const RefPtr<FrameNode>& node, bool isVisible, bool isNavBar)
2524 {
2525 auto renderContext = node->GetRenderContext();
2526 if (!renderContext->HasDisappearTransition()) {
2527 auto layoutProperty = node->GetLayoutProperty();
2528 layoutProperty->UpdateVisibility(isVisible ? VisibleType::VISIBLE : VisibleType::INVISIBLE);
2529 node->SetJSViewActive(isVisible);
2530 return;
2531 }
2532 auto layoutProperty = node->GetLayoutProperty();
2533 layoutProperty->UpdateVisibility(isVisible ? VisibleType::VISIBLE : VisibleType::INVISIBLE, true);
2534 renderContext->SetTransitionOutCallback([weakNode = WeakPtr<FrameNode>(node), isVisible, isNavBar] {
2535 auto curNode = weakNode.Upgrade();
2536 CHECK_NULL_VOID(curNode);
2537 if (isNavBar) {
2538 auto navBarNode = AceType::DynamicCast<NavBarNode>(curNode);
2539 if (navBarNode->GetTransitionType() != PageTransitionType::EXIT_PUSH) {
2540 return;
2541 }
2542 } else {
2543 auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
2544 if (navDestinationNode->GetTransitionType() != PageTransitionType::EXIT_PUSH) {
2545 return;
2546 }
2547 }
2548 curNode->SetJSViewActive(isVisible);
2549 });
2550 }
2551
AddToDumpManager()2552 void NavigationPattern::AddToDumpManager()
2553 {
2554 auto node = GetHost();
2555 auto context = PipelineContext::GetCurrentContext();
2556 if (!node || !context) {
2557 return;
2558 }
2559 auto mgr = context->GetNavigationManager();
2560 if (!mgr) {
2561 return;
2562 }
2563 auto callback = [weakPattern = WeakClaim(this)](int depth) {
2564 auto pattern = weakPattern.Upgrade();
2565 if (!pattern) {
2566 return;
2567 }
2568 const auto& stack = pattern->GetNavigationStack();
2569 if (!stack) {
2570 return;
2571 }
2572 auto infos = stack->DumpStackInfo();
2573 };
2574 mgr->AddNavigationDumpCallback(node->GetId(), node->GetDepth(), callback);
2575 }
2576
RemoveFromDumpManager()2577 void NavigationPattern::RemoveFromDumpManager()
2578 {
2579 auto node = GetHost();
2580 auto context = PipelineContext::GetCurrentContext();
2581 if (!node || !context) {
2582 return;
2583 }
2584 auto mgr = context->GetNavigationManager();
2585 if (mgr) {
2586 mgr->RemoveNavigationDumpCallback(node->GetId(), node->GetDepth());
2587 }
2588 }
2589
FireInterceptionEvent(bool isBefore,const std::optional<std::pair<std::string,RefPtr<UINode>>> & newTopPath)2590 void NavigationPattern::FireInterceptionEvent(bool isBefore,
2591 const std::optional<std::pair<std::string, RefPtr<UINode>>>& newTopPath)
2592 {
2593 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2594 CHECK_NULL_VOID(hostNode);
2595 RefPtr<NavDestinationContext> to;
2596 if (newTopPath.has_value()) {
2597 auto topDestination =
2598 AceType::DynamicCast<NavDestinationGroupNode>(hostNode->GetNavDestinationNode(newTopPath->second));
2599 if (topDestination) {
2600 auto pattern = AceType::DynamicCast<NavDestinationPattern>(topDestination->GetPattern());
2601 to = pattern->GetNavDestinationContext();
2602 }
2603 }
2604 NavigationOperation operation;
2605 if (isReplace_ != 0) {
2606 operation = NavigationOperation::REPLACE;
2607 } else {
2608 operation = lastPreIndex_ == -1 ? NavigationOperation::POP : NavigationOperation::PUSH;
2609 }
2610 auto layoutProperty = hostNode->GetLayoutProperty<NavigationLayoutProperty>();
2611 // mode is split and stack size is one,don't need to do animation.
2612 if ((layoutProperty->GetUsrNavigationModeValue(NavigationMode::AUTO) == NavigationMode::SPLIT
2613 || navigationMode_ == NavigationMode::SPLIT) && !preContext_) {
2614 isAnimated_ = false;
2615 }
2616 navigationStack_->FireNavigationInterception(isBefore, preContext_, to, operation,
2617 isAnimated_);
2618
2619 if (!isBefore) {
2620 NotifyNavDestinationSwitch(preContext_, to, operation);
2621 }
2622 }
2623
UpdateIsAnimation(const std::optional<std::pair<std::string,RefPtr<UINode>>> & preTopNavPath)2624 void NavigationPattern::UpdateIsAnimation(const std::optional<std::pair<std::string, RefPtr<UINode>>>& preTopNavPath)
2625 {
2626 auto disAbleAnimation = navigationStack_->GetDisableAnimation();
2627 auto animated = navigationStack_->GetAnimatedValue();
2628 // current animation flag is false
2629 if (disAbleAnimation || !animated) {
2630 isAnimated_ = false;
2631 return;
2632 }
2633 // check is dialog mode
2634 bool isDialog = false;
2635 if (preTopNavPath.has_value()) {
2636 auto preDestination = AceType::DynamicCast<NavDestinationGroupNode>(
2637 NavigationGroupNode::GetNavDestinationNode(preTopNavPath->second));
2638 if (preDestination) {
2639 isDialog = isDialog || (preDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG);
2640 }
2641 }
2642 auto topNode = navigationStack_->Get();
2643 if (topNode) {
2644 auto newTopDestination = AceType::DynamicCast<NavDestinationGroupNode>(
2645 NavigationGroupNode::GetNavDestinationNode(topNode));
2646 if (newTopDestination) {
2647 isDialog = isDialog || (newTopDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG);
2648 }
2649 }
2650 if (!isDialog) {
2651 isAnimated_ = true;
2652 return;
2653 }
2654 isAnimated_ = isCustomAnimation_;
2655 }
2656
NotifyNavDestinationSwitch(const RefPtr<NavDestinationContext> & from,const RefPtr<NavDestinationContext> & to,NavigationOperation operation)2657 void NavigationPattern::NotifyNavDestinationSwitch(const RefPtr<NavDestinationContext>& from,
2658 const RefPtr<NavDestinationContext>& to, NavigationOperation operation)
2659 {
2660 auto host = GetHost();
2661 auto NavdestinationSwitchFunc =
2662 UIObserverHandler::GetInstance().GetHandleNavDestinationSwitchFunc();
2663 if (!host || !NavdestinationSwitchFunc) {
2664 return;
2665 }
2666
2667 std::string navigationId = host->GetInspectorIdValue("");
2668 std::optional<NavDestinationInfo> fromInfo;
2669 std::optional<NavDestinationInfo> toInfo;
2670 RefPtr<NavPathInfo> pathInfo = nullptr;
2671 if (from) {
2672 pathInfo = from->GetNavPathInfo();
2673 } else if (to) {
2674 pathInfo = to->GetNavPathInfo();
2675 }
2676 if (pathInfo) {
2677 pathInfo->OpenScope();
2678 }
2679 BuildNavDestinationInfoFromContext(navigationId, NavDestinationState::ON_HIDDEN, from, true, fromInfo);
2680 BuildNavDestinationInfoFromContext(navigationId, NavDestinationState::ON_SHOWN, to, false, toInfo);
2681 UIObserverHandler::GetInstance().NotifyNavDestinationSwitch(
2682 std::move(fromInfo), std::move(toInfo), operation);
2683 if (pathInfo) {
2684 pathInfo->CloseScope();
2685 }
2686 }
2687
StartTransition(const RefPtr<NavDestinationGroupNode> & preDestination,const RefPtr<NavDestinationGroupNode> & topDestination,bool isAnimated,bool isPopPage,bool isNeedVisible)2688 void NavigationPattern::StartTransition(const RefPtr<NavDestinationGroupNode>& preDestination,
2689 const RefPtr<NavDestinationGroupNode>& topDestination,
2690 bool isAnimated, bool isPopPage, bool isNeedVisible)
2691 {
2692 std::string fromPathInfo;
2693 std::string toPathInfo;
2694 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2695 CHECK_NULL_VOID(hostNode);
2696 bool isNotNeedAnimation = !isAnimated;
2697 #if defined(ENABLE_NAV_SPLIT_MODE)
2698 isNotNeedAnimation = !isAnimated ||
2699 (navigationMode_ == NavigationMode::SPLIT && navigationStack_->Size() <= 1 &&
2700 !isBackPage_ && !isCustomAnimation_);
2701 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "StartTransition navigationMode_:%{public}d isNotNeedAnimation:%{public}d",
2702 navigationMode_, isNotNeedAnimation);
2703 #endif
2704
2705 std::string fromNavDestinationName = "";
2706 std::string toNavDestinationName = "";
2707 if (preDestination) {
2708 fromPathInfo = preDestination->GetNavDestinationPathInfo();
2709 auto preDestinationPattern = preDestination->GetPattern<NavDestinationPattern>();
2710 CHECK_NULL_VOID(preDestinationPattern);
2711 fromNavDestinationName = preDestinationPattern->GetName();
2712 fromPathInfo += ", navDesitinationName: " + fromNavDestinationName;
2713 if ((isPopPage || preDestination->NeedRemoveInPush()) && isNotNeedAnimation) {
2714 /**
2715 * when transition without animation, 'pop' and 'push with remove' need to post
2716 * afterLayoutTask to delay old top's onDisappear. So set this flag to 'false'
2717 */
2718 preDestination->SetIsAnimated(false);
2719 }
2720 } else {
2721 fromPathInfo = hostNode->GetNavigationPathInfo();
2722 }
2723 if (topDestination) {
2724 toPathInfo = topDestination->GetNavDestinationPathInfo();
2725 auto topDestinationPattern = topDestination->GetPattern<NavDestinationPattern>();
2726 CHECK_NULL_VOID(topDestinationPattern);
2727 toNavDestinationName = topDestinationPattern->GetName();
2728 toPathInfo += ", navDesitinationName: " + toNavDestinationName;
2729 } else {
2730 toPathInfo = hostNode->GetNavigationPathInfo();
2731 }
2732 ACE_SCOPED_TRACE_COMMERCIAL("NavDestination Page from %s to %s", fromPathInfo.c_str(), toPathInfo.c_str());
2733 ResSchedReport::GetInstance().HandlePageTransition(fromNavDestinationName, toNavDestinationName, "navigation");
2734
2735 // fire onWillHide
2736 if (!isPopPage && !preDestination && navigationMode_ == NavigationMode::STACK) {
2737 // NavBar will be covered in STACK mode
2738 auto navBarNode = AceType::DynamicCast<FrameNode>(hostNode->GetNavBarNode());
2739 ProcessAutoSave(navBarNode);
2740 }
2741 if (isPopPage || (preDestination &&
2742 (hostNode->GetLastStandardIndex() > preDestination->GetIndex() || preDestination->NeedRemoveInPush()))) {
2743 NotifyDestinationLifecycle(preDestination, NavDestinationLifecycle::ON_WILL_HIDE);
2744 }
2745 hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_WILL_HIDE);
2746 auto pipeline = PipelineContext::GetCurrentContext();
2747 CHECK_NULL_VOID(pipeline);
2748 auto navigationManager = pipeline->GetNavigationManager();
2749 navigationManager->FireNavigationUpdateCallback();
2750 auto overlayManager = pipeline->GetOverlayManager();
2751 if (overlayManager) {
2752 overlayManager->RemoveAllModalInOverlay(false);
2753 }
2754 if (topDestination) {
2755 NotifyDialogChange(NavDestinationLifecycle::ON_WILL_SHOW, true);
2756 }
2757 if (isNotNeedAnimation) {
2758 FireShowAndHideLifecycle(preDestination, topDestination, isPopPage, false);
2759 TransitionWithOutAnimation(preDestination, topDestination, isPopPage, isNeedVisible);
2760 return;
2761 }
2762 pipeline->AddAfterLayoutTask([weakNavigation = WeakClaim(this),
2763 weakPreDestination = WeakPtr<NavDestinationGroupNode>(preDestination),
2764 weakTopDestination = WeakPtr<NavDestinationGroupNode>(topDestination),
2765 isPopPage, isNeedVisible]() {
2766 auto navigationPattern = AceType::DynamicCast<NavigationPattern>(weakNavigation.Upgrade());
2767 CHECK_NULL_VOID(navigationPattern);
2768 auto preDestination = weakPreDestination.Upgrade();
2769 auto topDestination = weakTopDestination.Upgrade();
2770 navigationPattern->FireShowAndHideLifecycle(preDestination, topDestination, isPopPage, true);
2771 navigationPattern->TransitionWithAnimation(preDestination, topDestination, isPopPage, isNeedVisible);
2772 });
2773 }
2774
ProcessAutoSave(const RefPtr<FrameNode> & node)2775 void NavigationPattern::ProcessAutoSave(const RefPtr<FrameNode>& node)
2776 {
2777 CHECK_NULL_VOID(node);
2778 if (!node->NeedRequestAutoSave()) {
2779 return;
2780 }
2781 auto container = Container::Current();
2782 CHECK_NULL_VOID(container);
2783 container->RequestAutoSave(node);
2784 }
2785
NotifyDestinationLifecycle(const RefPtr<UINode> & uiNode,NavDestinationLifecycle lifecycle,NavDestinationActiveReason reason)2786 void NavigationPattern::NotifyDestinationLifecycle(const RefPtr<UINode>& uiNode,
2787 NavDestinationLifecycle lifecycle, NavDestinationActiveReason reason)
2788 {
2789 auto curDestination =
2790 AceType::DynamicCast<NavDestinationGroupNode>(NavigationGroupNode::GetNavDestinationNode(uiNode));
2791 CHECK_NULL_VOID(curDestination);
2792 auto eventHub = curDestination->GetEventHub<NavDestinationEventHub>();
2793 CHECK_NULL_VOID(eventHub);
2794 if (lifecycle == NavDestinationLifecycle::ON_WILL_DISAPPEAR) {
2795 NavigationPattern::FireNavigationLifecycleChange(curDestination, lifecycle);
2796 eventHub->FireOnWillDisAppear();
2797 return;
2798 }
2799 auto navDestinationPattern = curDestination->GetPattern<NavDestinationPattern>();
2800 CHECK_NULL_VOID(navDestinationPattern);
2801 if (lifecycle == NavDestinationLifecycle::ON_INACTIVE) {
2802 FireOnInactiveLifecycle(curDestination, reason);
2803 return;
2804 }
2805 if (lifecycle == NavDestinationLifecycle::ON_ACTIVE) {
2806 FireOnActiveLifecycle(curDestination, reason);
2807 return;
2808 }
2809 if ((navDestinationPattern->GetIsOnShow() && (lifecycle == NavDestinationLifecycle::ON_SHOW ||
2810 lifecycle == NavDestinationLifecycle::ON_WILL_SHOW)) ||
2811 (!navDestinationPattern->GetIsOnShow() && (lifecycle == NavDestinationLifecycle::ON_HIDE ||
2812 lifecycle == NavDestinationLifecycle::ON_WILL_HIDE))) {
2813 return;
2814 }
2815 if (lifecycle == NavDestinationLifecycle::ON_WILL_SHOW) {
2816 eventHub->FireOnWillShow();
2817 NavigationPattern::FireNavigationLifecycleChange(curDestination, lifecycle);
2818 return;
2819 }
2820 if (lifecycle == NavDestinationLifecycle::ON_SHOW) {
2821 FireOnShowLifecycle(curDestination);
2822 return;
2823 }
2824 NavigationPattern::FireNavigationLifecycleChange(curDestination, lifecycle);
2825 if (lifecycle == NavDestinationLifecycle::ON_WILL_HIDE) {
2826 eventHub->FireOnWillHide();
2827 return;
2828 }
2829 if (lifecycle == NavDestinationLifecycle::ON_HIDE) {
2830 eventHub->FireOnHiddenEvent(navDestinationPattern->GetName());
2831 NotifyPageHide(navDestinationPattern->GetName());
2832 navDestinationPattern->SetIsOnShow(false);
2833 }
2834 }
2835
FireOnShowLifecycle(const RefPtr<NavDestinationGroupNode> & curDestination)2836 void NavigationPattern::FireOnShowLifecycle(const RefPtr<NavDestinationGroupNode>& curDestination)
2837 {
2838 auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2839 CHECK_NULL_VOID(navigationNode);
2840 auto parentDestinationNode = navigationNode->GetParentDestinationNode().Upgrade();
2841 if (CheckParentDestinationIsOnhide(parentDestinationNode) && CheckDestinationIsPush(parentDestinationNode)) {
2842 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "parentDestinationNode is onhide");
2843 return;
2844 }
2845 auto param = Recorder::EventRecorder::Get().IsPageParamRecordEnable() ? navigationStack_->GetRouteParam() : "";
2846 auto eventHub = curDestination->GetEventHub<NavDestinationEventHub>();
2847 CHECK_NULL_VOID(eventHub);
2848 auto navDestinationPattern = curDestination->GetPattern<NavDestinationPattern>();
2849 CHECK_NULL_VOID(navDestinationPattern);
2850 eventHub->FireOnShownEvent(navDestinationPattern->GetName(), param);
2851 NotifyPageShow(navDestinationPattern->GetName());
2852 navDestinationPattern->SetIsOnShow(true);
2853 NavigationPattern::FireNavigationLifecycleChange(curDestination, NavDestinationLifecycle::ON_SHOW);
2854 }
2855
FireOnActiveLifecycle(const RefPtr<NavDestinationGroupNode> & curDestination,NavDestinationActiveReason reason)2856 void NavigationPattern::FireOnActiveLifecycle(const RefPtr<NavDestinationGroupNode>& curDestination,
2857 NavDestinationActiveReason reason)
2858 {
2859 auto navDestinationPattern = curDestination->GetPattern<NavDestinationPattern>();
2860 CHECK_NULL_VOID(navDestinationPattern);
2861 if (navDestinationPattern->IsActive() || CheckParentDestinationInactive()) {
2862 return;
2863 }
2864 auto eventHub = curDestination->GetEventHub<NavDestinationEventHub>();
2865 CHECK_NULL_VOID(eventHub);
2866 navDestinationPattern->SetIsActive(true);
2867 eventHub->FireOnActive(static_cast<int32_t>(reason));
2868 NavigationPattern::FireNavigationLifecycle(curDestination, NavDestinationLifecycle::ON_ACTIVE, reason);
2869 }
2870
FireOnInactiveLifecycle(const RefPtr<NavDestinationGroupNode> & curDestination,NavDestinationActiveReason reason)2871 void NavigationPattern::FireOnInactiveLifecycle(const RefPtr<NavDestinationGroupNode>& curDestination,
2872 NavDestinationActiveReason reason)
2873 {
2874 auto navDestinationPattern = curDestination->GetPattern<NavDestinationPattern>();
2875 CHECK_NULL_VOID(navDestinationPattern);
2876 if (!navDestinationPattern->IsActive()) {
2877 return;
2878 }
2879 auto eventHub = curDestination->GetEventHub<NavDestinationEventHub>();
2880 CHECK_NULL_VOID(eventHub);
2881 navDestinationPattern->SetIsActive(false);
2882 NavigationPattern::FireNavigationLifecycle(curDestination, NavDestinationLifecycle::ON_INACTIVE, reason);
2883 eventHub->FireOnInactive(static_cast<int32_t>(reason));
2884 }
2885
GetNavdestinationJsonArray()2886 std::unique_ptr<JsonValue> NavigationPattern::GetNavdestinationJsonArray()
2887 {
2888 auto allNavdestinationInfo = JsonUtil::CreateArray(true);
2889 const auto& navdestinationNodes = GetAllNavDestinationNodes();
2890 for (auto iter : navdestinationNodes) {
2891 auto navdestinationInfo = JsonUtil::Create(true);
2892 auto navdestinationNode =
2893 AceType::DynamicCast<NavDestinationGroupNode>(NavigationGroupNode::GetNavDestinationNode(iter.second));
2894 if (!navdestinationNode) {
2895 continue;
2896 }
2897 if (!navdestinationNode->CanRecovery()) {
2898 continue;
2899 }
2900 auto navdestinationPattern = navdestinationNode->GetPattern<NavDestinationPattern>();
2901 if (!navdestinationPattern) {
2902 continue;
2903 }
2904 auto name = navdestinationPattern->GetName();
2905 auto param = navigationStack_->GetStringifyParamByIndex(navdestinationNode->GetIndex());
2906 auto mode = static_cast<int32_t>(navdestinationNode->GetNavDestinationMode());
2907 navdestinationInfo->Put("name", name.c_str());
2908 navdestinationInfo->Put("param", param.c_str());
2909 navdestinationInfo->Put("mode", mode);
2910 allNavdestinationInfo->Put(navdestinationInfo);
2911 }
2912 return allNavdestinationInfo;
2913 }
2914
RestoreJsStackIfNeeded()2915 void NavigationPattern::RestoreJsStackIfNeeded()
2916 {
2917 auto pipeline = PipelineContext::GetCurrentContext();
2918 CHECK_NULL_VOID(pipeline);
2919 auto navigationManager = pipeline->GetNavigationManager();
2920 CHECK_NULL_VOID(navigationManager);
2921 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2922 CHECK_NULL_VOID(hostNode);
2923 auto navdestinationsInfo = navigationManager->GetNavigationRecoveryInfo(hostNode->GetCurId());
2924 if (navdestinationsInfo.empty()) {
2925 return;
2926 }
2927 navigationStack_->SetPathArray(navdestinationsInfo);
2928 }
2929
PerformanceEventReport(int32_t nodeCount,int32_t depth,const std::string & navDestinationName)2930 void NavigationPattern::PerformanceEventReport(int32_t nodeCount, int32_t depth, const std::string& navDestinationName)
2931 {
2932 if (nodeCount >= PAGE_NODES) {
2933 EventReport::ReportPageNodeOverflow(navDestinationName, nodeCount, PAGE_NODES);
2934 }
2935 if (depth >= PAGE_DEPTH) {
2936 EventReport::ReportPageDepthOverflow(navDestinationName, depth, PAGE_DEPTH);
2937 }
2938 }
2939
FireShowAndHideLifecycle(const RefPtr<NavDestinationGroupNode> & preDestination,const RefPtr<NavDestinationGroupNode> & topDestination,bool isPopPage,bool isAnimated)2940 void NavigationPattern::FireShowAndHideLifecycle(const RefPtr<NavDestinationGroupNode>& preDestination,
2941 const RefPtr<NavDestinationGroupNode>& topDestination, bool isPopPage, bool isAnimated)
2942 {
2943 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2944 CHECK_NULL_VOID(hostNode);
2945 // don't move position hide lifecycle is from top to end
2946 if (preDestination) {
2947 NotifyDestinationLifecycle(preDestination, NavDestinationLifecycle::ON_INACTIVE);
2948 auto lastStandardIndex = hostNode->GetLastStandardIndex();
2949 if (isPopPage || lastStandardIndex > preDestination->GetIndex() || preDestination->NeedRemoveInPush()) {
2950 // fire preTop Destination lifecycle
2951 NotifyDestinationLifecycle(preDestination, NavDestinationLifecycle::ON_HIDE);
2952 }
2953 }
2954 // fire remove navDestination and invisible navDestination lifecycle for pop or clear
2955 hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_HIDE);
2956 if (isPopPage || (preDestination && preDestination->NeedRemoveInPush())) {
2957 // fire removed preDestination lifecycle for pop many times or clear
2958 NotifyDestinationLifecycle(preDestination, NavDestinationLifecycle::ON_WILL_DISAPPEAR);
2959 }
2960 // fire removed navDestination lifecycle
2961 hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_WILL_DISAPPEAR);
2962 if (!isAnimated) {
2963 auto pipelineContext = PipelineContext::GetCurrentContext();
2964 CHECK_NULL_VOID(pipelineContext);
2965 pipelineContext->AddAfterLayoutTask([weakNavigation = WeakClaim(this),
2966 weakTopDestination = WeakPtr<NavDestinationGroupNode>(topDestination)]() {
2967 auto navigation = weakNavigation.Upgrade();
2968 CHECK_NULL_VOID(navigation);
2969 auto topDestination = weakTopDestination.Upgrade();
2970 navigation->NotifyDialogChange(NavDestinationLifecycle::ON_SHOW, true);
2971 navigation->NotifyDestinationLifecycle(topDestination, NavDestinationLifecycle::ON_ACTIVE);
2972 });
2973 } else {
2974 NotifyDialogChange(NavDestinationLifecycle::ON_SHOW, true);
2975 NotifyDestinationLifecycle(topDestination, NavDestinationLifecycle::ON_ACTIVE);
2976 }
2977 FireInterceptionEvent(false, navigationStack_->GetTopNavPath());
2978 }
2979
OnWindowSizeChanged(int32_t,int32_t,WindowSizeChangeReason type)2980 void NavigationPattern::OnWindowSizeChanged(int32_t /*width*/, int32_t /*height*/, WindowSizeChangeReason type)
2981 {
2982 if (WindowSizeChangeReason::ROTATION == type) {
2983 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2984 CHECK_NULL_VOID(hostNode);
2985 AbortAnimation(hostNode);
2986 CloseLongPressDialog();
2987 }
2988 }
2989
OnWindowHide()2990 void NavigationPattern::OnWindowHide()
2991 {
2992 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
2993 CHECK_NULL_VOID(hostNode);
2994 auto navigationPattern = hostNode->GetPattern<NavigationPattern>();
2995 CHECK_NULL_VOID(navigationPattern);
2996 navigationPattern->SyncWithJsStackIfNeeded();
2997 }
2998
NotifyPerfMonitorPageMsg(const std::string & pageName)2999 void NavigationPattern::NotifyPerfMonitorPageMsg(const std::string& pageName)
3000 {
3001 auto container = Container::Current();
3002 if (container != nullptr && PerfMonitor::GetPerfMonitor() != nullptr) {
3003 std::string bundleName = container->GetBundleName();
3004 PerfMonitor::GetPerfMonitor()->ReportPageShowMsg("", bundleName, pageName);
3005 }
3006 }
3007
RefreshFocusToDestination()3008 void NavigationPattern::RefreshFocusToDestination()
3009 {
3010 auto newTopNavPath = navigationStack_->GetTopNavPath();
3011 if (!newTopNavPath.has_value()) {
3012 return;
3013 }
3014 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
3015 CHECK_NULL_VOID(hostNode);
3016 auto navBarNode = AceType::DynamicCast<FrameNode>(hostNode->GetNavBarNode());
3017 CHECK_NULL_VOID(navBarNode);
3018 auto navBarFocus = navBarNode->GetFocusHub();
3019 CHECK_NULL_VOID(navBarFocus);
3020 if (!navBarFocus->IsCurrentFocus()) {
3021 return;
3022 }
3023 auto newTopNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(
3024 NavigationGroupNode::GetNavDestinationNode(newTopNavPath->second));
3025 CHECK_NULL_VOID(newTopNavDestination);
3026 if (!GetIsFocusable(newTopNavDestination)) {
3027 return;
3028 }
3029 auto navDestinationFocusView = newTopNavDestination->GetPattern<FocusView>();
3030 CHECK_NULL_VOID(navDestinationFocusView);
3031 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TWELVE)) {
3032 navDestinationFocusView->SetIsViewRootScopeFocused(false);
3033 }
3034 navDestinationFocusView->FocusViewShow();
3035 }
3036
RecoveryToLastStack(const RefPtr<NavDestinationGroupNode> & preTopDestination,const RefPtr<NavDestinationGroupNode> & newTopDestination)3037 void NavigationPattern::RecoveryToLastStack(
3038 const RefPtr<NavDestinationGroupNode>& preTopDestination,
3039 const RefPtr<NavDestinationGroupNode>& newTopDestination)
3040 {
3041 if (preTopDestination) {
3042 preTopDestination->SetIsOnAnimation(false);
3043 preTopDestination->SetInCurrentStack(true);
3044 }
3045 if (newTopDestination) {
3046 newTopDestination->SetIsOnAnimation(false);
3047 }
3048 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
3049 CHECK_NULL_VOID(hostNode);
3050 hostNode->CleanHideNodes();
3051 CHECK_NULL_VOID(navigationStack_);
3052 navigationStack_->SetNavPathList(navigationStack_->GetRecoveryList());
3053
3054 // update cached node
3055 auto destinationNodes = navigationStack_->GetAllNavDestinationNodes();
3056 for (uint32_t index = 0; index < destinationNodes.size(); index++) {
3057 auto childNode = destinationNodes[index];
3058 if (!childNode.second) {
3059 continue;
3060 }
3061 auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(
3062 NavigationGroupNode::GetNavDestinationNode(childNode.second));
3063 if (!navDestinationNode) {
3064 continue;
3065 }
3066 // update pre cache node to cache node list
3067 auto cacheNode = navigationStack_->GetFromCacheNode(childNode.first);
3068 if (cacheNode && cacheNode == childNode.second) {
3069 navigationStack_->AddCacheNode(childNode.first, childNode.second);
3070 }
3071 }
3072 hostNode->UpdateNavDestinationNodeWithoutMarkDirty(nullptr, navigationModeChange_);
3073
3074 // recover lifecycle state before transition
3075 NotifyDestinationLifecycle(preTopDestination, NavDestinationLifecycle::ON_INACTIVE);
3076 hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_HIDE);
3077 hostNode->FireHideNodeChange(NavDestinationLifecycle::ON_WILL_DISAPPEAR);
3078 NotifyDialogChange(NavDestinationLifecycle::ON_SHOW, true);
3079 NotifyDestinationLifecycle(newTopDestination, NavDestinationLifecycle::ON_ACTIVE);
3080 hostNode->RemoveDialogDestination(false, true);
3081 hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
3082
3083 // update name index
3084 navigationStack_->RecoveryNavigationStack();
3085 ACE_SCOPED_TRACE_COMMERCIAL("Navigation page transition end");
3086 PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH, true);
3087 hostNode->SetIsOnAnimation(false);
3088 auto id = hostNode->GetTopDestination() ? hostNode->GetTopDestination()->GetAccessibilityId() : -1;
3089 hostNode->OnAccessibilityEvent(
3090 AccessibilityEventType::PAGE_CHANGE, id, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID);
3091 }
3092
ExecuteAddAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage,const RefPtr<NavigationTransitionProxy> & proxy,NavigationTransition navigationTransition)3093 bool NavigationPattern::ExecuteAddAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
3094 const RefPtr<NavDestinationGroupNode>& newTopNavDestination,
3095 bool isPopPage, const RefPtr<NavigationTransitionProxy>& proxy,
3096 NavigationTransition navigationTransition)
3097 {
3098 // custom animation return undefined,finish this transition
3099 if (!navigationTransition.isValid) {
3100 proxy->SetIsSuccess(false);
3101 proxy->SetIsFinished(true);
3102 return false;
3103 }
3104 if (preTopNavDestination) {
3105 preTopNavDestination->SetIsOnAnimation(true);
3106 if (!isPopPage) {
3107 auto renderContext = preTopNavDestination->GetRenderContext();
3108 CHECK_NULL_RETURN(renderContext, false);
3109 renderContext->RemoveClipWithRRect();
3110 }
3111 }
3112 if (newTopNavDestination) {
3113 newTopNavDestination->SetIsOnAnimation(true);
3114 }
3115 auto proxyId = proxy->GetProxyId();
3116 proxy->SetInteractive(navigationTransition.interactive);
3117 // set on transition end callback
3118 proxy->SetEndCallback(std::move(navigationTransition.endCallback));
3119 proxy->SetFinishTransitionEvent([weakNavigation = WeakClaim(this),
3120 weakPreNavDestination = WeakPtr<NavDestinationGroupNode>(preTopNavDestination),
3121 weakNewNavDestination = WeakPtr<NavDestinationGroupNode>(newTopNavDestination),
3122 isPopPage, proxyId]() {
3123 auto pattern = weakNavigation.Upgrade();
3124 CHECK_NULL_VOID(pattern);
3125 auto proxy = pattern->GetProxyById(proxyId);
3126 auto preDestination = weakPreNavDestination.Upgrade();
3127 auto topDestination = weakNewNavDestination.Upgrade();
3128 // disable render group for text node after the custom animation
3129 if (isPopPage && preDestination) {
3130 preDestination->ReleaseTextNodeList();
3131 }
3132 if (!isPopPage && topDestination) {
3133 topDestination->ReleaseTextNodeList();
3134 }
3135
3136 // to avoid call finishTransition many times
3137 if (proxy == nullptr) {
3138 TAG_LOGW(AceLogTag::ACE_NAVIGATION, "custom animation proxy is empty or is finished");
3139 return;
3140 }
3141 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "custom animation finish end");
3142 proxy->SetIsFinished(true);
3143 // update pre navigation stack
3144 ACE_SCOPED_TRACE_COMMERCIAL("navigation page custom transition end");
3145 PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH, true);
3146 pattern->ClearRecoveryList();
3147 pattern->OnCustomAnimationFinish(preDestination, topDestination, isPopPage);
3148 pattern->RemoveProxyById(proxyId);
3149 });
3150 // add timeout callback
3151 auto timeout = navigationTransition.timeout;
3152 auto hostNode = GetHost();
3153 CHECK_NULL_RETURN(hostNode, false);
3154 auto pipeline = hostNode->GetContext();
3155 CHECK_NULL_RETURN(pipeline, false);
3156 auto taskExecutor = pipeline->GetTaskExecutor();
3157 CHECK_NULL_RETURN(taskExecutor, false);
3158 if (timeout < 0) {
3159 return true;
3160 }
3161 // deal timeout callback
3162 taskExecutor->PostDelayedTask(
3163 [weakProxy = WeakPtr<NavigationTransitionProxy>(proxy)] {
3164 auto transitionProxy = weakProxy.Upgrade();
3165 CHECK_NULL_VOID(transitionProxy);
3166 transitionProxy->FireFinishCallback();
3167 },
3168 TaskExecutor::TaskType::UI, timeout, "ArkUINavigationTransitionProxyFinish");
3169 return true;
3170 }
3171
GetIsFocusable(const RefPtr<FrameNode> & frameNode)3172 bool NavigationPattern::GetIsFocusable(const RefPtr<FrameNode>& frameNode)
3173 {
3174 CHECK_NULL_RETURN(frameNode, false);
3175 auto hostNode = AceType::DynamicCast<FrameNode>(GetHost());
3176 CHECK_NULL_RETURN(hostNode, false);
3177 auto focusHub = hostNode->GetFocusHub();
3178 CHECK_NULL_RETURN(focusHub, false);
3179 if (!focusHub->IsFocusableWholePath()) {
3180 return false;
3181 }
3182 auto currentFocusHub = frameNode->GetFocusHub();
3183 CHECK_NULL_RETURN(currentFocusHub, false);
3184 return currentFocusHub->IsFocusableNode();
3185 }
3186
IsLastStdChange()3187 bool NavigationPattern::IsLastStdChange()
3188 {
3189 // check whether last std navdestination id is changed, change return true, not change return false
3190 auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
3191 CHECK_NULL_RETURN(navigationNode, false);
3192 auto& navPathList = navigationStack_->GetAllNavDestinationNodes();
3193 auto& preNavPathList = navigationStack_->GetAllNavDestinationNodesPrev();
3194 auto lastStdIndex = navigationNode->GetLastStandardIndex();
3195 auto preLastStdIndex = navigationNode->GetPreLastStandardIndex();
3196 if (preLastStdIndex == -1 && lastStdIndex == -1) {
3197 return false;
3198 }
3199 if (preLastStdIndex != -1 && lastStdIndex != -1) {
3200 // check new and pre std navdestination id changed or not
3201 auto preStd = NavigationGroupNode::GetNavDestinationNode(preNavPathList[preLastStdIndex].second.Upgrade());
3202 auto newStd = NavigationGroupNode::GetNavDestinationNode(navPathList[lastStdIndex].second);
3203 if (preStd && newStd) {
3204 return preStd != newStd;
3205 }
3206 }
3207 return true;
3208 }
3209
FollowStdNavdestinationAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage)3210 void NavigationPattern::FollowStdNavdestinationAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
3211 const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage)
3212 {
3213 auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
3214 CHECK_NULL_VOID(navigationNode);
3215 if (preTopNavDestination && newTopNavDestination) {
3216 if (isPopPage) {
3217 navigationNode->TransitionWithDialogPop(preTopNavDestination, newTopNavDestination);
3218 } else {
3219 navigationNode->TransitionWithDialogPush(preTopNavDestination, newTopNavDestination);
3220 }
3221 return;
3222 }
3223 if (newTopNavDestination && navigationMode_ == NavigationMode::STACK) {
3224 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationNode->GetNavBarNode());
3225 CHECK_NULL_VOID(navBarNode);
3226 navigationNode->TransitionWithDialogPush(navBarNode, newTopNavDestination, true);
3227 return;
3228 }
3229 if (preTopNavDestination) {
3230 if (navigationMode_ == NavigationMode::SPLIT) {
3231 navigationNode->TransitionWithDialogPop(preTopNavDestination, nullptr);
3232 }
3233 if (navigationMode_ == NavigationMode::STACK) {
3234 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationNode->GetNavBarNode());
3235 CHECK_NULL_VOID(navBarNode);
3236 navigationNode->TransitionWithDialogPop(preTopNavDestination, navBarNode, true);
3237 }
3238 }
3239 }
3240
TransitionWithDialogAnimation(const RefPtr<NavDestinationGroupNode> & preTopNavDestination,const RefPtr<NavDestinationGroupNode> & newTopNavDestination,bool isPopPage)3241 void NavigationPattern::TransitionWithDialogAnimation(const RefPtr<NavDestinationGroupNode>& preTopNavDestination,
3242 const RefPtr<NavDestinationGroupNode>& newTopNavDestination, bool isPopPage)
3243 {
3244 auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
3245 CHECK_NULL_VOID(navigationNode);
3246
3247 // if last standard id is not changed and new top navdestination is standard
3248 if (!isPopPage && !IsLastStdChange() && newTopNavDestination &&
3249 newTopNavDestination->GetNavDestinationMode() == NavDestinationMode::STANDARD) {
3250 return;
3251 }
3252 auto replaceVal = navigationStack_->GetReplaceValue();
3253 if (replaceVal != 0) {
3254 ReplaceAnimation(preTopNavDestination, newTopNavDestination);
3255 return;
3256 }
3257 // last std id is not change, but new dialogs came into stack and upward animation
3258 if (!IsLastStdChange()) {
3259 if (isPopPage) {
3260 navigationNode->StartDialogtransition(preTopNavDestination, newTopNavDestination, false);
3261 } else {
3262 if (!preTopNavDestination && navigationMode_ == NavigationMode::SPLIT) {
3263 // if split mode and push one dialog at the first time, no animation
3264 return;
3265 }
3266 navigationNode->StartDialogtransition(preTopNavDestination, newTopNavDestination, true);
3267 }
3268 return;
3269 }
3270 FollowStdNavdestinationAnimation(preTopNavDestination, newTopNavDestination, isPopPage);
3271 }
3272
DumpInfo(std::unique_ptr<JsonValue> & json)3273 void NavigationPattern::DumpInfo(std::unique_ptr<JsonValue>& json)
3274 {
3275 if (!navigationStack_) {
3276 return;
3277 }
3278 json->Put("size", std::to_string(navigationStack_->Size()).c_str());
3279 }
3280
CreateDragBarNode(const RefPtr<NavigationGroupNode> & navigationGroupNode)3281 void NavigationPattern::CreateDragBarNode(const RefPtr<NavigationGroupNode>& navigationGroupNode)
3282 {
3283 auto dragBarNode = FrameNode::GetOrCreateFrameNode("DragBar", ElementRegister::GetInstance()->MakeUniqueId(),
3284 []() { return AceType::MakeRefPtr<NavigationDragBarPattern>(); });
3285 auto dragBarLayoutProperty = dragBarNode->GetLayoutProperty();
3286 CHECK_NULL_VOID(dragBarLayoutProperty);
3287 auto theme = NavigationGetTheme();
3288 CHECK_NULL_VOID(theme);
3289 auto renderContext = dragBarNode->GetRenderContext();
3290 CHECK_NULL_VOID(renderContext);
3291 renderContext->UpdateBackBlurRadius(DRAG_BAR_BLUR_RADIUS);
3292 renderContext->UpdateBorderRadius(BorderRadiusProperty(DRAG_BAR_RADIUS));
3293 renderContext->UpdateZIndex(1);
3294 dragBarNode->MarkModifyDone();
3295 auto dragBarItem = CreateDragBarItemNode();
3296 dragBarItem->MountToParent(dragBarNode);
3297 dragBarNode->MountToParent(navigationGroupNode);
3298 navigationGroupNode->SetDragBarNode(dragBarNode);
3299
3300 auto dragBarPattern = dragBarNode->GetPattern<NavigationDragBarPattern>();
3301 CHECK_NULL_VOID(dragBarPattern);
3302 dragBarPattern->UpdateDefaultColor();
3303 }
3304
CreateDragBarItemNode()3305 RefPtr<FrameNode> NavigationPattern::CreateDragBarItemNode()
3306 {
3307 auto dragBarItemNode = FrameNode::GetOrCreateFrameNode("DragBarItem",
3308 ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<Pattern>(); });
3309 auto dragBarItemLayoutProperty = dragBarItemNode->GetLayoutProperty();
3310 CHECK_NULL_RETURN(dragBarItemLayoutProperty, nullptr);
3311 dragBarItemLayoutProperty->UpdateAlignment(Alignment::CENTER);
3312 auto renderContext = dragBarItemNode->GetRenderContext();
3313 CHECK_NULL_RETURN(renderContext, nullptr);
3314 renderContext->UpdateZIndex(SECOND_ZINDEX_VALUE);
3315 renderContext->UpdateBorderRadius(BorderRadiusProperty(DRAG_BAR_ITEM_RADIUS));
3316 dragBarItemNode->MarkModifyDone();
3317 return dragBarItemNode;
3318 }
3319
GetProxyById(uint64_t id) const3320 RefPtr<NavigationTransitionProxy> NavigationPattern::GetProxyById(uint64_t id) const
3321 {
3322 for (auto proxy : proxyList_) {
3323 if (proxy && proxy->GetProxyId() == id) {
3324 return proxy;
3325 }
3326 }
3327 return nullptr;
3328 }
3329
RemoveProxyById(uint64_t id)3330 void NavigationPattern::RemoveProxyById(uint64_t id)
3331 {
3332 for (auto it = proxyList_.begin(); it != proxyList_.end(); ++it) {
3333 if (*it && (*it)->GetProxyId() == id) {
3334 it = proxyList_.erase(it);
3335 return;
3336 }
3337 }
3338 }
3339
InitTouchEvent(const RefPtr<GestureEventHub> & gestureHub)3340 void NavigationPattern::InitTouchEvent(const RefPtr<GestureEventHub>& gestureHub)
3341 {
3342 if (touchEvent_) {
3343 return;
3344 }
3345 auto touchTask = [weak = WeakClaim(this)](const TouchEventInfo& info) {
3346 auto pattern = weak.Upgrade();
3347 CHECK_NULL_VOID(pattern);
3348 pattern->HandleTouchEvent(info);
3349 };
3350 touchEvent_ = MakeRefPtr<TouchEventImpl>(std::move(touchTask));
3351 gestureHub->AddTouchEvent(touchEvent_);
3352 }
3353
HandleTouchEvent(const TouchEventInfo & info)3354 void NavigationPattern::HandleTouchEvent(const TouchEventInfo& info)
3355 {
3356 auto touchType = info.GetTouches().front().GetTouchType();
3357 if (touchType == TouchType::DOWN) {
3358 HandleTouchDown();
3359 }
3360 if (touchType == TouchType::UP || touchType == TouchType::CANCEL) {
3361 HandleTouchUp();
3362 }
3363 }
3364
HandleTouchDown()3365 void NavigationPattern::HandleTouchDown()
3366 {
3367 auto dragBarNode = GetDragBarNode();
3368 CHECK_NULL_VOID(dragBarNode);
3369 auto dragPattern = dragBarNode->GetPattern<NavigationDragBarPattern>();
3370 CHECK_NULL_VOID(dragPattern);
3371 dragPattern->UpdateActiveColor();
3372
3373 auto dividerNode = GetDividerNode();
3374 CHECK_NULL_VOID(dividerNode);
3375 auto dividerRenderContext = dividerNode->GetRenderContext();
3376 CHECK_NULL_VOID(dividerRenderContext);
3377 auto theme = NavigationGetTheme();
3378 CHECK_NULL_VOID(theme);
3379 NG::Gradient gradient;
3380 gradient.CreateGradientWithType(NG::GradientType::LINEAR);
3381 gradient.AddColor(CreatePercentGradientColor(0, theme->GetDviderLightBlueColor()));
3382 gradient.AddColor(CreatePercentGradientColor(HALF_POSITION, theme->GetDviderDarkBlueColor()));
3383 gradient.AddColor(CreatePercentGradientColor(END_POSITION, theme->GetDviderLightBlueColor()));
3384 dividerRenderContext->UpdateBackgroundColor(Color::TRANSPARENT);
3385 dividerRenderContext->UpdateLinearGradient(gradient);
3386 }
3387
HandleTouchUp()3388 void NavigationPattern::HandleTouchUp()
3389 {
3390 auto dragBarNode = GetDragBarNode();
3391 CHECK_NULL_VOID(dragBarNode);
3392 auto dragPattern = dragBarNode->GetPattern<NavigationDragBarPattern>();
3393 CHECK_NULL_VOID(dragPattern);
3394 dragPattern->UpdateDefaultColor();
3395
3396 auto theme = NavigationGetTheme();
3397 CHECK_NULL_VOID(theme);
3398 auto dividerNode = GetDividerNode();
3399 CHECK_NULL_VOID(dividerNode);
3400 NG::Gradient gradient;
3401 gradient.CreateGradientWithType(NG::GradientType::LINEAR);
3402 gradient.AddColor(CreatePercentGradientColor(0, Color::TRANSPARENT));
3403 dividerNode->GetRenderContext()->UpdateLinearGradient(gradient);
3404 dividerNode->GetRenderContext()->UpdateBackgroundColor(theme->GetNavigationDividerColor());
3405 }
3406
CheckContentNeedMeasure(const RefPtr<FrameNode> & node)3407 void NavigationPattern::CheckContentNeedMeasure(const RefPtr<FrameNode>& node)
3408 {
3409 auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(node);
3410 CHECK_NULL_VOID(navigationNode);
3411 auto navigationLayoutProperty = navigationNode->GetLayoutProperty<NavigationLayoutProperty>();
3412 CHECK_NULL_VOID(navigationLayoutProperty);
3413 if (!NavigationLayoutAlgorithm::IsAutoHeight(navigationLayoutProperty)) {
3414 return;
3415 }
3416 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "Navigation height is auto, content need to measure after pushAnimation ends");
3417 auto contentNode = navigationNode->GetContentNode();
3418 CHECK_NULL_VOID(contentNode);
3419 contentNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
3420 }
3421
CloseLongPressDialog()3422 void NavigationPattern::CloseLongPressDialog()
3423 {
3424 auto hostNode = AceType::DynamicCast<NavigationGroupNode>(GetHost());
3425 CHECK_NULL_VOID(hostNode);
3426 auto pipeline = hostNode->GetContext();
3427 CHECK_NULL_VOID(pipeline);
3428 auto overlayManager = pipeline->GetOverlayManager();
3429 CHECK_NULL_VOID(overlayManager);
3430
3431 auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetNavBarNode());
3432 CHECK_NULL_VOID(navBarNode);
3433 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navBarNode->GetTitleBarNode());
3434 CHECK_NULL_VOID(titleBarNode);
3435 auto titleBarPattern = AceType::DynamicCast<TitleBarPattern>(titleBarNode->GetPattern());
3436 CHECK_NULL_VOID(titleBarPattern);
3437 auto backButtonDialogNode = titleBarPattern->GetBackButtonDialogNode();
3438 if (backButtonDialogNode) {
3439 overlayManager->CloseDialog(backButtonDialogNode);
3440 titleBarPattern->SetBackButtonDialogNode(nullptr);
3441 }
3442
3443 auto menuItemDialogNode = titleBarPattern->GetLargeFontPopUpDialogNode();
3444 if (menuItemDialogNode) {
3445 overlayManager->CloseDialog(menuItemDialogNode);
3446 titleBarPattern->SetLargeFontPopUpDialogNode(nullptr);
3447 }
3448
3449 auto toolBarNode = AceType::DynamicCast<NavToolbarNode>(navBarNode->GetToolBarNode());
3450 CHECK_NULL_VOID(toolBarNode);
3451 auto toolBarPattern = AceType::DynamicCast<NavToolbarPattern>(toolBarNode->GetPattern());
3452 CHECK_NULL_VOID(toolBarPattern);
3453 auto toolBarItemDialogNode = toolBarPattern->GetDialogNode();
3454 if (toolBarItemDialogNode) {
3455 overlayManager->CloseDialog(toolBarItemDialogNode);
3456 toolBarPattern->SetToolBarItemDialogNode(nullptr);
3457 }
3458 }
3459
FindInCurStack(const RefPtr<FrameNode> & navDestinationNode)3460 bool NavigationPattern::FindInCurStack(const RefPtr<FrameNode>& navDestinationNode)
3461 {
3462 const auto& navdestinationNodes = GetAllNavDestinationNodes();
3463 for (auto navdestination : navdestinationNodes) {
3464 if (navDestinationNode == NavigationGroupNode::GetNavDestinationNode(navdestination.second)) {
3465 return true;
3466 }
3467 }
3468 return false;
3469 }
3470
SetMouseStyle(MouseFormat format)3471 void NavigationPattern::SetMouseStyle(MouseFormat format)
3472 {
3473 auto host = GetHost();
3474 CHECK_NULL_VOID(host);
3475 auto pipeline = host->GetContextWithCheck();
3476 CHECK_NULL_VOID(pipeline);
3477 auto frameNodeId = host->GetId();
3478 int32_t windowId = static_cast<int32_t>(pipeline->GetFocusWindowId());
3479 #ifdef WINDOW_SCENE_SUPPORTED
3480 windowId = static_cast<int32_t>(WindowSceneHelper::GetFocusSystemWindowId(host));
3481 #endif
3482 pipeline->SetMouseStyleHoldNode(frameNodeId);
3483 pipeline->ChangeMouseStyle(frameNodeId, format, windowId);
3484 pipeline->FreeMouseStyleHoldNode(frameNodeId);
3485 }
3486
OnAvoidInfoChange(const ContainerModalAvoidInfo & info)3487 void NavigationPattern::OnAvoidInfoChange(const ContainerModalAvoidInfo& info)
3488 {
3489 if (!isFullPageNavigation_) {
3490 return;
3491 }
3492 MarkAllNavDestinationDirtyIfNeeded(GetHost(), true);
3493 }
3494
RegisterAvoidInfoChangeListener(const RefPtr<FrameNode> & hostNode)3495 void NavigationPattern::RegisterAvoidInfoChangeListener(const RefPtr<FrameNode>& hostNode)
3496 {
3497 CHECK_NULL_VOID(hostNode);
3498 auto pipeline = hostNode->GetContext();
3499 CHECK_NULL_VOID(pipeline);
3500 auto mgr = pipeline->GetAvoidInfoManager();
3501 CHECK_NULL_VOID(mgr);
3502 mgr->AddAvoidInfoListener(WeakClaim(this));
3503 }
3504
UnregisterAvoidInfoChangeListener(const RefPtr<FrameNode> & hostNode)3505 void NavigationPattern::UnregisterAvoidInfoChangeListener(const RefPtr<FrameNode>& hostNode)
3506 {
3507 CHECK_NULL_VOID(hostNode);
3508 auto pipeline = hostNode->GetContext();
3509 CHECK_NULL_VOID(pipeline);
3510 auto mgr = pipeline->GetAvoidInfoManager();
3511 CHECK_NULL_VOID(mgr);
3512 mgr->RemoveAvoidInfoListener(WeakClaim(this));
3513 }
3514
MarkAllNavDestinationDirtyIfNeeded(const RefPtr<FrameNode> & hostNode,bool skipCheck)3515 void NavigationPattern::MarkAllNavDestinationDirtyIfNeeded(const RefPtr<FrameNode>& hostNode, bool skipCheck)
3516 {
3517 auto groupNode = AceType::DynamicCast<NavigationGroupNode>(hostNode);
3518 CHECK_NULL_VOID(groupNode);
3519 if (!skipCheck) {
3520 auto pipeline = groupNode->GetContext();
3521 CHECK_NULL_VOID(pipeline);
3522 auto avoidInfoMgr = pipeline->GetAvoidInfoManager();
3523 CHECK_NULL_VOID(avoidInfoMgr);
3524 if (!avoidInfoMgr->NeedAvoidContainerModal()) {
3525 return;
3526 }
3527 }
3528
3529 auto contentNode = AceType::DynamicCast<FrameNode>(groupNode->GetContentNode());
3530 CHECK_NULL_VOID(contentNode);
3531 auto& childrens = contentNode->GetChildren();
3532 for (auto& child : childrens) {
3533 auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(child);
3534 if (!navDestination) {
3535 continue;
3536 }
3537 if (!navDestination->IsVisible()) {
3538 navDestination->SetNeedForceMeasure(true);
3539 continue;
3540 }
3541 navDestination->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
3542 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navDestination->GetTitleBarNode());
3543 if (titleBarNode) {
3544 titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3545 }
3546 }
3547 }
3548
FireNavigationLifecycle(const RefPtr<UINode> & uiNode,NavDestinationLifecycle lifecycle,NavDestinationActiveReason reason)3549 void NavigationPattern::FireNavigationLifecycle(const RefPtr<UINode>& uiNode, NavDestinationLifecycle lifecycle,
3550 NavDestinationActiveReason reason)
3551 {
3552 auto frameNode = AceType::DynamicCast<FrameNode>(uiNode);
3553 CHECK_NULL_VOID(frameNode);
3554 auto context = frameNode->GetContextRefPtr();
3555 CHECK_NULL_VOID(context);
3556 auto navigationManager = context->GetNavigationManager();
3557 CHECK_NULL_VOID(navigationManager);
3558 auto navigationIds = navigationManager->FindNavigationInTargetParent(frameNode->GetId());
3559 for (auto navigationId: navigationIds) {
3560 auto navigation = AceType::DynamicCast<NavigationGroupNode>(
3561 FrameNode::GetFrameNode(V2::NAVIGATION_VIEW_ETS_TAG, navigationId));
3562 if (!navigation) {
3563 continue;
3564 }
3565 auto pattern = navigation->GetPattern<NavigationPattern>();
3566 if (!pattern) {
3567 continue;
3568 }
3569 auto navigationStack = pattern->GetNavigationStack();
3570 if (navigationStack) {
3571 pattern->NotifyDestinationLifecycle(AceType::DynamicCast<NavDestinationGroupNode>(
3572 NavigationGroupNode::GetNavDestinationNode(navigationStack->Get())), lifecycle, reason);
3573 }
3574 }
3575 }
3576
GenerateLastStandardPage(NavPathList & navPathList)3577 void NavigationPattern::GenerateLastStandardPage(NavPathList& navPathList)
3578 {
3579 int64_t lastPageIndex = navPathList.size() - 1;
3580 // if top page is nullptr or is dialog node, we need to generate node util standard page is found.
3581 while (lastPageIndex >= 0 &&
3582 (navPathList[lastPageIndex].second == nullptr || !IsStandardPage(navPathList[lastPageIndex].second))) {
3583 auto pageNode = navPathList[lastPageIndex].second;
3584 // existed dialog node is no need to generate
3585 bool isExistedNode = (pageNode != nullptr);
3586 if (!pageNode && !GenerateUINodeByIndex(lastPageIndex, pageNode)) {
3587 std::string replacedName;
3588 int32_t replacedIndex = -1;
3589 if (navigationStack_->CheckIsReplacedDestination(lastPageIndex, replacedName, replacedIndex)) {
3590 navigationStack_->SetRecoveryFromReplaceDestination(lastPageIndex, false);
3591 continue;
3592 }
3593 navPathList.erase(navPathList.begin() + lastPageIndex);
3594 lastPageIndex--;
3595 continue;
3596 }
3597 navPathList[lastPageIndex].second = pageNode;
3598 auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(
3599 NavigationGroupNode::GetNavDestinationNode(pageNode));
3600 if (!isExistedNode && navDestinationNode && navigationStack_->GetIsForceSet(lastPageIndex)) {
3601 navigationStack_->ResetIsForceSetFlag(lastPageIndex);
3602 }
3603 if (navDestinationNode && navDestinationNode->GetNavDestinationMode() == NavDestinationMode::STANDARD) {
3604 break;
3605 }
3606 lastPageIndex--;
3607 }
3608 }
3609
IsStandardPage(const RefPtr<UINode> & uiNode) const3610 bool NavigationPattern::IsStandardPage(const RefPtr<UINode>& uiNode) const
3611 {
3612 auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(
3613 NavigationGroupNode::GetNavDestinationNode(uiNode));
3614 CHECK_NULL_RETURN(navDestinationNode, false);
3615 return navDestinationNode->GetNavDestinationMode() == NavDestinationMode::STANDARD;
3616 }
3617
FindNavDestinationNodeInPreList(const uint64_t navDestinationId) const3618 RefPtr<UINode> NavigationPattern::FindNavDestinationNodeInPreList(const uint64_t navDestinationId) const
3619 {
3620 CHECK_NULL_RETURN(navigationStack_, nullptr);
3621 auto preNavDestinationList = navigationStack_->GetAllNavDestinationNodesPrev();
3622 for (auto preNavDestinationInfo : preNavDestinationList) {
3623 auto preNavDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(
3624 NavigationGroupNode::GetNavDestinationNode(preNavDestinationInfo.second.Upgrade()));
3625 CHECK_NULL_CONTINUE(preNavDestinationNode);
3626 auto pattern = preNavDestinationNode->GetPattern<NavDestinationPattern>();
3627 CHECK_NULL_CONTINUE(pattern);
3628 auto preId = pattern->GetNavDestinationId();
3629 if (preId == navDestinationId) {
3630 return preNavDestinationInfo.second.Upgrade();
3631 }
3632 }
3633 return nullptr;
3634 }
3635
FireOnNewParam(const RefPtr<UINode> & uiNode)3636 void NavigationPattern::FireOnNewParam(const RefPtr<UINode>& uiNode)
3637 {
3638 CHECK_NULL_VOID(uiNode);
3639 auto navDestination = DynamicCast<NavDestinationGroupNode>(NavigationGroupNode::GetNavDestinationNode(uiNode));
3640 CHECK_NULL_VOID(navDestination);
3641 auto navDestinationPattern = navDestination->GetPattern<NavDestinationPattern>();
3642 CHECK_NULL_VOID(navDestinationPattern);
3643 auto navPathInfo = navDestinationPattern->GetNavPathInfo();
3644 CHECK_NULL_VOID(navPathInfo);
3645 auto eventHub = navDestination->GetEventHub<NavDestinationEventHub>();
3646 CHECK_NULL_VOID(eventHub);
3647 eventHub->FireOnNewParam(navPathInfo->GetParamObj());
3648 }
3649
ClearRecoveryList()3650 void NavigationPattern::ClearRecoveryList()
3651 {
3652 if (!isFinishInteractiveAnimation_) {
3653 return;
3654 }
3655 CHECK_NULL_VOID(navigationStack_);
3656 navigationStack_->ClearRecoveryList();
3657 }
3658 } // namespace OHOS::Ace::NG
3659