From beab06f7ce38cf6f1d769b601b933f3f140a1d36 Mon Sep 17 00:00:00 2001 From: "Manu Mtz.-Almeida" Date: Fri, 4 Nov 2016 20:12:04 +0100 Subject: [PATCH 1/4] fix(nav): controller is initialized --- src/components/nav/test/basic/app-module.ts | 2 +- src/navigation/nav-controller-base.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/nav/test/basic/app-module.ts b/src/components/nav/test/basic/app-module.ts index 7b64379785..8e690840f6 100644 --- a/src/components/nav/test/basic/app-module.ts +++ b/src/components/nav/test/basic/app-module.ts @@ -258,7 +258,7 @@ export class FirstPage { } -@Component({template: ''}) +@Component({template: ''}) export class RedirectPage { constructor(public navCtrl: NavController) { } ionViewDidEnter() { diff --git a/src/navigation/nav-controller-base.ts b/src/navigation/nav-controller-base.ts index 60e057f59d..ab68e09594 100644 --- a/src/navigation/nav-controller-base.ts +++ b/src/navigation/nav-controller-base.ts @@ -177,6 +177,7 @@ export class NavControllerBase extends Ion implements NavController { ti.resolve = (hasCompleted: boolean, isAsync: boolean, enteringName: string, leavingName: string, direction: string) => { // transition has successfully resolved this._trnsId = null; + this._init = true; resolve && resolve(hasCompleted, isAsync, enteringName, leavingName, direction); // let's see if there's another to kick off From 63d495ae431db954b96f346504791ea602443ce9 Mon Sep 17 00:00:00 2001 From: "Manu Mtz.-Almeida" Date: Fri, 4 Nov 2016 20:16:56 +0100 Subject: [PATCH 2/4] fix(nav): transitioning state is a boolean not a timer long async promises in canLeave / canEnter can lead to a false negative of isTransitioning() It is key for the internal consistency of NavController to always know the correct state --- src/navigation/nav-controller-base.ts | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/navigation/nav-controller-base.ts b/src/navigation/nav-controller-base.ts index ab68e09594..2d48e44f1a 100644 --- a/src/navigation/nav-controller-base.ts +++ b/src/navigation/nav-controller-base.ts @@ -34,7 +34,7 @@ export class NavControllerBase extends Ion implements NavController { _sbThreshold: number; _sbTrns: Transition; _trnsId: number = null; - _trnsTm: number = 0; + _trnsTm: boolean = false; _viewport: ViewContainerRef; _views: ViewController[] = []; @@ -597,7 +597,7 @@ export class NavControllerBase extends Ion implements NavController { const duration = transition.getDuration(); // set that this nav is actively transitioning - this.setTransitioning(true, duration); + this.setTransitioning(true); if (transition.isRoot()) { // this is the top most, or only active transition, so disable the app @@ -883,7 +883,7 @@ export class NavControllerBase extends Ion implements NavController { if (this._sbTrns && this._sbGesture) { // continue to disable the app while actively dragging this._app.setEnabled(false, ACTIVE_TRANSITION_DEFAULT); - this.setTransitioning(true, ACTIVE_TRANSITION_DEFAULT); + this.setTransitioning(true); // set the transition animation's progress this._sbTrns.progressStep(stepValue); @@ -933,15 +933,11 @@ export class NavControllerBase extends Ion implements NavController { } isTransitioning(): boolean { - if (this._trnsTm === 0) { - return false; - } - // using a timestamp instead of boolean incase something goes wrong - return (this._trnsTm > Date.now()); + return this._trnsTm; } - setTransitioning(isTransitioning: boolean, durationPadding: number = ACTIVE_TRANSITION_DEFAULT) { - this._trnsTm = (isTransitioning ? (Date.now() + durationPadding + ACTIVE_TRANSITION_OFFSET) : 0); + setTransitioning(isTransitioning: boolean) { + this._trnsTm = isTransitioning; } getActive(): ViewController { From 5f1a86265cbba9a80eac4976bc0ec0308b0ac15e Mon Sep 17 00:00:00 2001 From: "Manu Mtz.-Almeida" Date: Fri, 4 Nov 2016 20:18:09 +0100 Subject: [PATCH 3/4] fix(nav): returning Promise in canLeave / canEnter works as expected --- src/navigation/nav-controller-base.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/navigation/nav-controller-base.ts b/src/navigation/nav-controller-base.ts index 2d48e44f1a..a89950efae 100644 --- a/src/navigation/nav-controller-base.ts +++ b/src/navigation/nav-controller-base.ts @@ -485,8 +485,13 @@ export class NavControllerBase extends Ion implements NavController { if (promises.length) { // darn, async promises, gotta wait for them to resolve Promise.all(promises) - .then(() => this._postViewInit(enteringView, leavingView, ti, resolve)) - .catch(reject); + .then((values: any[]) => { + if (values.some(result => result === false)) { + reject(`ionViewCanEnter rejected`); + } else { + this._postViewInit(enteringView, leavingView, ti, resolve); + } + }).catch(reject); } else { // synchronous and all tests passed! let's move on already this._postViewInit(enteringView, leavingView, ti, resolve); From 0ab990c0155c89d0d9079c4b64c77ff244025a31 Mon Sep 17 00:00:00 2001 From: "Manu Mtz.-Almeida" Date: Fri, 4 Nov 2016 20:18:29 +0100 Subject: [PATCH 4/4] fix(nav): it is not allowed to pop all the views --- src/navigation/nav-controller-base.ts | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/navigation/nav-controller-base.ts b/src/navigation/nav-controller-base.ts index a89950efae..34c17eaeed 100644 --- a/src/navigation/nav-controller-base.ts +++ b/src/navigation/nav-controller-base.ts @@ -248,14 +248,15 @@ export class NavControllerBase extends Ion implements NavController { if (!ti) { return false; } - // set that this nav is actively transitioning - this.setTransitioning(true); // Get entering and leaving views const leavingView = this.getActive(); const enteringView = this._getEnteringView(ti, leavingView); - assert(leavingView || enteringView, 'Both leavingView and enteringView are null'); + assert(leavingView || enteringView, 'both leavingView and enteringView are null'); + + // set that this nav is actively transitioning + this.setTransitioning(true); // Initialize enteringView if (enteringView && isBlank(enteringView._state)) { @@ -328,6 +329,16 @@ export class NavControllerBase extends Ion implements NavController { } _postViewInit(enteringView: ViewController, leavingView: ViewController, ti: TransitionInstruction, resolve: TransitionResolveFn) { + assert(leavingView || enteringView, 'Both leavingView and enteringView are null'); + + if (!enteringView && !this._isPortal) { + console.warn(`You can't remove all the pages in the navigation stack. nav.pop() is probably called too many times.`, + this, this.getNativeElement()); + + ti.reject && ti.reject('navigation stack needs at least one root page'); + return false; + } + const opts = ti.opts || {}; const insertViews = ti.insertViews; const removeStart = ti.removeStart;