fix(loading): fix loading overlay during app init

Closes #6209
This commit is contained in:
Adam Bradley
2016-06-29 00:27:50 -05:00
parent 3fb58d95c3
commit b615c60478
3 changed files with 99 additions and 31 deletions

View File

@ -831,6 +831,10 @@ export class NavController extends Ion {
// it should be removed after the transition
view.state = STATE_REMOVE_AFTER_TRANS;
} else if (view.state === STATE_INIT_ENTER) {
// asked to be removed before it even entered!
view.state = STATE_CANCEL_ENTER;
} else {
// if this view is already leaving then no need to immediately
// remove it, otherwise set the remove state
@ -1087,9 +1091,9 @@ export class NavController extends Ion {
// create the transitions animation, play the animation
// when the transition ends call wait for it to end
if (enteringView.state === STATE_INACTIVE) {
// this entering view is already set to inactive, so this
// transition must be canceled, so don't continue
if (enteringView.state === STATE_INACTIVE || enteringView.state === STATE_CANCEL_ENTER) {
// this entering view is already set to inactive or has been canceled
// so this transition must not begin, so don't continue
return done();
}
@ -1185,9 +1189,10 @@ export class NavController extends Ion {
this._app.viewDidEnter.emit(enteringView);
}
if (enteringView.fireOtherLifecycles) {
if (enteringView.fireOtherLifecycles && this._init) {
// only fire leaving lifecycle if the entering
// view hasn't explicitly set not to
// and after the nav has initialized
leavingView.fireDidLeave();
this.viewDidLeave.emit(leavingView);
this._app.viewDidLeave.emit(leavingView);
@ -1224,6 +1229,11 @@ export class NavController extends Ion {
// a transition has completed, but not sure if it's the last one or not
// check if this transition is the most recent one or not
if (enteringView.state === STATE_CANCEL_ENTER) {
// this view was told to leave before it finished entering
this.remove(enteringView.index, 1);
}
if (transId === this._transIds) {
// ok, good news, there were no other transitions that kicked
// off during the time this transition started and ended
@ -1263,9 +1273,7 @@ export class NavController extends Ion {
// this check only needs to happen once, which will add the css
// class to the nav when it's finished its first transition
if (!this._init) {
this._init = true;
}
this._init = true;
} else {
// this transition has not completed, meaning the
@ -1406,6 +1414,14 @@ export class NavController extends Ion {
this._compiler.resolveComponent(view.componentType).then(componentFactory => {
if (view.state === STATE_CANCEL_ENTER) {
// view may have already been removed from the stack
// if so, don't even bother adding it
view.destroy();
this._views.splice(view.index, 1);
return;
}
// add more providers to just this page
let componentProviders = ReflectiveInjector.resolve([
provide(NavController, {useValue: this}),
@ -1613,7 +1629,7 @@ export class NavController extends Ion {
/**
* @private
*/
getByState(state: string): ViewController {
getByState(state: number): ViewController {
for (var i = this._views.length - 1; i >= 0; i--) {
if (this._views[i].state === state) {
return this._views[i];
@ -1708,6 +1724,7 @@ export class NavController extends Ion {
/**
* @private
* Dismiss all pages which have set the `dismissOnPageChange` property.
*/
dismissPageChangeViews() {
this._views.forEach(view => {
@ -1765,15 +1782,17 @@ export class NavController extends Ion {
}
const STATE_ACTIVE = 'active';
const STATE_INACTIVE = 'inactive';
const STATE_INIT_ENTER = 'init_enter';
const STATE_INIT_LEAVE = 'init_leave';
const STATE_TRANS_ENTER = 'trans_enter';
const STATE_TRANS_LEAVE = 'trans_leave';
const STATE_REMOVE = 'remove';
const STATE_REMOVE_AFTER_TRANS = 'remove_after_trans';
const STATE_FORCE_ACTIVE = 'force_active';
const STATE_ACTIVE = 1;
const STATE_INACTIVE = 2;
const STATE_INIT_ENTER = 3;
const STATE_INIT_LEAVE = 4;
const STATE_TRANS_ENTER = 5;
const STATE_TRANS_LEAVE = 6;
const STATE_REMOVE = 7;
const STATE_REMOVE_AFTER_TRANS = 8;
const STATE_CANCEL_ENTER = 9;
const STATE_FORCE_ACTIVE = 10;
const INIT_ZINDEX = 100;
const PORTAL_ZINDEX = 9999;

View File

@ -137,15 +137,17 @@ export function run() {
nav.views = [view1, view2, view3];
nav._remove(1, 1);
expect(nav.length()).toBe(2);
expect(nav.length()).toBe(3);
expect(view1.state).toBe(STATE_INIT_ENTER);
expect(view2.state).toBe(STATE_REMOVE);
expect(view2.state).toBe(STATE_CANCEL_ENTER);
expect(view3.state).toBe(STATE_INIT_LEAVE);
expect(nav.getByIndex(0).state).toBe(STATE_INIT_ENTER);
expect(nav.getByIndex(0).componentType).toBe(Page1);
expect(nav.getByIndex(1).state).toBe(STATE_INIT_LEAVE);
expect(nav.getByIndex(1).componentType).toBe(Page3);
expect(nav.getByIndex(1).state).toBe(STATE_CANCEL_ENTER);
expect(nav.getByIndex(1).componentType).toBe(Page2);
expect(nav.getByIndex(2).state).toBe(STATE_INIT_LEAVE);
expect(nav.getByIndex(2).componentType).toBe(Page3);
});
it('should set to pop the active and enter the previous', () => {
@ -728,6 +730,7 @@ export function run() {
spyOn(enteringView, 'fireDidEnter');
spyOn(leavingView, 'fireDidLeave');
nav._init = true;
nav._afterTrans(enteringView, leavingView, navOpts, hasCompleted, done);
expect(enteringView.fireDidEnter).toHaveBeenCalled();
@ -748,6 +751,7 @@ export function run() {
spyOn(enteringView, 'fireDidEnter');
spyOn(leavingView, 'fireDidLeave');
nav._init = true;
nav._afterTrans(enteringView, leavingView, navOpts, hasCompleted, done);
expect(enteringView.fireDidEnter).not.toHaveBeenCalled();
@ -788,6 +792,7 @@ export function run() {
spyOn(enteringView, 'fireDidEnter');
spyOn(leavingView, 'fireDidLeave');
nav._init = true;
nav._afterTrans(enteringView, leavingView, navOpts, hasCompleted, done);
expect(enteringView.fireDidEnter).not.toHaveBeenCalled();
@ -817,6 +822,19 @@ export function run() {
describe('_transFinish', () => {
it('should remove entering view if it was already set to cancel', () => {
let enteringView = new ViewController(Page1);
let leavingView = new ViewController(Page2);
enteringView.state = STATE_CANCEL_ENTER;
spyOn(nav, 'remove');
nav._transFinish(1, enteringView, leavingView, 'forward', true);
expect(nav.remove).toHaveBeenCalled();
expect(enteringView.state).toBe(STATE_CANCEL_ENTER);
});
it('should not entering/leaving state, after transition that isnt the most recent, and state already changed', () => {
let enteringView = new ViewController(Page1);
enteringView.state = 'somethingelse';
@ -1492,6 +1510,36 @@ export function run() {
// act
nav._beforeTrans(view1, view2, {}, () => {});
});
it('should not begin transition when entering stated is inactive', () => {
let view1 = new ViewController(Page1);
view1.state = STATE_INACTIVE;
let wasDoneCalled = false;
let done = () => {
wasDoneCalled = true;
};
nav._beforeTrans(view1, null, {}, done);
expect(wasDoneCalled).toEqual(true);
expect(view1.state).toEqual(STATE_INACTIVE);
});
it('should not begin transition when entering state is canceled', () => {
let view1 = new ViewController(Page1);
view1.state = STATE_CANCEL_ENTER;
let wasDoneCalled = false;
let done = () => {
wasDoneCalled = true;
};
nav._beforeTrans(view1, null, {}, done);
expect(wasDoneCalled).toEqual(true);
expect(view1.state).toEqual(STATE_CANCEL_ENTER);
});
});
/* private method */
@ -1679,12 +1727,13 @@ class MockNavController extends NavController {
}
const STATE_ACTIVE = 'active';
const STATE_INACTIVE = 'inactive';
const STATE_INIT_ENTER = 'init_enter';
const STATE_INIT_LEAVE = 'init_leave';
const STATE_TRANS_ENTER = 'trans_enter';
const STATE_TRANS_LEAVE = 'trans_leave';
const STATE_REMOVE = 'remove';
const STATE_REMOVE_AFTER_TRANS = 'remove_after_trans';
const STATE_FORCE_ACTIVE = 'force_active';
const STATE_ACTIVE = 1;
const STATE_INACTIVE = 2;
const STATE_INIT_ENTER = 3;
const STATE_INIT_LEAVE = 4;
const STATE_TRANS_ENTER = 5;
const STATE_TRANS_LEAVE = 6;
const STATE_REMOVE = 7;
const STATE_REMOVE_AFTER_TRANS = 8;
const STATE_CANCEL_ENTER = 9;
const STATE_FORCE_ACTIVE = 10;

View File

@ -66,7 +66,7 @@ export class ViewController {
/**
* @private
*/
state: string = '';
state: number = 0;
/**
* @private