From 70a38ac5945614ce7b84ec064f872079fc98029f Mon Sep 17 00:00:00 2001 From: "Manu Mtz.-Almeida" Date: Sat, 25 Aug 2018 10:19:27 +0200 Subject: [PATCH] fix(transition): cleanup transition fixes #15317 --- core/src/utils/transition.ts | 143 ++++++++++++++++++++--------------- 1 file changed, 81 insertions(+), 62 deletions(-) diff --git a/core/src/utils/transition.ts b/core/src/utils/transition.ts index 1daedf19e8..ea53da44e9 100644 --- a/core/src/utils/transition.ts +++ b/core/src/utils/transition.ts @@ -6,35 +6,24 @@ import { Animation, AnimationBuilder, NavDirection, NavOptions } from '../interf const iosTransitionAnimation = () => import('./animations/ios.transition'); const mdTransitionAnimation = () => import('./animations/md.transition'); -export function transition(opts: TransitionOptions): Promise { - return new Promise(resolve => { - opts.queue.write(async () => { +export function transition(opts: TransitionOptions): Promise { + return new Promise((resolve, reject) => { + opts.queue.write(() => { beforeTransition(opts); - - const animationBuilder = await getAnimationBuilder(opts); - const ani = (animationBuilder) - ? animation(animationBuilder, opts) - : noAnimation(opts); // fast path for no animation - - resolve(ani); + runTransition(opts).then(result => { + if (result.animation) { + result.animation.destroy(); + } + afterTransition(opts); + resolve(result); + }, error => { + afterTransition(opts); + reject(error); + }); }); }); } -async function getAnimationBuilder(opts: TransitionOptions): Promise { - if (!opts.leavingEl || opts.animated === false || opts.duration === 0) { - return undefined; - } - if (opts.animationBuilder) { - return opts.animationBuilder; - } - const builder = (opts.mode === 'ios') - ? (await iosTransitionAnimation()).iosTransitionAnimation - : (await mdTransitionAnimation()).mdTransitionAnimation; - - return builder; -} - function beforeTransition(opts: TransitionOptions) { const enteringEl = opts.enteringEl; const leavingEl = opts.leavingEl; @@ -52,46 +41,16 @@ function beforeTransition(opts: TransitionOptions) { } } -export function setPageHidden(el: HTMLElement, hidden: boolean) { - if (hidden) { - el.setAttribute('aria-hidden', 'true'); - el.classList.add('ion-page-hidden'); - } else { - el.hidden = false; - el.removeAttribute('aria-hidden'); - el.classList.remove('ion-page-hidden'); - } +async function runTransition(opts: TransitionOptions): Promise { + const animationBuilder = await getAnimationBuilder(opts); + const ani = (animationBuilder) + ? animation(animationBuilder, opts) + : noAnimation(opts); // fast path for no animation + + return ani; } -async function animation(animationBuilder: AnimationBuilder, opts: TransitionOptions): Promise { - await waitForReady(opts, true); - - const trns = await opts.animationCtrl.create(animationBuilder, opts.baseEl, opts); - fireWillEvents(opts.window, opts.enteringEl, opts.leavingEl); - await playTransition(trns, opts); - - markVisible(opts); - - if (trns.hasCompleted) { - fireDidEvents(opts.window, opts.enteringEl, opts.leavingEl); - } - return trns; -} - -async function noAnimation(opts: TransitionOptions): Promise { - const enteringEl = opts.enteringEl; - const leavingEl = opts.leavingEl; - - await waitForReady(opts, false); - - markVisible(opts); - - fireWillEvents(opts.window, enteringEl, leavingEl); - fireDidEvents(opts.window, enteringEl, leavingEl); - return null; -} - -async function markVisible(opts: TransitionOptions) { +async function afterTransition(opts: TransitionOptions) { const enteringEl = opts.enteringEl; const leavingEl = opts.leavingEl; if (enteringEl) { @@ -102,6 +61,50 @@ async function markVisible(opts: TransitionOptions) { } } +async function getAnimationBuilder(opts: TransitionOptions): Promise { + if (!opts.leavingEl || opts.animated === false || opts.duration === 0) { + return undefined; + } + if (opts.animationBuilder) { + return opts.animationBuilder; + } + const builder = (opts.mode === 'ios') + ? (await iosTransitionAnimation()).iosTransitionAnimation + : (await mdTransitionAnimation()).mdTransitionAnimation; + + return builder; +} + +async function animation(animationBuilder: AnimationBuilder, opts: TransitionOptions): Promise { + await waitForReady(opts, true); + + const trns = await opts.animationCtrl.create(animationBuilder, opts.baseEl, opts); + fireWillEvents(opts.window, opts.enteringEl, opts.leavingEl); + await playTransition(trns, opts); + + if (trns.hasCompleted) { + fireDidEvents(opts.window, opts.enteringEl, opts.leavingEl); + } + return { + hasCompleted: trns.hasCompleted, + animation: trns + }; +} + +async function noAnimation(opts: TransitionOptions): Promise { + const enteringEl = opts.enteringEl; + const leavingEl = opts.leavingEl; + + await waitForReady(opts, false); + + fireWillEvents(opts.window, enteringEl, leavingEl); + fireDidEvents(opts.window, enteringEl, leavingEl); + + return { + hasCompleted: true + }; +} + async function waitForReady(opts: TransitionOptions, defaultDeep: boolean) { const deep = opts.deepWait != null ? opts.deepWait : defaultDeep; const promises = deep ? [ @@ -184,6 +187,17 @@ async function deepReady(el: Element | undefined): Promise { } } +export function setPageHidden(el: HTMLElement, hidden: boolean) { + if (hidden) { + el.setAttribute('aria-hidden', 'true'); + el.classList.add('ion-page-hidden'); + } else { + el.hidden = false; + el.removeAttribute('aria-hidden'); + el.classList.remove('ion-page-hidden'); + } +} + function setZIndex( enteringEl: HTMLElement | undefined, leavingEl: HTMLElement | undefined, @@ -208,3 +222,8 @@ export interface TransitionOptions extends NavOptions { enteringEl: HTMLElement; leavingEl: HTMLElement | undefined; } + +export interface TransitionResult { + hasCompleted: boolean; + animation?: Animation; +}