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