Skip to content

Commit 8652422

Browse files
authored
fix(android): improved handling for nested frames (#10713)
1 parent 2377b6a commit 8652422

File tree

7 files changed

+163
-99
lines changed

7 files changed

+163
-99
lines changed

packages/core/ui/core/view-base/index.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,12 +117,13 @@ export interface ShowModalOptions {
117117
* @param criterion - The type of ancestor view we are looking for. Could be a string containing a class name or an actual type.
118118
* Returns an instance of a view (if found), otherwise undefined.
119119
*/
120-
export function getAncestor(view: ViewBaseDefinition, criterion: string | { new () }): ViewBaseDefinition {
121-
let matcher: (view: ViewBaseDefinition) => boolean = null;
120+
export function getAncestor<T extends ViewBaseDefinition = ViewBaseDefinition>(view: T, criterion: string | { new () }): T {
121+
let matcher: (view: ViewBaseDefinition) => view is T;
122+
122123
if (typeof criterion === 'string') {
123-
matcher = (view: ViewBaseDefinition) => view.typeName === criterion;
124+
matcher = (view: ViewBaseDefinition): view is T => view.typeName === criterion;
124125
} else {
125-
matcher = (view: ViewBaseDefinition) => view instanceof criterion;
126+
matcher = (view: ViewBaseDefinition): view is T => view instanceof criterion;
126127
}
127128

128129
for (let parent = view.parent; parent != null; parent = parent.parent) {

packages/core/ui/frame/callbacks/activity-callbacks.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import { AndroidActivityBackPressedEventData, AndroidActivityNewIntentEventData,
55
import { Trace } from '../../../trace';
66
import { View } from '../../core/view';
77

8-
import { _clearEntry, _clearFragment, _getAnimatedEntries, _reverseTransitions, _setAndroidFragmentTransitions, _updateTransitions } from '../fragment.transitions';
9-
108
import { profile } from '../../../profiling';
119
import { isEmbedded, setEmbeddedView } from '../../embedding';
1210

packages/core/ui/frame/fragment.transitions.android.ts

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Definitions.
2-
import { NavigationType } from './frame-common';
2+
import { NavigationType, TransitionState } from './frame-common';
33
import { NavigationTransition, BackstackEntry } from '.';
44

55
// Types.
@@ -152,7 +152,7 @@ export function _setAndroidFragmentTransitions(animated: boolean, navigationTran
152152
setupCurrentFragmentExplodeTransition(navigationTransition, currentEntry);
153153
}
154154
} else if (name.indexOf('flip') === 0) {
155-
const direction = name.substr('flip'.length) || 'right'; //Extract the direction from the string
155+
const direction = name.substring('flip'.length) || 'right'; //Extract the direction from the string
156156
const flipTransition = new FlipTransition(direction, navigationTransition.duration, navigationTransition.curve);
157157

158158
setupNewFragmentCustomTransition(navigationTransition, newEntry, flipTransition);
@@ -282,23 +282,28 @@ export function _getAnimatedEntries(frameId: number): Set<BackstackEntry> {
282282

283283
export function _updateTransitions(entry: ExpandedEntry): void {
284284
const fragment = entry.fragment;
285+
286+
if (!fragment) {
287+
return;
288+
}
289+
285290
const enterTransitionListener = entry.enterTransitionListener;
286-
if (enterTransitionListener && fragment) {
291+
if (enterTransitionListener) {
287292
fragment.setEnterTransition(enterTransitionListener.transition);
288293
}
289294

290295
const exitTransitionListener = entry.exitTransitionListener;
291-
if (exitTransitionListener && fragment) {
296+
if (exitTransitionListener) {
292297
fragment.setExitTransition(exitTransitionListener.transition);
293298
}
294299

295300
const reenterTransitionListener = entry.reenterTransitionListener;
296-
if (reenterTransitionListener && fragment) {
301+
if (reenterTransitionListener) {
297302
fragment.setReenterTransition(reenterTransitionListener.transition);
298303
}
299304

300305
const returnTransitionListener = entry.returnTransitionListener;
301-
if (returnTransitionListener && fragment) {
306+
if (returnTransitionListener) {
302307
fragment.setReturnTransition(returnTransitionListener.transition);
303308
}
304309
}
@@ -428,6 +433,16 @@ function addToWaitingQueue(entry: ExpandedEntry): void {
428433
entries.add(entry);
429434
}
430435

436+
function cloneExpandedTransitionListener(expandedTransitionListener: ExpandedTransitionListener) {
437+
if (!expandedTransitionListener) {
438+
return null;
439+
}
440+
441+
const cloneTransition = expandedTransitionListener.transition.clone();
442+
443+
return addNativeTransitionListener(expandedTransitionListener.entry, cloneTransition);
444+
}
445+
431446
function clearExitAndReenterTransitions(entry: ExpandedEntry, removeListener: boolean): void {
432447
const fragment: androidx.fragment.app.Fragment = entry.fragment;
433448
const exitListener = entry.exitTransitionListener;
@@ -469,15 +484,56 @@ function clearExitAndReenterTransitions(entry: ExpandedEntry, removeListener: bo
469484
}
470485
}
471486

487+
export function _getTransitionState(entry: ExpandedEntry): TransitionState {
488+
let transitionState: TransitionState;
489+
490+
if (entry.enterTransitionListener && entry.exitTransitionListener) {
491+
transitionState = {
492+
enterTransitionListener: cloneExpandedTransitionListener(entry.enterTransitionListener),
493+
exitTransitionListener: cloneExpandedTransitionListener(entry.exitTransitionListener),
494+
reenterTransitionListener: cloneExpandedTransitionListener(entry.reenterTransitionListener),
495+
returnTransitionListener: cloneExpandedTransitionListener(entry.returnTransitionListener),
496+
transitionName: entry.transitionName,
497+
entry,
498+
};
499+
} else {
500+
transitionState = null;
501+
}
502+
503+
return transitionState;
504+
}
505+
506+
export function _restoreTransitionState(snapshot: TransitionState): void {
507+
const entry = snapshot.entry as ExpandedEntry;
508+
509+
if (snapshot.enterTransitionListener) {
510+
entry.enterTransitionListener = snapshot.enterTransitionListener;
511+
}
512+
513+
if (snapshot.exitTransitionListener) {
514+
entry.exitTransitionListener = snapshot.exitTransitionListener;
515+
}
516+
517+
if (snapshot.reenterTransitionListener) {
518+
entry.reenterTransitionListener = snapshot.reenterTransitionListener;
519+
}
520+
521+
if (snapshot.returnTransitionListener) {
522+
entry.returnTransitionListener = snapshot.returnTransitionListener;
523+
}
524+
525+
entry.transitionName = snapshot.transitionName;
526+
}
527+
472528
export function _clearFragment(entry: ExpandedEntry): void {
473-
clearEntry(entry, false);
529+
clearTransitions(entry, false);
474530
}
475531

476532
export function _clearEntry(entry: ExpandedEntry): void {
477-
clearEntry(entry, true);
533+
clearTransitions(entry, true);
478534
}
479535

480-
function clearEntry(entry: ExpandedEntry, removeListener: boolean): void {
536+
function clearTransitions(entry: ExpandedEntry, removeListener: boolean): void {
481537
clearExitAndReenterTransitions(entry, removeListener);
482538

483539
const fragment: androidx.fragment.app.Fragment = entry.fragment;
@@ -569,7 +625,7 @@ function setReturnTransition(navigationTransition: NavigationTransition, entry:
569625

570626
function setupNewFragmentSlideTransition(navTransition: NavigationTransition, entry: ExpandedEntry, name: string): void {
571627
setupCurrentFragmentSlideTransition(navTransition, entry, name);
572-
const direction = name.substr('slide'.length) || 'left'; //Extract the direction from the string
628+
const direction = name.substring('slide'.length) || 'left'; //Extract the direction from the string
573629
switch (direction) {
574630
case 'left':
575631
setEnterTransition(navTransition, entry, new androidx.transition.Slide(android.view.Gravity.RIGHT));
@@ -594,7 +650,7 @@ function setupNewFragmentSlideTransition(navTransition: NavigationTransition, en
594650
}
595651

596652
function setupCurrentFragmentSlideTransition(navTransition: NavigationTransition, entry: ExpandedEntry, name: string): void {
597-
const direction = name.substr('slide'.length) || 'left'; //Extract the direction from the string
653+
const direction = name.substring('slide'.length) || 'left'; //Extract the direction from the string
598654
switch (direction) {
599655
case 'left':
600656
setExitTransition(navTransition, entry, new androidx.transition.Slide(android.view.Gravity.LEFT));

packages/core/ui/frame/fragment.transitions.d.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { NavigationTransition, BackstackEntry } from '.';
1+
import { NavigationTransition, BackstackEntry, TransitionState } from '.';
22

33
/**
44
* @private
@@ -20,6 +20,14 @@ export function _updateTransitions(entry: BackstackEntry): void;
2020
* Reverse transitions from entry to fragment if any.
2121
*/
2222
export function _reverseTransitions(previousEntry: BackstackEntry, currentEntry: BackstackEntry): boolean;
23+
/**
24+
* @private
25+
*/
26+
export function _getTransitionState(entry: BackstackEntry): TransitionState;
27+
/**
28+
* @private
29+
*/
30+
export function _restoreTransitionState(snapshot: TransitionState): void;
2331
/**
2432
* @private
2533
* Called when entry is removed from backstack (either back navigation or

packages/core/ui/frame/frame-common.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,13 @@ export class FrameBase extends CustomLayoutView {
7676
return true;
7777
} else if (top) {
7878
let parentFrameCanGoBack = false;
79-
let parentFrame = <FrameBase>getAncestor(top, 'Frame');
79+
let parentFrame = getAncestor(top, 'Frame');
8080

8181
while (parentFrame && !parentFrameCanGoBack) {
8282
if (parentFrame && parentFrame.canGoBack()) {
8383
parentFrameCanGoBack = true;
8484
} else {
85-
parentFrame = <FrameBase>getAncestor(parentFrame, 'Frame');
85+
parentFrame = getAncestor(parentFrame, 'Frame');
8686
}
8787
}
8888

@@ -122,7 +122,6 @@ export class FrameBase extends CustomLayoutView {
122122
@profile
123123
public onLoaded() {
124124
super.onLoaded();
125-
126125
this._processNextNavigationEntry();
127126
}
128127

@@ -323,9 +322,10 @@ export class FrameBase extends CustomLayoutView {
323322
}
324323

325324
private isNestedWithin(parentFrameCandidate: FrameBase): boolean {
326-
let frameAncestor: FrameBase = this;
325+
let frameAncestor = this as FrameBase;
326+
327327
while (frameAncestor) {
328-
frameAncestor = <FrameBase>getAncestor(frameAncestor, FrameBase);
328+
frameAncestor = getAncestor(frameAncestor, FrameBase);
329329
if (frameAncestor === parentFrameCandidate) {
330330
return true;
331331
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy