fix(nav): prevent completing transition from being interrupted (#19113)

* do not enable swipe to begin before previous one has ended

* update defaults

* use canStart instead

* pause animations on finish

* remove old pause code
This commit is contained in:
Liam DeBeasi
2019-08-16 13:33:39 -04:00
committed by GitHub
parent 624e118b56
commit fd65765bdf
3 changed files with 22 additions and 6 deletions

View File

@ -18,6 +18,7 @@ export class Nav implements NavOutlet {
private transInstr: TransitionInstruction[] = []; private transInstr: TransitionInstruction[] = [];
private sbAni?: Animation | IonicAnimation; private sbAni?: Animation | IonicAnimation;
private animationEnabled = true;
private useRouter = false; private useRouter = false;
private isTransitioning = false; private isTransitioning = false;
private destroyed = false; private destroyed = false;
@ -937,6 +938,7 @@ export class Nav implements NavOutlet {
!!this.swipeGesture && !!this.swipeGesture &&
!this.isTransitioning && !this.isTransitioning &&
this.transInstr.length === 0 && this.transInstr.length === 0 &&
this.animationEnabled &&
this.canGoBackSync() this.canGoBackSync()
); );
} }
@ -960,6 +962,10 @@ export class Nav implements NavOutlet {
private onEnd(shouldComplete: boolean, stepValue: number, dur: number) { private onEnd(shouldComplete: boolean, stepValue: number, dur: number) {
if (this.sbAni) { if (this.sbAni) {
this.animationEnabled = false;
this.sbAni.onFinish(() => {
this.animationEnabled = true;
}, { oneTimeCallback: true });
this.sbAni.progressEnd(shouldComplete, stepValue, dur); this.sbAni.progressEnd(shouldComplete, stepValue, dur);
} }
} }

View File

@ -18,6 +18,7 @@ export class RouterOutlet implements ComponentInterface, NavOutlet {
private waitPromise?: Promise<void>; private waitPromise?: Promise<void>;
private gesture?: Gesture; private gesture?: Gesture;
private ani?: IonicAnimation | Animation; private ani?: IonicAnimation | Animation;
private animationEnabled = true;
@Element() el!: HTMLElement; @Element() el!: HTMLElement;
@ -65,12 +66,18 @@ export class RouterOutlet implements ComponentInterface, NavOutlet {
async componentDidLoad() { async componentDidLoad() {
this.gesture = (await import('../../utils/gesture/swipe-back')).createSwipeBackGesture( this.gesture = (await import('../../utils/gesture/swipe-back')).createSwipeBackGesture(
this.el, this.el,
() => !!this.swipeHandler && this.swipeHandler.canStart(), () => !!this.swipeHandler && this.swipeHandler.canStart() && this.animationEnabled,
() => this.swipeHandler && this.swipeHandler.onStart(), () => this.swipeHandler && this.swipeHandler.onStart(),
step => this.ani && this.ani.progressStep(step), step => this.ani && this.ani.progressStep(step),
(shouldComplete, step, dur) => { (shouldComplete, step, dur) => {
if (this.ani) { if (this.ani) {
this.animationEnabled = false;
this.ani.onFinish(() => {
this.animationEnabled = true;
}, { oneTimeCallback: true });
this.ani.progressEnd(shouldComplete, step, dur); this.ani.progressEnd(shouldComplete, step, dur);
} }
if (this.swipeHandler) { if (this.swipeHandler) {
this.swipeHandler.onEnd(shouldComplete); this.swipeHandler.onEnd(shouldComplete);

View File

@ -604,7 +604,7 @@ export const createAnimation = () => {
} }
}; };
const initializeCSSAnimation = () => { const initializeCSSAnimation = (toggleAnimationName = true) => {
cleanUpStyleSheets(); cleanUpStyleSheets();
elements.forEach(element => { elements.forEach(element => {
@ -628,7 +628,10 @@ export const createAnimation = () => {
setStyleProperty(element, 'animation-iteration-count', iterationsCount); setStyleProperty(element, 'animation-iteration-count', iterationsCount);
setStyleProperty(element, 'animation-play-state', 'paused'); setStyleProperty(element, 'animation-play-state', 'paused');
setStyleProperty(element, 'animation-name', `${stylesheet.id}-alt`); if (toggleAnimationName) {
setStyleProperty(element, 'animation-name', `${stylesheet.id}-alt`);
}
requestAnimationFrame(() => { requestAnimationFrame(() => {
setStyleProperty(element, 'animation-name', stylesheet.id || null); setStyleProperty(element, 'animation-name', stylesheet.id || null);
}); });
@ -660,14 +663,14 @@ export const createAnimation = () => {
}; };
const initializeAnimation = () => { const initializeAnimation = (toggleAnimationName = true) => {
beforeAnimation(); beforeAnimation();
if (_keyframes.length > 0) { if (_keyframes.length > 0) {
if (supportsWebAnimations) { if (supportsWebAnimations) {
initializeWebAnimation(); initializeWebAnimation();
} else { } else {
initializeCSSAnimation(); initializeCSSAnimation(toggleAnimationName);
} }
} }
@ -968,7 +971,7 @@ export const createAnimation = () => {
*/ */
const play = () => { const play = () => {
if (!initialized) { if (!initialized) {
initializeAnimation(); initializeAnimation(false);
} }
if (finished) { if (finished) {