Skip to content

Commit b615c60

Browse files
committed
fix(loading): fix loading overlay during app init
Closes #6209
1 parent 3fb58d9 commit b615c60

File tree

3 files changed

+99
-31
lines changed

3 files changed

+99
-31
lines changed

src/components/nav/nav-controller.ts

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,10 @@ export class NavController extends Ion {
831831
// it should be removed after the transition
832832
view.state = STATE_REMOVE_AFTER_TRANS;
833833

834+
} else if (view.state === STATE_INIT_ENTER) {
835+
// asked to be removed before it even entered!
836+
view.state = STATE_CANCEL_ENTER;
837+
834838
} else {
835839
// if this view is already leaving then no need to immediately
836840
// remove it, otherwise set the remove state
@@ -1087,9 +1091,9 @@ export class NavController extends Ion {
10871091
// create the transitions animation, play the animation
10881092
// when the transition ends call wait for it to end
10891093

1090-
if (enteringView.state === STATE_INACTIVE) {
1091-
// this entering view is already set to inactive, so this
1092-
// transition must be canceled, so don't continue
1094+
if (enteringView.state === STATE_INACTIVE || enteringView.state === STATE_CANCEL_ENTER) {
1095+
// this entering view is already set to inactive or has been canceled
1096+
// so this transition must not begin, so don't continue
10931097
return done();
10941098
}
10951099

@@ -1185,9 +1189,10 @@ export class NavController extends Ion {
11851189
this._app.viewDidEnter.emit(enteringView);
11861190
}
11871191

1188-
if (enteringView.fireOtherLifecycles) {
1192+
if (enteringView.fireOtherLifecycles && this._init) {
11891193
// only fire leaving lifecycle if the entering
11901194
// view hasn't explicitly set not to
1195+
// and after the nav has initialized
11911196
leavingView.fireDidLeave();
11921197
this.viewDidLeave.emit(leavingView);
11931198
this._app.viewDidLeave.emit(leavingView);
@@ -1224,6 +1229,11 @@ export class NavController extends Ion {
12241229
// a transition has completed, but not sure if it's the last one or not
12251230
// check if this transition is the most recent one or not
12261231

1232+
if (enteringView.state === STATE_CANCEL_ENTER) {
1233+
// this view was told to leave before it finished entering
1234+
this.remove(enteringView.index, 1);
1235+
}
1236+
12271237
if (transId === this._transIds) {
12281238
// ok, good news, there were no other transitions that kicked
12291239
// off during the time this transition started and ended
@@ -1263,9 +1273,7 @@ export class NavController extends Ion {
12631273

12641274
// this check only needs to happen once, which will add the css
12651275
// class to the nav when it's finished its first transition
1266-
if (!this._init) {
1267-
this._init = true;
1268-
}
1276+
this._init = true;
12691277

12701278
} else {
12711279
// this transition has not completed, meaning the
@@ -1406,6 +1414,14 @@ export class NavController extends Ion {
14061414

14071415
this._compiler.resolveComponent(view.componentType).then(componentFactory => {
14081416

1417+
if (view.state === STATE_CANCEL_ENTER) {
1418+
// view may have already been removed from the stack
1419+
// if so, don't even bother adding it
1420+
view.destroy();
1421+
this._views.splice(view.index, 1);
1422+
return;
1423+
}
1424+
14091425
// add more providers to just this page
14101426
let componentProviders = ReflectiveInjector.resolve([
14111427
provide(NavController, {useValue: this}),
@@ -1613,7 +1629,7 @@ export class NavController extends Ion {
16131629
/**
16141630
* @private
16151631
*/
1616-
getByState(state: string): ViewController {
1632+
getByState(state: number): ViewController {
16171633
for (var i = this._views.length - 1; i >= 0; i--) {
16181634
if (this._views[i].state === state) {
16191635
return this._views[i];
@@ -1708,6 +1724,7 @@ export class NavController extends Ion {
17081724

17091725
/**
17101726
* @private
1727+
* Dismiss all pages which have set the `dismissOnPageChange` property.
17111728
*/
17121729
dismissPageChangeViews() {
17131730
this._views.forEach(view => {
@@ -1765,15 +1782,17 @@ export class NavController extends Ion {
17651782

17661783
}
17671784

1768-
const STATE_ACTIVE = 'active';
1769-
const STATE_INACTIVE = 'inactive';
1770-
const STATE_INIT_ENTER = 'init_enter';
1771-
const STATE_INIT_LEAVE = 'init_leave';
1772-
const STATE_TRANS_ENTER = 'trans_enter';
1773-
const STATE_TRANS_LEAVE = 'trans_leave';
1774-
const STATE_REMOVE = 'remove';
1775-
const STATE_REMOVE_AFTER_TRANS = 'remove_after_trans';
1776-
const STATE_FORCE_ACTIVE = 'force_active';
1785+
const STATE_ACTIVE = 1;
1786+
const STATE_INACTIVE = 2;
1787+
const STATE_INIT_ENTER = 3;
1788+
const STATE_INIT_LEAVE = 4;
1789+
const STATE_TRANS_ENTER = 5;
1790+
const STATE_TRANS_LEAVE = 6;
1791+
const STATE_REMOVE = 7;
1792+
const STATE_REMOVE_AFTER_TRANS = 8;
1793+
const STATE_CANCEL_ENTER = 9;
1794+
const STATE_FORCE_ACTIVE = 10;
1795+
17771796
const INIT_ZINDEX = 100;
17781797
const PORTAL_ZINDEX = 9999;
17791798

src/components/nav/test/nav-controller.spec.ts

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -137,15 +137,17 @@ export function run() {
137137
nav.views = [view1, view2, view3];
138138

139139
nav._remove(1, 1);
140-
expect(nav.length()).toBe(2);
140+
expect(nav.length()).toBe(3);
141141
expect(view1.state).toBe(STATE_INIT_ENTER);
142-
expect(view2.state).toBe(STATE_REMOVE);
142+
expect(view2.state).toBe(STATE_CANCEL_ENTER);
143143
expect(view3.state).toBe(STATE_INIT_LEAVE);
144144

145145
expect(nav.getByIndex(0).state).toBe(STATE_INIT_ENTER);
146146
expect(nav.getByIndex(0).componentType).toBe(Page1);
147-
expect(nav.getByIndex(1).state).toBe(STATE_INIT_LEAVE);
148-
expect(nav.getByIndex(1).componentType).toBe(Page3);
147+
expect(nav.getByIndex(1).state).toBe(STATE_CANCEL_ENTER);
148+
expect(nav.getByIndex(1).componentType).toBe(Page2);
149+
expect(nav.getByIndex(2).state).toBe(STATE_INIT_LEAVE);
150+
expect(nav.getByIndex(2).componentType).toBe(Page3);
149151
});
150152

151153
it('should set to pop the active and enter the previous', () => {
@@ -728,6 +730,7 @@ export function run() {
728730
spyOn(enteringView, 'fireDidEnter');
729731
spyOn(leavingView, 'fireDidLeave');
730732

733+
nav._init = true;
731734
nav._afterTrans(enteringView, leavingView, navOpts, hasCompleted, done);
732735

733736
expect(enteringView.fireDidEnter).toHaveBeenCalled();
@@ -748,6 +751,7 @@ export function run() {
748751
spyOn(enteringView, 'fireDidEnter');
749752
spyOn(leavingView, 'fireDidLeave');
750753

754+
nav._init = true;
751755
nav._afterTrans(enteringView, leavingView, navOpts, hasCompleted, done);
752756

753757
expect(enteringView.fireDidEnter).not.toHaveBeenCalled();
@@ -788,6 +792,7 @@ export function run() {
788792
spyOn(enteringView, 'fireDidEnter');
789793
spyOn(leavingView, 'fireDidLeave');
790794

795+
nav._init = true;
791796
nav._afterTrans(enteringView, leavingView, navOpts, hasCompleted, done);
792797

793798
expect(enteringView.fireDidEnter).not.toHaveBeenCalled();
@@ -817,6 +822,19 @@ export function run() {
817822

818823
describe('_transFinish', () => {
819824

825+
it('should remove entering view if it was already set to cancel', () => {
826+
let enteringView = new ViewController(Page1);
827+
let leavingView = new ViewController(Page2);
828+
enteringView.state = STATE_CANCEL_ENTER;
829+
830+
spyOn(nav, 'remove');
831+
832+
nav._transFinish(1, enteringView, leavingView, 'forward', true);
833+
834+
expect(nav.remove).toHaveBeenCalled();
835+
expect(enteringView.state).toBe(STATE_CANCEL_ENTER);
836+
});
837+
820838
it('should not entering/leaving state, after transition that isnt the most recent, and state already changed', () => {
821839
let enteringView = new ViewController(Page1);
822840
enteringView.state = 'somethingelse';
@@ -1492,6 +1510,36 @@ export function run() {
14921510
// act
14931511
nav._beforeTrans(view1, view2, {}, () => {});
14941512
});
1513+
1514+
it('should not begin transition when entering stated is inactive', () => {
1515+
let view1 = new ViewController(Page1);
1516+
view1.state = STATE_INACTIVE;
1517+
1518+
let wasDoneCalled = false;
1519+
let done = () => {
1520+
wasDoneCalled = true;
1521+
};
1522+
1523+
nav._beforeTrans(view1, null, {}, done);
1524+
1525+
expect(wasDoneCalled).toEqual(true);
1526+
expect(view1.state).toEqual(STATE_INACTIVE);
1527+
});
1528+
1529+
it('should not begin transition when entering state is canceled', () => {
1530+
let view1 = new ViewController(Page1);
1531+
view1.state = STATE_CANCEL_ENTER;
1532+
1533+
let wasDoneCalled = false;
1534+
let done = () => {
1535+
wasDoneCalled = true;
1536+
};
1537+
1538+
nav._beforeTrans(view1, null, {}, done);
1539+
1540+
expect(wasDoneCalled).toEqual(true);
1541+
expect(view1.state).toEqual(STATE_CANCEL_ENTER);
1542+
});
14951543
});
14961544

14971545
/* private method */
@@ -1679,12 +1727,13 @@ class MockNavController extends NavController {
16791727
}
16801728

16811729

1682-
const STATE_ACTIVE = 'active';
1683-
const STATE_INACTIVE = 'inactive';
1684-
const STATE_INIT_ENTER = 'init_enter';
1685-
const STATE_INIT_LEAVE = 'init_leave';
1686-
const STATE_TRANS_ENTER = 'trans_enter';
1687-
const STATE_TRANS_LEAVE = 'trans_leave';
1688-
const STATE_REMOVE = 'remove';
1689-
const STATE_REMOVE_AFTER_TRANS = 'remove_after_trans';
1690-
const STATE_FORCE_ACTIVE = 'force_active';
1730+
const STATE_ACTIVE = 1;
1731+
const STATE_INACTIVE = 2;
1732+
const STATE_INIT_ENTER = 3;
1733+
const STATE_INIT_LEAVE = 4;
1734+
const STATE_TRANS_ENTER = 5;
1735+
const STATE_TRANS_LEAVE = 6;
1736+
const STATE_REMOVE = 7;
1737+
const STATE_REMOVE_AFTER_TRANS = 8;
1738+
const STATE_CANCEL_ENTER = 9;
1739+
const STATE_FORCE_ACTIVE = 10;

src/components/nav/view-controller.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export class ViewController {
6666
/**
6767
* @private
6868
*/
69-
state: string = '';
69+
state: number = 0;
7070

7171
/**
7272
* @private

0 commit comments

Comments
 (0)