• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/stage/page_pattern.h"
17 
18 #include "base/log/jank_frame_report.h"
19 #include "base/perfmonitor/perf_constants.h"
20 #include "base/perfmonitor/perf_monitor.h"
21 #include "core/components_ng/base/observer_handler.h"
22 #include "bridge/common/utils/engine_helper.h"
23 #include "bridge/declarative_frontend/ng/entry_page_info.h"
24 
25 namespace OHOS::Ace::NG {
26 
27 namespace {
28 constexpr int32_t INVALID_PAGE_INDEX = -1;
29 const int32_t MASK_DURATION = 350;
30 constexpr int32_t DEFAULT_ANIMATION_DURATION = 450;
31 std::string KEY_PAGE_TRANSITION_PROPERTY = "pageTransitionProperty";
32 constexpr float REMOVE_CLIP_SIZE = 10000.0f;
33 constexpr double HALF = 0.5;
34 constexpr double PARENT_PAGE_OFFSET = 0.2;
35 constexpr int32_t RELEASE_JSCHILD_DELAY_TIME = 50;
36 const Color MASK_COLOR = Color::FromARGB(25, 0, 0, 0);
37 const Color DEFAULT_MASK_COLOR = Color::FromARGB(0, 0, 0, 0);
38 
IterativeAddToSharedMap(const RefPtr<UINode> & node,SharedTransitionMap & map)39 void IterativeAddToSharedMap(const RefPtr<UINode>& node, SharedTransitionMap& map)
40 {
41     const auto& children = node->GetChildren();
42     for (const auto& child : children) {
43         auto frameChild = AceType::DynamicCast<FrameNode>(child);
44         if (!frameChild) {
45             IterativeAddToSharedMap(child, map);
46             continue;
47         }
48         auto id = frameChild->GetRenderContext()->GetShareId();
49         if (!id.empty()) {
50             map[id] = frameChild;
51         }
52         IterativeAddToSharedMap(frameChild, map);
53     }
54 }
55 } // namespace
56 
OnAttachToFrameNode()57 void PagePattern::OnAttachToFrameNode()
58 {
59     auto host = GetHost();
60     CHECK_NULL_VOID(host);
61     MeasureType measureType = MeasureType::MATCH_PARENT;
62     auto container = Container::Current();
63     if (container && container->IsDynamicRender()) {
64         measureType = MeasureType::MATCH_CONTENT;
65     }
66     host->GetLayoutProperty()->UpdateMeasureType(measureType);
67     host->GetLayoutProperty()->UpdateAlignment(Alignment::TOP_LEFT);
68     auto pipelineContext = host->GetContext();
69     CHECK_NULL_VOID(pipelineContext);
70     pipelineContext->AddWindowSizeChangeCallback(host->GetId());
71     pipelineContext->GetMemoryManager()->AddRecyclePageNode(host);
72 }
73 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & wrapper,const DirtySwapConfig &)74 bool PagePattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& wrapper, const DirtySwapConfig& /* config */)
75 {
76     if (isFirstLoad_) {
77         isFirstLoad_ = false;
78         if (firstBuildCallback_) {
79             firstBuildCallback_();
80             firstBuildCallback_ = nullptr;
81         }
82     }
83     return false;
84 }
85 
BeforeSyncGeometryProperties(const DirtySwapConfig & config)86 void PagePattern::BeforeSyncGeometryProperties(const DirtySwapConfig& config)
87 {
88     if (config.skipLayout || config.skipMeasure) {
89         return;
90     }
91     CHECK_NULL_VOID(dynamicPageSizeCallback_);
92     auto host = GetHost();
93     CHECK_NULL_VOID(host);
94     auto node = host->GetGeometryNode();
95     CHECK_NULL_VOID(node);
96     dynamicPageSizeCallback_(node->GetFrameSize());
97 }
98 
TriggerPageTransition(const std::function<void ()> & onFinish,PageTransitionType type)99 void PagePattern::TriggerPageTransition(const std::function<void()>& onFinish, PageTransitionType type)
100 {
101     auto host = GetHost();
102     CHECK_NULL_VOID(host);
103     if (pageTransitionFunc_) {
104         pageTransitionFunc_();
105     }
106     pageTransitionFinish_ = std::make_shared<std::function<void()>>(onFinish);
107     auto wrappedOnFinish = [weak = WeakClaim(this), sharedFinish = pageTransitionFinish_, type]() {
108         auto pattern = weak.Upgrade();
109         CHECK_NULL_VOID(pattern);
110         if (type == PageTransitionType::ENTER_PUSH || type == PageTransitionType::ENTER_POP) {
111             ACE_SCOPED_TRACE_COMMERCIAL("Router Page Transition End");
112             PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH, true);
113         }
114         auto host = pattern->GetHost();
115         CHECK_NULL_VOID(host);
116         if (sharedFinish == pattern->pageTransitionFinish_) {
117             // ensure this is exactly the finish callback saved in pagePattern,
118             // otherwise means new pageTransition started
119             pattern->FirePageTransitionFinish();
120             host->DeleteAnimatablePropertyFloat(KEY_PAGE_TRANSITION_PROPERTY);
121         }
122     };
123     auto effect = FindPageTransitionEffect(type);
124     if (effect && effect->GetUserCallback()) {
125         AnimationUtils::StopAnimation(currCustomAnimation_);
126         host->DeleteAnimatablePropertyFloat(KEY_PAGE_TRANSITION_PROPERTY);
127         RouteType routeType = (type == PageTransitionType::ENTER_POP || type == PageTransitionType::EXIT_POP)
128                                   ? RouteType::POP
129                                   : RouteType::PUSH;
130         host->CreateAnimatablePropertyFloat(KEY_PAGE_TRANSITION_PROPERTY, 0.0f,
131             [routeType, handler = effect->GetUserCallback()](const float& progress) { handler(routeType, progress); });
132         auto handler = effect->GetUserCallback();
133         handler(routeType, 0.0f);
134         AnimationOption option(effect->GetCurve(), effect->GetDuration());
135         option.SetDelay(effect->GetDelay());
136         option.SetOnFinishEvent(wrappedOnFinish);
137         currCustomAnimation_ = AnimationUtils::StartAnimation(option, [weakPage = WeakPtr<FrameNode>(host)]() {
138             auto pageNode = weakPage.Upgrade();
139             CHECK_NULL_VOID(pageNode);
140             pageNode->UpdateAnimatablePropertyFloat(KEY_PAGE_TRANSITION_PROPERTY, 1.0f);
141         }, option.GetOnFinishEvent());
142         TriggerDefaultTransition(nullptr, type);
143         return;
144     }
145     TriggerDefaultTransition(wrappedOnFinish, type);
146 }
147 
ProcessAutoSave(const std::function<void ()> & onFinish,const std::function<void ()> & onUIExtNodeBindingCompleted)148 bool PagePattern::ProcessAutoSave(const std::function<void()>& onFinish,
149     const std::function<void()>& onUIExtNodeBindingCompleted)
150 {
151     auto host = GetHost();
152     CHECK_NULL_RETURN(host, false);
153     if (!host->NeedRequestAutoSave()) {
154         return false;
155     }
156     auto container = Container::Current();
157     CHECK_NULL_RETURN(container, false);
158     return container->RequestAutoSave(host, onFinish, onUIExtNodeBindingCompleted);
159 }
160 
ProcessHideState()161 void PagePattern::ProcessHideState()
162 {
163     auto host = GetHost();
164     CHECK_NULL_VOID(host);
165     host->SetActive(false);
166     host->NotifyVisibleChange(VisibleType::VISIBLE, VisibleType::INVISIBLE);
167     host->GetLayoutProperty()->UpdateVisibility(VisibleType::INVISIBLE);
168     auto parent = host->GetAncestorNodeOfFrame(false);
169     CHECK_NULL_VOID(parent);
170     parent->MarkNeedSyncRenderTree();
171     parent->RebuildRenderContextTree();
172 }
173 
ProcessShowState()174 void PagePattern::ProcessShowState()
175 {
176     auto host = GetHost();
177     CHECK_NULL_VOID(host);
178     host->SetActive(true);
179     host->NotifyVisibleChange(VisibleType::INVISIBLE, VisibleType::VISIBLE);
180     host->GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE);
181     auto parent = host->GetAncestorNodeOfFrame(false);
182     CHECK_NULL_VOID(parent);
183     auto context = NG::PipelineContext::GetCurrentContext();
184     CHECK_NULL_VOID(context);
185     auto manager = context->GetSafeAreaManager();
186     if (manager) {
187         auto safeArea = manager->GetSafeArea();
188         auto parentGlobalOffset = host->GetParentGlobalOffsetDuringLayout();
189         auto frame = host->GetPaintRectWithTransform() + parentGlobalOffset;
190         // if page's frameRect not fit current safeArea, need layout page again
191         if (!NearEqual(frame.GetY(), safeArea.top_.end)) {
192             host->MarkDirtyNode(manager->KeyboardSafeAreaEnabled() ? PROPERTY_UPDATE_LAYOUT : PROPERTY_UPDATE_MEASURE);
193         }
194         if (!NearEqual(frame.GetY() + frame.Height(), safeArea.bottom_.start)) {
195             host->MarkDirtyNode(manager->KeyboardSafeAreaEnabled() ? PROPERTY_UPDATE_LAYOUT : PROPERTY_UPDATE_MEASURE);
196         }
197     }
198     parent->MarkNeedSyncRenderTree();
199     parent->RebuildRenderContextTree();
200 }
201 
OnAttachToMainTree()202 void PagePattern::OnAttachToMainTree()
203 {
204 #if defined(ENABLE_SPLIT_MODE)
205     if (!needFireObserver_) {
206         return;
207     }
208 #endif
209     int32_t index = INVALID_PAGE_INDEX;
210     auto delegate = EngineHelper::GetCurrentDelegate();
211     if (delegate) {
212         index = delegate->GetCurrentPageIndex();
213         GetPageInfo()->SetPageIndex(index);
214     }
215     state_ = RouterPageState::ABOUT_TO_APPEAR;
216     UIObserverHandler::GetInstance().NotifyRouterPageStateChange(GetPageInfo(), state_);
217 }
218 
OnDetachFromMainTree()219 void PagePattern::OnDetachFromMainTree()
220 {
221 #if defined(ENABLE_SPLIT_MODE)
222     if (!needFireObserver_) {
223         return;
224     }
225 #endif
226     state_ = RouterPageState::ABOUT_TO_DISAPPEAR;
227     UIObserverHandler::GetInstance().NotifyRouterPageStateChange(GetPageInfo(), state_);
228 }
229 
OnDetachFromFrameNode(FrameNode * frameNode)230 void PagePattern::OnDetachFromFrameNode(FrameNode* frameNode)
231 {
232     CHECK_NULL_VOID(frameNode);
233     auto pipelineContext = frameNode->GetContext();
234     CHECK_NULL_VOID(pipelineContext);
235     pipelineContext->RemoveWindowSizeChangeCallback(frameNode->GetId());
236     pipelineContext->GetMemoryManager()->RemoveRecyclePageNode(frameNode->GetId());
237 }
238 
OnWindowSizeChanged(int32_t,int32_t,WindowSizeChangeReason)239 void PagePattern::OnWindowSizeChanged(int32_t /*width*/, int32_t /*height*/, WindowSizeChangeReason /*type*/)
240 {
241     if (!isPageInTransition_) {
242         return;
243     }
244     auto page = GetHost();
245     CHECK_NULL_VOID(page);
246     auto renderContext = page->GetRenderContext();
247     CHECK_NULL_VOID(renderContext);
248     renderContext->RemoveClipWithRRect();
249 }
250 
OnShow(bool isFromWindow)251 void PagePattern::OnShow(bool isFromWindow)
252 {
253     // Do not invoke onPageShow unless the initialRender function has been executed.
254     CHECK_NULL_VOID(isRenderDone_);
255     CHECK_NULL_VOID(!isOnShow_);
256     auto context = NG::PipelineContext::GetCurrentContext();
257     CHECK_NULL_VOID(context);
258     auto container = Container::Current();
259     if (!container || !container->WindowIsShow()) {
260         LOGW("no need to trigger onPageShow callback when not in the foreground");
261         return;
262     }
263     NotifyPerfMonitorPageMsg(pageInfo_->GetFullPath(), container->GetBundleName());
264     if (pageInfo_) {
265         context->FirePageChanged(pageInfo_->GetPageId(), true);
266         NotifyNavigationLifecycle(true, isFromWindow);
267     }
268     UpdatePageParam();
269     isOnShow_ = true;
270 #if defined(ENABLE_SPLIT_MODE)
271     if (needFireObserver_) {
272         state_ = RouterPageState::ON_PAGE_SHOW;
273         UIObserverHandler::GetInstance().NotifyRouterPageStateChange(GetPageInfo(), state_);
274     }
275 #else
276     state_ = RouterPageState::ON_PAGE_SHOW;
277     UIObserverHandler::GetInstance().NotifyRouterPageStateChange(GetPageInfo(), state_);
278 #endif
279     JankFrameReport::GetInstance().StartRecord(pageInfo_->GetFullPath());
280     auto pageUrlChecker = container->GetPageUrlChecker();
281     if (pageUrlChecker != nullptr) {
282         pageUrlChecker->NotifyPageShow(pageInfo_->GetPageUrl());
283     }
284     if (visibilityChangeCallback_) {
285         visibilityChangeCallback_(true);
286     }
287     if (onPageShow_) {
288         onPageShow_();
289     }
290     if (!onHiddenChange_.empty()) {
291         FireOnHiddenChange(true);
292     }
293     RecordPageEvent(true);
294 }
295 
RecordPageEvent(bool isShow)296 void PagePattern::RecordPageEvent(bool isShow)
297 {
298     if (!Recorder::EventRecorder::Get().IsPageRecordEnable()) {
299         return;
300     }
301     auto entryPageInfo = DynamicCast<EntryPageInfo>(pageInfo_);
302     if (isShow) {
303         std::string param;
304         if (entryPageInfo) {
305             param = Recorder::EventRecorder::Get().IsPageParamRecordEnable() ? entryPageInfo->GetPageParams() : "";
306             entryPageInfo->SetShowTime(GetCurrentTimestamp());
307         }
308         Recorder::EventRecorder::Get().OnPageShow(
309             pageInfo_->GetPageUrl(), param, pageInfo_->GetRouteName().value_or(""));
310     } else {
311         int64_t duration = 0;
312         if (entryPageInfo && entryPageInfo->GetShowTime() > 0) {
313             duration = GetCurrentTimestamp() - entryPageInfo->GetShowTime();
314         }
315         Recorder::EventRecorder::Get().OnPageHide(
316             pageInfo_->GetPageUrl(), duration, pageInfo_->GetRouteName().value_or(""));
317     }
318 }
319 
OnHide(bool isFromWindow)320 void PagePattern::OnHide(bool isFromWindow)
321 {
322     CHECK_NULL_VOID(isOnShow_);
323     JankFrameReport::GetInstance().FlushRecord();
324     auto context = NG::PipelineContext::GetCurrentContext();
325     CHECK_NULL_VOID(context);
326     auto host = GetHost();
327     CHECK_NULL_VOID(host);
328     if (pageInfo_) {
329         NotifyNavigationLifecycle(false, isFromWindow);
330         context->FirePageChanged(pageInfo_->GetPageId(), false);
331     }
332     host->SetJSViewActive(false);
333     isOnShow_ = false;
334     host->SetAccessibilityVisible(false);
335 #if defined(ENABLE_SPLIT_MODE)
336     if (needFireObserver_) {
337         state_ = RouterPageState::ON_PAGE_HIDE;
338         UIObserverHandler::GetInstance().NotifyRouterPageStateChange(GetPageInfo(), state_);
339     }
340 #else
341     state_ = RouterPageState::ON_PAGE_HIDE;
342     UIObserverHandler::GetInstance().NotifyRouterPageStateChange(GetPageInfo(), state_);
343 #endif
344     auto container = Container::Current();
345     if (container) {
346         auto pageUrlChecker = container->GetPageUrlChecker();
347         // ArkTSCard container no SetPageUrlChecker
348         if (pageUrlChecker != nullptr) {
349             pageUrlChecker->NotifyPageHide(pageInfo_->GetPageUrl());
350         }
351     }
352     if (visibilityChangeCallback_) {
353         visibilityChangeCallback_(false);
354     }
355     if (onPageHide_) {
356         onPageHide_();
357     }
358     if (!onHiddenChange_.empty()) {
359         FireOnHiddenChange(false);
360     }
361     RecordPageEvent(false);
362 }
363 
OnBackPressed()364 bool PagePattern::OnBackPressed()
365 {
366     if (RemoveOverlay()) {
367         TAG_LOGI(AceLogTag::ACE_OVERLAY, "page removes it's overlay when on backpressed");
368         return true;
369     }
370     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN) && isPageInTransition_) {
371         TAG_LOGI(AceLogTag::ACE_ROUTER, "page is in transition");
372         return true;
373     }
374     // if in page transition, do not set to ON_BACK_PRESS
375 #if defined(ENABLE_SPLIT_MODE)
376     if (needFireObserver_) {
377         state_ = RouterPageState::ON_BACK_PRESS;
378         UIObserverHandler::GetInstance().NotifyRouterPageStateChange(GetPageInfo(), state_);
379     }
380 #else
381     state_ = RouterPageState::ON_BACK_PRESS;
382     UIObserverHandler::GetInstance().NotifyRouterPageStateChange(GetPageInfo(), state_);
383 #endif
384     if (onBackPressed_) {
385         bool result = onBackPressed_();
386         CheckIsNeedForceExitWindow(result);
387         return result;
388     }
389     return false;
390 }
391 
BuildSharedTransitionMap()392 void PagePattern::BuildSharedTransitionMap()
393 {
394     auto host = GetHost();
395     CHECK_NULL_VOID(host);
396     sharedTransitionMap_.clear();
397     IterativeAddToSharedMap(host, sharedTransitionMap_);
398 }
399 
CheckIsNeedForceExitWindow(bool result)400 void PagePattern::CheckIsNeedForceExitWindow(bool result)
401 {
402     auto host = GetHost();
403     CHECK_NULL_VOID(host);
404     auto context = host->GetContext();
405     CHECK_NULL_VOID(context);
406     if (!context->GetInstallationFree() || !result) {
407         // if is not atommic service and result is false, don't process.
408         return;
409     }
410     auto stageManager = context->GetStageManager();
411     CHECK_NULL_VOID(stageManager);
412     int32_t pageSize =
413         stageManager->GetStageNode() ? static_cast<int32_t>(stageManager->GetStageNode()->GetChildren().size()) : 0;
414     if (pageSize != 1) {
415         return;
416     }
417     auto container = Container::Current();
418     CHECK_NULL_VOID(container);
419     if (container->IsUIExtensionWindow()) {
420         container->TerminateUIExtension();
421     } else {
422         auto windowManager = context->GetWindowManager();
423         CHECK_NULL_VOID(windowManager);
424         windowManager->WindowPerformBack();
425     }
426     TAG_LOGI(AceLogTag::ACE_ROUTER, "page onbackpress intercepted, exit window.");
427 }
428 
ReloadPage()429 void PagePattern::ReloadPage()
430 {
431     auto host = GetHost();
432     CHECK_NULL_VOID(host);
433     auto customNode = DynamicCast<CustomNodeBase>(host->GetFirstChild());
434     CHECK_NULL_VOID(customNode);
435     customNode->FireReloadFunction(true);
436 }
437 
FindPageTransitionEffect(PageTransitionType type)438 RefPtr<PageTransitionEffect> PagePattern::FindPageTransitionEffect(PageTransitionType type)
439 {
440     RefPtr<PageTransitionEffect> result;
441     for (auto iter = pageTransitionEffects_.rbegin(); iter != pageTransitionEffects_.rend(); ++iter) {
442         auto effect = *iter;
443         if (effect->CanFit(type)) {
444             result = effect;
445             break;
446         }
447     }
448     return result;
449 }
450 
ClearPageTransitionEffect()451 void PagePattern::ClearPageTransitionEffect()
452 {
453     pageTransitionEffects_.clear();
454 }
455 
GetTopTransition() const456 RefPtr<PageTransitionEffect> PagePattern::GetTopTransition() const
457 {
458     return pageTransitionEffects_.empty() ? nullptr : pageTransitionEffects_.back();
459 }
460 
AddPageTransition(const RefPtr<PageTransitionEffect> & effect)461 void PagePattern::AddPageTransition(const RefPtr<PageTransitionEffect>& effect)
462 {
463     pageTransitionEffects_.emplace_back(effect);
464 }
465 
AddJsAnimator(const std::string & animatorId,const RefPtr<Framework::AnimatorInfo> & animatorInfo)466 void PagePattern::AddJsAnimator(const std::string& animatorId, const RefPtr<Framework::AnimatorInfo>& animatorInfo)
467 {
468     CHECK_NULL_VOID(animatorInfo);
469     auto animator = animatorInfo->GetAnimator();
470     CHECK_NULL_VOID(animator);
471     animator->AttachScheduler(PipelineContext::GetCurrentContext());
472     jsAnimatorMap_[animatorId] = animatorInfo;
473 }
474 
GetJsAnimator(const std::string & animatorId)475 RefPtr<Framework::AnimatorInfo> PagePattern::GetJsAnimator(const std::string& animatorId)
476 {
477     auto iter = jsAnimatorMap_.find(animatorId);
478     if (iter != jsAnimatorMap_.end()) {
479         return iter->second;
480     }
481     return nullptr;
482 }
483 
SetFirstBuildCallback(std::function<void ()> && buildCallback)484 void PagePattern::SetFirstBuildCallback(std::function<void()>&& buildCallback)
485 {
486     if (isFirstLoad_) {
487         firstBuildCallback_ = std::move(buildCallback);
488     } else if (buildCallback) {
489         buildCallback();
490     }
491 }
492 
FirePageTransitionFinish()493 void PagePattern::FirePageTransitionFinish()
494 {
495     if (pageTransitionFinish_) {
496         auto onFinish = *pageTransitionFinish_;
497         pageTransitionFinish_ = nullptr;
498         if (onFinish) {
499             onFinish();
500         }
501     }
502 }
503 
StopPageTransition()504 void PagePattern::StopPageTransition()
505 {
506     auto host = GetHost();
507     CHECK_NULL_VOID(host);
508     auto property = host->GetAnimatablePropertyFloat(KEY_PAGE_TRANSITION_PROPERTY);
509     if (property) {
510         FirePageTransitionFinish();
511         return;
512     }
513     AnimationOption option(Curves::LINEAR, 0);
514     AnimationUtils::Animate(
515         option, [host]() { host->UpdateAnimatablePropertyFloat(KEY_PAGE_TRANSITION_PROPERTY, 0.0f); });
516     host->DeleteAnimatablePropertyFloat(KEY_PAGE_TRANSITION_PROPERTY);
517     FirePageTransitionFinish();
518 }
519 
BeforeCreateLayoutWrapper()520 void PagePattern::BeforeCreateLayoutWrapper()
521 {
522     auto pipeline = PipelineContext::GetCurrentContext();
523     CHECK_NULL_VOID(pipeline);
524     // SafeArea already applied to AppBar (AtomicServicePattern)
525     if (pipeline->GetInstallationFree()) {
526         auto host = GetHost();
527         CHECK_NULL_VOID(host);
528         ACE_SCOPED_TRACE("[%s][self:%d] SafeArea already applied to AppBar", host->GetTag().c_str(), host->GetId());
529         return;
530     }
531     ContentRootPattern::BeforeCreateLayoutWrapper();
532     auto host = GetHost();
533     CHECK_NULL_VOID(host);
534     auto&& insets = host->GetLayoutProperty()->GetSafeAreaInsets();
535     CHECK_NULL_VOID(insets);
536     auto manager = pipeline->GetSafeAreaManager();
537     CHECK_NULL_VOID(manager);
538 }
539 
AvoidKeyboard() const540 bool PagePattern::AvoidKeyboard() const
541 {
542     auto pipeline = PipelineContext::GetCurrentContext();
543     CHECK_NULL_RETURN(pipeline, false);
544     auto safeAreaManager = pipeline->GetSafeAreaManager();
545     CHECK_NULL_RETURN(safeAreaManager, false);
546     return safeAreaManager->KeyboardSafeAreaEnabled();
547 }
548 
RemoveOverlay()549 bool PagePattern::RemoveOverlay()
550 {
551     CHECK_NULL_RETURN(overlayManager_, false);
552     if (overlayManager_->IsCurrentNodeProcessRemoveOverlay(GetHost(), false)) {
553         auto pipeline = PipelineContext::GetCurrentContext();
554         CHECK_NULL_RETURN(pipeline, false);
555         auto taskExecutor = pipeline->GetTaskExecutor();
556         CHECK_NULL_RETURN(taskExecutor, false);
557         return overlayManager_->RemoveOverlay(true);
558     }
559     return false;
560 }
561 
IsNeedCallbackBackPressed()562 bool PagePattern::IsNeedCallbackBackPressed()
563 {
564     CHECK_NULL_RETURN(overlayManager_, false);
565     return overlayManager_->IsCurrentNodeProcessRemoveOverlay(GetHost(), true);
566 }
567 
NotifyPerfMonitorPageMsg(const std::string & pageUrl,const std::string & bundleName)568 void PagePattern::NotifyPerfMonitorPageMsg(const std::string& pageUrl, const std::string& bundleName)
569 {
570     if (PerfMonitor::GetPerfMonitor() != nullptr) {
571         PerfMonitor::GetPerfMonitor()->SetPageUrl(pageUrl);
572         // The page contains only page url but not the page name
573         PerfMonitor::GetPerfMonitor()->SetPageName("");
574         PerfMonitor::GetPerfMonitor()->ReportPageShowMsg(pageUrl, bundleName, "");
575     }
576 }
577 
MarkDirtyOverlay()578 void PagePattern::MarkDirtyOverlay()
579 {
580     CHECK_NULL_VOID(overlayManager_);
581     overlayManager_->MarkDirtyOverlay();
582 }
583 
InitTransitionIn(const RefPtr<PageTransitionEffect> & effect,PageTransitionType type)584 void PagePattern::InitTransitionIn(const RefPtr<PageTransitionEffect>& effect, PageTransitionType type)
585 {
586     CHECK_NULL_VOID(effect);
587     auto hostNode = AceType::DynamicCast<FrameNode>(GetHost());
588     CHECK_NULL_VOID(hostNode);
589     auto renderContext = hostNode->GetRenderContext();
590     CHECK_NULL_VOID(renderContext);
591     const auto& scaleOptions = effect->GetScaleEffect();
592     const auto& translateOptions = effect->GetTranslateEffect();
593     renderContext->UpdateTransformCenter(DimensionOffset(scaleOptions->centerX, scaleOptions->centerY));
594     renderContext->UpdateTransformScale(VectorF(scaleOptions->xScale, scaleOptions->yScale));
595     renderContext->UpdateTransformTranslate(translateOptions.value());
596     renderContext->UpdateOpacity(effect->GetOpacityEffect().value());
597     renderContext->ClipWithRRect(effect->GetPageTransitionRectF().value(), RadiusF(EdgeF(0.0f, 0.0f)));
598 }
599 
InitTransitionOut(const RefPtr<PageTransitionEffect> & effect,PageTransitionType type)600 void PagePattern::InitTransitionOut(const RefPtr<PageTransitionEffect> & effect, PageTransitionType type)
601 {
602     CHECK_NULL_VOID(effect);
603     auto hostNode = AceType::DynamicCast<FrameNode>(GetHost());
604     CHECK_NULL_VOID(hostNode);
605     auto renderContext = hostNode->GetRenderContext();
606     CHECK_NULL_VOID(renderContext);
607     const auto& scaleOptions = effect->GetScaleEffect();
608     renderContext->UpdateTransformCenter(DimensionOffset(scaleOptions->centerX, scaleOptions->centerY));
609     renderContext->UpdateTransformScale(VectorF(1.0f, 1.0f));
610     renderContext->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
611     renderContext->UpdateOpacity(1.0);
612     renderContext->ClipWithRRect(effect->GetDefaultPageTransitionRectF().value(), RadiusF(EdgeF(0.0f, 0.0f)));
613 }
614 
GetDefaultPageTransition(PageTransitionType type)615 RefPtr<PageTransitionEffect> PagePattern::GetDefaultPageTransition(PageTransitionType type)
616 {
617     auto hostNode = GetHost();
618     CHECK_NULL_RETURN(hostNode, nullptr);
619     auto renderContext = hostNode->GetRenderContext();
620     CHECK_NULL_RETURN(renderContext, nullptr);
621     auto resultEffect = AceType::MakeRefPtr<PageTransitionEffect>(type, PageTransitionOption());
622     resultEffect->SetScaleEffect(ScaleOptions(1.0f, 1.0f, 1.0f, 0.5_pct, 0.5_pct));
623     TranslateOptions translate;
624     auto pipelineContext = PipelineContext::GetCurrentContext();
625     CHECK_NULL_RETURN(pipelineContext, nullptr);
626     auto safeAreaInsets = pipelineContext->GetSafeAreaWithoutProcess();
627     auto statusHeight = static_cast<float>(safeAreaInsets.top_.Length());
628     auto rect = renderContext->GetPaintRectWithoutTransform();
629     RectF defaultPageTransitionRectF = RectF(0.0f, -statusHeight, rect.Width(), REMOVE_CLIP_SIZE);
630     resultEffect->SetDefaultPageTransitionRectF(defaultPageTransitionRectF);
631     switch (type) {
632         case PageTransitionType::ENTER_PUSH:
633         case PageTransitionType::EXIT_POP:
634             UpdateEnterPushEffect(resultEffect, statusHeight);
635             break;
636         case PageTransitionType::ENTER_POP:
637             UpdateDefaultEnterPopEffect(resultEffect, statusHeight);
638             break;
639         case PageTransitionType::EXIT_PUSH:
640             UpdateExitPushEffect(resultEffect, statusHeight);
641             break;
642         default:
643             break;
644     }
645     resultEffect->SetOpacityEffect(1);
646     return resultEffect;
647 }
648 
UpdateDefaultEnterPopEffect(RefPtr<PageTransitionEffect> & effect,float statusHeight)649 void PagePattern::UpdateDefaultEnterPopEffect(RefPtr<PageTransitionEffect>& effect, float statusHeight)
650 {
651     CHECK_NULL_VOID(effect);
652     auto hostNode = AceType::DynamicCast<FrameNode>(GetHost());
653     CHECK_NULL_VOID(hostNode);
654     auto renderContext = hostNode->GetRenderContext();
655     CHECK_NULL_VOID(renderContext);
656     auto rect = renderContext->GetPaintRectWithoutTransform();
657     effect->SetInitialBackgroundColor(MASK_COLOR);
658     effect->SetBackgroundColor(DEFAULT_MASK_COLOR);
659     TranslateOptions translate;
660     RectF pageTransitionRectF;
661     if (AceApplicationInfo::GetInstance().IsRightToLeft()) {
662         pageTransitionRectF =
663             RectF(rect.Width() * HALF, -statusHeight, rect.Width() * HALF, REMOVE_CLIP_SIZE);
664         translate.x = Dimension(rect.Width() * HALF);
665     } else {
666         pageTransitionRectF =
667             RectF(0.0f, -statusHeight, rect.Width() * PARENT_PAGE_OFFSET, REMOVE_CLIP_SIZE);
668         translate.x = Dimension(-rect.Width() * PARENT_PAGE_OFFSET);
669     }
670     effect->SetPageTransitionRectF(pageTransitionRectF);
671     effect->SetTranslateEffect(translate);
672 }
673 
UpdateEnterPushEffect(RefPtr<PageTransitionEffect> & effect,float statusHeight)674 void PagePattern::UpdateEnterPushEffect(RefPtr<PageTransitionEffect>& effect, float statusHeight)
675 {
676     CHECK_NULL_VOID(effect);
677     auto hostNode = AceType::DynamicCast<FrameNode>(GetHost());
678     CHECK_NULL_VOID(hostNode);
679     auto renderContext = hostNode->GetRenderContext();
680     CHECK_NULL_VOID(renderContext);
681     auto rect = renderContext->GetPaintRectWithoutTransform();
682     effect->SetInitialBackgroundColor(DEFAULT_MASK_COLOR);
683     effect->SetBackgroundColor(DEFAULT_MASK_COLOR);
684     TranslateOptions translate;
685     RectF pageTransitionRectF;
686     RectF defaultPageTransitionRectF = RectF(0.0f, -statusHeight, rect.Width(), REMOVE_CLIP_SIZE);
687     if (AceApplicationInfo::GetInstance().IsRightToLeft()) {
688         pageTransitionRectF =
689             RectF(0.0f, -statusHeight, rect.Width() * PARENT_PAGE_OFFSET, REMOVE_CLIP_SIZE);
690         translate.x = Dimension(-rect.Width() * PARENT_PAGE_OFFSET);
691     } else {
692         pageTransitionRectF =
693             RectF(rect.Width() * HALF, -statusHeight, rect.Width() * HALF, REMOVE_CLIP_SIZE);
694         defaultPageTransitionRectF = RectF(0.0f, -statusHeight, rect.Width(), REMOVE_CLIP_SIZE);
695         translate.x = Dimension(rect.Width() * HALF);
696     }
697     effect->SetDefaultPageTransitionRectF(defaultPageTransitionRectF);
698     effect->SetPageTransitionRectF(pageTransitionRectF);
699     effect->SetTranslateEffect(translate);
700 }
701 
UpdateExitPushEffect(RefPtr<PageTransitionEffect> & effect,float statusHeight)702 void PagePattern::UpdateExitPushEffect(RefPtr<PageTransitionEffect>& effect, float statusHeight)
703 {
704     CHECK_NULL_VOID(effect);
705     auto hostNode = AceType::DynamicCast<FrameNode>(GetHost());
706     CHECK_NULL_VOID(hostNode);
707     auto renderContext = hostNode->GetRenderContext();
708     CHECK_NULL_VOID(renderContext);
709     auto rect = renderContext->GetPaintRectWithoutTransform();
710     effect->SetInitialBackgroundColor(DEFAULT_MASK_COLOR);
711     effect->SetBackgroundColor(MASK_COLOR);
712     TranslateOptions translate;
713     RectF pageTransitionRectF;
714     if (AceApplicationInfo::GetInstance().IsRightToLeft()) {
715         pageTransitionRectF =
716             RectF(rect.Width() * HALF, -statusHeight, rect.Width() * HALF, REMOVE_CLIP_SIZE);
717         translate.x = Dimension(rect.Width() * HALF);
718     } else {
719         pageTransitionRectF =
720             RectF(0.0f, -statusHeight, rect.Width() * PARENT_PAGE_OFFSET, REMOVE_CLIP_SIZE);
721         translate.x = Dimension(-rect.Width() * PARENT_PAGE_OFFSET);
722     }
723     effect->SetPageTransitionRectF(pageTransitionRectF);
724     effect->SetTranslateEffect(translate);
725 }
726 
TransitionInFinish(const RefPtr<PageTransitionEffect> & effect,PageTransitionType type)727 void PagePattern::TransitionInFinish(const RefPtr<PageTransitionEffect>& effect, PageTransitionType type)
728 {
729     CHECK_NULL_VOID(effect);
730     auto hostNode = AceType::DynamicCast<FrameNode>(GetHost());
731     CHECK_NULL_VOID(hostNode);
732     auto renderContext = hostNode->GetRenderContext();
733     CHECK_NULL_VOID(renderContext);
734     renderContext->UpdateTransformScale(VectorF(1.0f, 1.0f));
735     renderContext->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
736     renderContext->UpdateOpacity(1.0);
737     renderContext->ClipWithRRect(effect->GetDefaultPageTransitionRectF().value(), RadiusF(EdgeF(0.0f, 0.0f)));
738 }
739 
TransitionOutFinish(const RefPtr<PageTransitionEffect> & effect,PageTransitionType type)740 void PagePattern::TransitionOutFinish(const RefPtr<PageTransitionEffect>& effect, PageTransitionType type)
741 {
742     CHECK_NULL_VOID(effect);
743     auto hostNode = AceType::DynamicCast<FrameNode>(GetHost());
744     CHECK_NULL_VOID(hostNode);
745     auto renderContext = hostNode->GetRenderContext();
746     CHECK_NULL_VOID(renderContext);
747     const auto& scaleOptions = effect->GetScaleEffect();
748     const auto& translateOptions = effect->GetTranslateEffect();
749     renderContext->UpdateTransformScale(VectorF(scaleOptions->xScale, scaleOptions->yScale));
750     renderContext->UpdateTransformTranslate(translateOptions.value());
751     renderContext->UpdateOpacity(effect->GetOpacityEffect().value());
752     renderContext->ClipWithRRect(effect->GetPageTransitionRectF().value(), RadiusF(EdgeF(0.0f, 0.0f)));
753 }
754 
MaskAnimation(const Color & initialBackgroundColor,const Color & backgroundColor)755 void PagePattern::MaskAnimation(const Color& initialBackgroundColor, const Color& backgroundColor)
756 {
757     auto hostNode = AceType::DynamicCast<FrameNode>(GetHost());
758     CHECK_NULL_VOID(hostNode);
759     auto renderContext = hostNode->GetRenderContext();
760     CHECK_NULL_VOID(renderContext);
761     AnimationOption maskOption;
762     maskOption.SetCurve(Curves::FRICTION);
763     maskOption.SetDuration(MASK_DURATION);
764     renderContext->SetActualForegroundColor(initialBackgroundColor);
765     AnimationUtils::OpenImplicitAnimation(maskOption, maskOption.GetCurve(), nullptr);
766     renderContext->SetActualForegroundColor(backgroundColor);
767     AnimationUtils::CloseImplicitAnimation();
768 }
769 
GetPageTransitionEffect(const RefPtr<PageTransitionEffect> & transition)770 RefPtr<PageTransitionEffect> PagePattern::GetPageTransitionEffect(const RefPtr<PageTransitionEffect>& transition)
771 {
772     auto hostNode = AceType::DynamicCast<FrameNode>(GetHost());
773     CHECK_NULL_RETURN(hostNode, nullptr);
774     auto renderContext = hostNode->GetRenderContext();
775     CHECK_NULL_RETURN(renderContext, nullptr);
776     auto resultEffect = AceType::MakeRefPtr<PageTransitionEffect>(
777         transition->GetPageTransitionType(), transition->GetPageTransitionOption());
778     resultEffect->SetScaleEffect(
779         transition->GetScaleEffect().value_or(ScaleOptions(1.0f, 1.0f, 1.0f, 0.5_pct, 0.5_pct)));
780     TranslateOptions translate;
781     auto rect = renderContext->GetPaintRectWithoutTransform();
782     auto context = PipelineContext::GetCurrentContext();
783     CHECK_NULL_RETURN(context, nullptr);
784     auto safeAreaInsets = context->GetSafeAreaWithoutProcess();
785     auto statusHeight = static_cast<float>(safeAreaInsets.top_.Length());
786     RectF defaultPageTransitionRectF = RectF(0.0f, -statusHeight, rect.Width(), REMOVE_CLIP_SIZE);
787     // slide and translate, only one can be effective
788     if (transition->GetSlideEffect().has_value()) {
789         SlideTransitionEffect(transition->GetSlideEffect().value(), rect, translate);
790     } else if (transition->GetTranslateEffect().has_value()) {
791         const auto& translateOptions = transition->GetTranslateEffect();
792         translate.x = Dimension(translateOptions->x.ConvertToPxWithSize(rect.Width()));
793         translate.y = Dimension(translateOptions->y.ConvertToPxWithSize(rect.Height()));
794         translate.z = Dimension(translateOptions->z.ConvertToPx());
795     }
796     resultEffect->SetTranslateEffect(translate);
797     resultEffect->SetOpacityEffect(transition->GetOpacityEffect().value_or(1));
798     resultEffect->SetPageTransitionRectF(RectF(0.0f, -statusHeight, rect.Width(), REMOVE_CLIP_SIZE));
799     resultEffect->SetDefaultPageTransitionRectF(defaultPageTransitionRectF);
800     resultEffect->SetInitialBackgroundColor(DEFAULT_MASK_COLOR);
801     resultEffect->SetBackgroundColor(DEFAULT_MASK_COLOR);
802     return resultEffect;
803 }
804 
SlideTransitionEffect(const SlideEffect & effect,const RectF & rect,TranslateOptions & translate)805 void PagePattern::SlideTransitionEffect(const SlideEffect& effect, const RectF& rect, TranslateOptions& translate)
806 {
807     switch (effect) {
808         case SlideEffect::LEFT:
809             translate.x = Dimension(-rect.Width());
810             break;
811         case SlideEffect::RIGHT:
812             translate.x = Dimension(rect.Width());
813             break;
814         case SlideEffect::BOTTOM:
815             translate.y = Dimension(rect.Height());
816             break;
817         case SlideEffect::TOP:
818             translate.y = Dimension(-rect.Height());
819             break;
820         case SlideEffect::START:
821             if (AceApplicationInfo::GetInstance().IsRightToLeft()) {
822                 translate.x = Dimension(rect.Width());
823                 break;
824             }
825             translate.x = Dimension(-rect.Width());
826             break;
827         case SlideEffect::END:
828             if (AceApplicationInfo::GetInstance().IsRightToLeft()) {
829                 translate.x = Dimension(-rect.Width());
830                 break;
831             }
832             translate.x = Dimension(rect.Width());
833             break;
834         default:
835             break;
836     }
837 }
838 
ResetPageTransitionEffect()839 void PagePattern::ResetPageTransitionEffect()
840 {
841     auto hostNode = AceType::DynamicCast<FrameNode>(GetHost());
842     CHECK_NULL_VOID(hostNode);
843     auto renderContext = hostNode->GetRenderContext();
844     CHECK_NULL_VOID(renderContext);
845     renderContext->UpdateTransformTranslate({0.0f, 0.0f, 0.0f});
846     renderContext->RemoveClipWithRRect();
847     MaskAnimation(DEFAULT_MASK_COLOR, DEFAULT_MASK_COLOR);
848 }
849 
RemoveJsChildImmediately(const RefPtr<FrameNode> & page,PageTransitionType transactionType)850 void PagePattern::RemoveJsChildImmediately(const RefPtr<FrameNode>& page, PageTransitionType transactionType)
851 {
852     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
853         return;
854     }
855 
856     if (transactionType != PageTransitionType::EXIT_POP) {
857         return;
858     }
859 
860     auto effect = FindPageTransitionEffect(transactionType);
861     if (effect && effect->GetUserCallback()) {
862         return;
863     }
864 
865     if (page->HasSkipNode()) {
866         return;
867     }
868 
869     auto taskExecutor = Container::CurrentTaskExecutor();
870     CHECK_NULL_VOID(taskExecutor);
871     taskExecutor->PostDelayedTask(
872         [weak = WeakPtr<FrameNode>(page)]() {
873             auto page = weak.Upgrade();
874             CHECK_NULL_VOID(page);
875             page->SetDestroying();
876         }, TaskExecutor::TaskType::UI, RELEASE_JSCHILD_DELAY_TIME, "ArkUIRemoveJsChild");
877 }
878 
FinishOutPage(const int32_t animationId,PageTransitionType type)879 void PagePattern::FinishOutPage(const int32_t animationId, PageTransitionType type)
880 {
881     if (animationId_ != animationId) {
882         TAG_LOGI(AceLogTag::ACE_ROUTER, "animation id is different");
883         return;
884     }
885     auto outPage = AceType::DynamicCast<FrameNode>(GetHost());
886     CHECK_NULL_VOID(outPage);
887     outPage->GetEventHub<EventHub>()->SetEnabled(true);
888     if (type != PageTransitionType::EXIT_PUSH && type != PageTransitionType::EXIT_POP) {
889         TAG_LOGI(AceLogTag::ACE_ROUTER, "current transition type is invalid");
890         return;
891     }
892     TAG_LOGI(AceLogTag::ACE_ROUTER, "%{public}s finish out page transition.", GetPageUrl().c_str());
893     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
894         FocusViewHide();
895     }
896 
897     if (outPage->IsInDestroying()) {
898         outPage->SetDestroying(false, false);
899     }
900     auto context = PipelineContext::GetCurrentContext();
901     CHECK_NULL_VOID(context);
902     if (type == PageTransitionType::EXIT_POP || isNeedRemove_) {
903         auto stageNode = outPage->GetParent();
904         CHECK_NULL_VOID(stageNode);
905         stageNode->RemoveChild(outPage);
906         stageNode->RebuildRenderContextTree();
907         context->RequestFrame();
908         return;
909     }
910     isPageInTransition_ = false;
911     ProcessHideState();
912     context->MarkNeedFlushMouseEvent();
913     auto stageManager = context->GetStageManager();
914     CHECK_NULL_VOID(stageManager);
915     stageManager->SetStageInTrasition(false);
916     ResetPageTransitionEffect();
917 }
918 
FinishInPage(const int32_t animationId,PageTransitionType type)919 void PagePattern::FinishInPage(const int32_t animationId, PageTransitionType type)
920 {
921     if (animationId_ != animationId) {
922         TAG_LOGI(AceLogTag::ACE_ROUTER, "animation id in inPage is invalid");
923         return;
924     }
925     auto inPage = AceType::DynamicCast<FrameNode>(GetHost());
926     CHECK_NULL_VOID(inPage);
927     inPage->GetEventHub<EventHub>()->SetEnabled(true);
928     if (type != PageTransitionType::ENTER_PUSH && type != PageTransitionType::ENTER_POP) {
929         TAG_LOGI(AceLogTag::ACE_ROUTER, "inPage transition type is invalid");
930         return;
931     }
932     TAG_LOGI(AceLogTag::ACE_ROUTER, "%{public}s finish inPage transition.", GetPageUrl().c_str());
933     isPageInTransition_ = false;
934     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
935         FocusViewShow();
936     }
937     auto context = PipelineContext::GetCurrentContext();
938     CHECK_NULL_VOID(context);
939     context->MarkNeedFlushMouseEvent();
940     ResetPageTransitionEffect();
941     auto stageManager = context->GetStageManager();
942     CHECK_NULL_VOID(stageManager);
943     stageManager->SetStageInTrasition(false);
944 }
945 
TriggerDefaultTransition(const std::function<void ()> & onFinish,PageTransitionType type)946 void PagePattern::TriggerDefaultTransition(const std::function<void()>& onFinish, PageTransitionType type)
947 {
948     bool transitionIn = true;
949     if (type == PageTransitionType::ENTER_PUSH || type == PageTransitionType::ENTER_POP) {
950         transitionIn = true;
951     } else if (type == PageTransitionType::EXIT_PUSH || type == PageTransitionType::EXIT_POP) {
952         transitionIn = false;
953     } else {
954         return;
955     }
956     auto transition = FindPageTransitionEffect(type);
957     RefPtr<PageTransitionEffect> effect;
958     AnimationOption option;
959     UpdateAnimationOption(transition, effect, option, type);
960     option.SetOnFinishEvent(onFinish);
961     auto hostNode = AceType::DynamicCast<FrameNode>(GetHost());
962     CHECK_NULL_VOID(hostNode);
963     auto pipelineContext = hostNode->GetContext();
964     CHECK_NULL_VOID(pipelineContext);
965     auto stageManager = pipelineContext->GetStageManager();
966     CHECK_NULL_VOID(stageManager);
967     if (transitionIn) {
968         InitTransitionIn(effect, type);
969         auto animation = AnimationUtils::StartAnimation(option, [weakPattern = WeakClaim(this), effect, type]() {
970             auto pattern = weakPattern.Upgrade();
971             CHECK_NULL_VOID(pattern);
972             pattern->TransitionInFinish(effect, type);
973         }, option.GetOnFinishEvent());
974         stageManager->AddAnimation(animation, type == PageTransitionType::ENTER_PUSH);
975         MaskAnimation(effect->GetInitialBackgroundColor().value(), effect->GetBackgroundColor().value());
976         return;
977     }
978     InitTransitionOut(effect, type);
979     auto animation = AnimationUtils::StartAnimation(option, [weakPattern = WeakClaim(this), effect, type]() {
980         auto pagePattern = weakPattern.Upgrade();
981         CHECK_NULL_VOID(pagePattern);
982         pagePattern->TransitionOutFinish(effect, type);
983     }, option.GetOnFinishEvent());
984     stageManager->AddAnimation(animation, type == PageTransitionType::ENTER_POP);
985     MaskAnimation(effect->GetInitialBackgroundColor().value(), effect->GetBackgroundColor().value());
986 }
987 
UpdateAnimationOption(const RefPtr<PageTransitionEffect> & transition,RefPtr<PageTransitionEffect> & effect,AnimationOption & option,PageTransitionType type)988 void PagePattern::UpdateAnimationOption(const RefPtr<PageTransitionEffect>& transition,
989     RefPtr<PageTransitionEffect>& effect, AnimationOption& option, PageTransitionType type)
990 {
991     if (transition) {
992         effect = GetPageTransitionEffect(transition);
993         option.SetCurve(transition->GetCurve());
994         option.SetDuration(transition->GetDuration());
995         option.SetDelay(transition->GetDelay());
996         return;
997     }
998     effect = GetDefaultPageTransition(type);
999     const RefPtr<InterpolatingSpring> springCurve =
1000         AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 342.0f, 37.0f);
1001     auto host = GetHost();
1002     CHECK_NULL_VOID(host);
1003     auto pipeline = host->GetContext();
1004     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
1005         CHECK_NULL_VOID(pipeline);
1006         auto appTheme = pipeline->GetTheme<AppTheme>();
1007         CHECK_NULL_VOID(appTheme);
1008         float defaultAmplitudeRatio = appTheme->GetPageTransitionAmplitudeRatio();
1009         springCurve->UpdateMinimumAmplitudeRatio(defaultAmplitudeRatio);
1010     }
1011     option.SetCurve(springCurve);
1012     option.SetDuration(DEFAULT_ANIMATION_DURATION);
1013 #ifdef QUICK_PUSH_TRANSITION
1014     if (pipeline) {
1015         const int32_t nanoToMilliSeconds = 1000000;
1016         const int32_t minTransitionDuration = DEFAULT_ANIMATION_DURATION / 2;
1017         const int32_t frameDelayTime = 32;
1018         int32_t startDelayTime =
1019             static_cast<int32_t>(pipeline->GetTimeFromExternalTimer() - pipeline->GetLastTouchTime()) /
1020             nanoToMilliSeconds;
1021         startDelayTime = std::max(0, startDelayTime);
1022         int32_t delayedDuration = DEFAULT_ANIMATION_DURATION > startDelayTime
1023                                       ? DEFAULT_ANIMATION_DURATION - startDelayTime
1024                                       : DEFAULT_ANIMATION_DURATION;
1025         delayedDuration = std::max(minTransitionDuration, delayedDuration - frameDelayTime);
1026         LOGI("Use quick push delayedDuration:%{public}d", delayedDuration);
1027         option.SetDuration(delayedDuration);
1028     }
1029 #endif
1030 }
1031 
NotifyNavigationLifecycle(bool isShow,bool isFromWindow)1032 void PagePattern::NotifyNavigationLifecycle(bool isShow, bool isFromWindow)
1033 {
1034     auto hostNode = AceType::DynamicCast<FrameNode>(GetHost());
1035     CHECK_NULL_VOID(hostNode);
1036     auto context = hostNode->GetContextRefPtr();
1037     CHECK_NULL_VOID(context);
1038     auto navigationManager = context->GetNavigationManager();
1039     CHECK_NULL_VOID(navigationManager);
1040     NavDestinationActiveReason activeReason = isFromWindow ? NavDestinationActiveReason::APP_STATE_CHANGE
1041         : NavDestinationActiveReason::TRANSITION;
1042     NavDestinationLifecycle lifecycle = isShow ? NavDestinationLifecycle::ON_ACTIVE
1043         : NavDestinationLifecycle::ON_INACTIVE;
1044     navigationManager->FireNavigationLifecycle(hostNode, static_cast<int32_t>(lifecycle),
1045         static_cast<int32_t>(activeReason));
1046 }
1047 } // namespace OHOS::Ace::NG
1048