@@ -4,7 +4,7 @@ import { AnimationOptions } from '../animations/animation';
44import { App } from '../components/app/app' ;
55import { Config } from '../config/config' ;
66import { convertToView , convertToViews , NavOptions , DIRECTION_BACK , DIRECTION_FORWARD , INIT_ZINDEX ,
7- TransitionResolveFn , TransitionRejectFn , TransitionInstruction , ViewState } from './nav-util' ;
7+ TransitionResolveFn , TransitionInstruction , ViewState } from './nav-util' ;
88import { setZIndex } from './nav-util' ;
99import { DeepLinker } from './deep-linker' ;
1010import { GestureController } from '../gestures/gesture-controller' ;
@@ -254,28 +254,40 @@ export class NavControllerBase extends Ion implements NavController {
254254
255255 // there is no transition happening right now
256256 // get the next instruction
257- const ti = this . _queue . shift ( ) ;
257+ const ti = this . _nextTI ( ) ;
258258 if ( ! ti ) {
259- this . setTransitioning ( false ) ;
260259 return false ;
261260 }
262261
263- this . setTransitioning ( true , ACTIVE_TRANSITION_MAX_TIME ) ;
264- const viewsLength = this . _views . length ;
265- const activeView = this . getActive ( ) ;
262+ // Get entering and leaving views
263+ const leavingView = this . getActive ( ) ;
264+ const enteringView = this . _getEnteringView ( ti , leavingView ) ;
266265
267- let enteringView : ViewController ;
268- let leavingView : ViewController = activeView ;
269- const destroyQueue : ViewController [ ] = [ ] ;
266+ // Initialize enteringView
267+ if ( enteringView && isBlank ( enteringView . _state ) ) {
268+ // render the entering view, and all child navs and views
269+ // ******** DOM WRITE ****************
270+ this . _viewInit ( enteringView ) ;
271+ }
270272
271- const opts = ti . opts || { } ;
272- const resolve = ti . resolve ;
273- const reject = ti . reject ;
274- let insertViews = ti . insertViews ;
275- ti . resolve = ti . reject = ti . opts = ti . insertViews = null ;
273+ // Only test canLeave/canEnter if there is transition
274+ let requiresTransition = ( ti . enteringRequiresTransition || ti . leavingRequiresTransition ) && enteringView !== leavingView ;
275+ if ( requiresTransition ) {
276+ // views have been initialized, now let's test
277+ // to see if the transition is even allowed or not
278+ return this . _viewTest ( enteringView , leavingView , ti ) ;
279+
280+ } else {
281+ return this . _postViewInit ( enteringView , leavingView , ti , ti . resolve ) ;
282+ }
283+ }
276284
277- let enteringRequiresTransition = false ;
278- let leavingRequiresTransition = false ;
285+ _nextTI ( ) : TransitionInstruction {
286+ const ti = this . _queue . shift ( ) ;
287+ if ( ! ti ) {
288+ return null ;
289+ }
290+ const viewsLength = this . _views . length ;
279291
280292 if ( isPresent ( ti . removeStart ) ) {
281293 if ( ti . removeStart < 0 ) {
@@ -284,39 +296,59 @@ export class NavControllerBase extends Ion implements NavController {
284296 if ( ti . removeCount < 0 ) {
285297 ti . removeCount = ( viewsLength - ti . removeStart ) ;
286298 }
287-
288- leavingRequiresTransition = ( ti . removeStart + ti . removeCount === viewsLength ) ;
289-
290- for ( var i = 0 ; i < ti . removeCount ; i ++ ) {
291- destroyQueue . push ( this . _views [ i + ti . removeStart ] ) ;
292- }
293-
294- for ( var i = viewsLength - 1 ; i >= 0 ; i -- ) {
295- var view = this . _views [ i ] ;
296- if ( destroyQueue . indexOf ( view ) < 0 && view !== leavingView ) {
297- enteringView = view ;
298- break ;
299- }
300- }
301-
302- // default the direction to "back"
303- opts . direction = opts . direction || DIRECTION_BACK ;
299+ ti . leavingRequiresTransition = ( ( ti . removeStart + ti . removeCount ) === viewsLength ) ;
304300 }
305301
306- if ( insertViews ) {
302+ if ( ti . insertViews ) {
307303 // allow -1 to be passed in to auto push it on the end
308304 // and clean up the index if it's larger then the size of the stack
309305 if ( ti . insertStart < 0 || ti . insertStart > viewsLength ) {
310306 ti . insertStart = viewsLength ;
311307 }
308+ ti . enteringRequiresTransition = ( ti . insertStart === viewsLength ) ;
309+ }
310+ return ti ;
311+ }
312312
313- // only requires a transition if it's going at the end
314- enteringRequiresTransition = ( ti . insertStart === viewsLength ) ;
315-
313+ _getEnteringView ( ti : TransitionInstruction , leavingView : ViewController ) : ViewController {
314+ const insertViews = ti . insertViews ;
315+ if ( insertViews ) {
316316 // grab the very last view of the views to be inserted
317317 // and initialize it as the new entering view
318- enteringView = insertViews [ insertViews . length - 1 ] ;
318+ return insertViews [ insertViews . length - 1 ] ;
319+ }
319320
321+ const removeStart = ti . removeStart ;
322+ if ( isPresent ( removeStart ) ) {
323+ let views = this . _views ;
324+ const removeEnd = removeStart + ti . removeCount ;
325+ for ( var i = views . length - 1 ; i >= 0 ; i -- ) {
326+ var view = views [ i ] ;
327+ if ( ( i < removeStart || i >= removeEnd ) && view !== leavingView ) {
328+ return view ;
329+ }
330+ }
331+ }
332+ return null ;
333+ }
334+
335+ _postViewInit ( enteringView : ViewController , leavingView : ViewController , ti : TransitionInstruction , resolve : TransitionResolveFn ) : boolean {
336+ const opts = ti . opts || { } ;
337+
338+ const insertViews = ti . insertViews ;
339+ const removeStart = ti . removeStart ;
340+
341+ let destroyQueue : ViewController [ ] = [ ] ;
342+
343+ if ( isPresent ( removeStart ) ) {
344+ for ( var i = 0 ; i < ti . removeCount ; i ++ ) {
345+ destroyQueue . push ( this . _views [ i + removeStart ] ) ;
346+ }
347+ // default the direction to "back"
348+ opts . direction = opts . direction || DIRECTION_BACK ;
349+ }
350+
351+ if ( insertViews ) {
320352 // manually set the new view's id if an id was passed in the options
321353 if ( isPresent ( opts . id ) ) {
322354 enteringView . id = opts . id ;
@@ -345,7 +377,7 @@ export class NavControllerBase extends Ion implements NavController {
345377 }
346378 }
347379
348- if ( enteringRequiresTransition ) {
380+ if ( ti . enteringRequiresTransition ) {
349381 // default to forward if not already set
350382 opts . direction = opts . direction || DIRECTION_FORWARD ;
351383 }
@@ -380,7 +412,7 @@ export class NavControllerBase extends Ion implements NavController {
380412 }
381413 destroyQueue . length = 0 ;
382414
383- if ( enteringRequiresTransition || leavingRequiresTransition && enteringView !== leavingView ) {
415+ if ( ti . enteringRequiresTransition || ti . leavingRequiresTransition && enteringView !== leavingView ) {
384416 // set which animation it should use if it wasn't set yet
385417 if ( ! opts . animation ) {
386418 if ( isPresent ( ti . removeStart ) ) {
@@ -391,7 +423,7 @@ export class NavControllerBase extends Ion implements NavController {
391423 }
392424
393425 // huzzah! let us transition these views
394- this . _transition ( enteringView , leavingView , opts , resolve , reject ) ;
426+ this . _transition ( enteringView , leavingView , opts , resolve ) ;
395427
396428 } else {
397429 // they're inserting/removing the views somewhere in the middle or
@@ -403,71 +435,10 @@ export class NavControllerBase extends Ion implements NavController {
403435 return true ;
404436 }
405437
406- _transition ( enteringView : ViewController , leavingView : ViewController , opts : NavOptions , resolve : TransitionResolveFn , reject : TransitionRejectFn ) : void {
407- // figure out if this transition is the root one or a
408- // child of a parent nav that has the root transition
409- this . _trnsId = this . _trnsCtrl . getRootTrnsId ( this ) ;
410- if ( this . _trnsId === null ) {
411- // this is the root transition, meaning all child navs and their views
412- // should be added as a child transition to this one
413- this . _trnsId = this . _trnsCtrl . nextId ( ) ;
414- }
415-
416- // create the transition options
417- const animationOpts : AnimationOptions = {
418- animation : opts . animation ,
419- direction : opts . direction ,
420- duration : ( opts . animate === false ? 0 : opts . duration ) ,
421- easing : opts . easing ,
422- isRTL : this . config . platform . isRTL ( ) ,
423- ev : opts . ev ,
424- } ;
425-
426- // create the transition animation from the TransitionController
427- // this will either create the root transition, or add it as a child transition
428- const trns = this . _trnsCtrl . get ( this . _trnsId , enteringView , leavingView , animationOpts ) ;
429-
430- // ensure any swipeback transitions are cleared out
431- this . _sbTrns && this . _sbTrns . destroy ( ) ;
432-
433- if ( trns . parent ) {
434- // this is important for later to know if there
435- // are any more child tests to check for
436- trns . parent . hasChildTrns = true ;
437-
438- } else {
439- // this is the root transition
440- if ( opts . progressAnimation ) {
441- this . _sbTrns = trns ;
442- }
443- }
444-
445- trns . registerStart ( ( ) => {
446- this . _trnsStart ( trns , enteringView , leavingView , opts , resolve ) ;
447- if ( trns . parent ) {
448- trns . parent . start ( ) ;
449- }
450- } ) ;
451-
452- if ( enteringView && isBlank ( enteringView . _state ) ) {
453- // render the entering view, and all child navs and views
454- // ******** DOM WRITE ****************
455- this . _viewInit ( trns , enteringView , opts ) ;
456- }
457-
458- // views have been initialized, now let's test
459- // to see if the transition is even allowed or not
460- const shouldContinue = this . _viewTest ( trns , enteringView , leavingView , opts , resolve , reject ) ;
461- if ( shouldContinue ) {
462- // synchronous and all tests passed! let's continue
463- this . _postViewInit ( trns , enteringView , leavingView , opts , resolve ) ;
464- }
465- }
466-
467438 /**
468439 * DOM WRITE
469440 */
470- _viewInit ( trns : Transition , enteringView : ViewController , opts : NavOptions ) {
441+ _viewInit ( enteringView : ViewController ) {
471442 // entering view has not been initialized yet
472443 const componentProviders = ReflectiveInjector . resolve ( [
473444 { provide : NavController , useValue : this } ,
@@ -482,8 +453,10 @@ export class NavControllerBase extends Ion implements NavController {
482453 enteringView . _state = ViewState . INITIALIZED ;
483454 }
484455
485- _viewTest ( trns : Transition , enteringView : ViewController , leavingView : ViewController , opts : NavOptions , resolve : TransitionResolveFn , reject : TransitionRejectFn ) : boolean {
456+ _viewTest ( enteringView : ViewController , leavingView : ViewController , ti : TransitionInstruction ) : boolean {
486457 const promises : Promise < any > [ ] = [ ] ;
458+ const reject = ti . reject ;
459+ const resolve = ti . resolve ;
487460
488461 if ( leavingView ) {
489462 const leavingTestResult = leavingView . _lifecycleTest ( 'Leave' ) ;
@@ -495,7 +468,7 @@ export class NavControllerBase extends Ion implements NavController {
495468
496469 } else {
497470 // synchronous reject
498- reject ( ( leavingTestResult !== false ? leavingTestResult : `ionViewCanLeave rejected` ) , trns ) ;
471+ reject ( ( leavingTestResult !== false ? leavingTestResult : `ionViewCanLeave rejected` ) ) ;
499472 return false ;
500473 }
501474 }
@@ -511,7 +484,7 @@ export class NavControllerBase extends Ion implements NavController {
511484
512485 } else {
513486 // synchronous reject
514- reject ( ( enteringTestResult !== false ? enteringTestResult : `ionViewCanEnter rejected` ) , trns ) ;
487+ reject ( ( enteringTestResult !== false ? enteringTestResult : `ionViewCanEnter rejected` ) ) ;
515488 return false ;
516489 }
517490 }
@@ -521,26 +494,67 @@ export class NavControllerBase extends Ion implements NavController {
521494 // darn, async promises, gotta wait for them to resolve
522495 Promise . all ( promises ) . then ( ( ) => {
523496 // all promises resolved! let's continue
524- this . _postViewInit ( trns , enteringView , leavingView , opts , resolve ) ;
525-
526- } , ( rejectReason : any ) => {
527- // darn, one of the promises was rejected!!
528- reject ( rejectReason , trns ) ;
497+ this . _postViewInit ( enteringView , leavingView , ti , resolve ) ;
529498
530499 } ) . catch ( ( rejectReason ) => {
531- // idk, who knows
532- reject ( rejectReason , trns ) ;
500+ reject ( rejectReason ) ;
533501 } ) ;
534502
535503 return false ;
536504 }
537505
538506 // synchronous and all tests passed! let's move on already
507+ this . _postViewInit ( enteringView , leavingView , ti , resolve ) ;
508+
539509 return true ;
540510 }
541511
542- _postViewInit ( trns : Transition , enteringView : ViewController , leavingView : ViewController , opts : NavOptions , resolve : TransitionResolveFn ) : void {
543- // passed both the enter and leave tests
512+ _transition ( enteringView : ViewController , leavingView : ViewController , opts : NavOptions , resolve : TransitionResolveFn ) : void {
513+ // figure out if this transition is the root one or a
514+ // child of a parent nav that has the root transition
515+ this . _trnsId = this . _trnsCtrl . getRootTrnsId ( this ) ;
516+ if ( this . _trnsId === null ) {
517+ // this is the root transition, meaning all child navs and their views
518+ // should be added as a child transition to this one
519+ this . _trnsId = this . _trnsCtrl . nextId ( ) ;
520+ }
521+
522+ // create the transition options
523+ const animationOpts : AnimationOptions = {
524+ animation : opts . animation ,
525+ direction : opts . direction ,
526+ duration : ( opts . animate === false ? 0 : opts . duration ) ,
527+ easing : opts . easing ,
528+ isRTL : this . config . platform . isRTL ( ) ,
529+ ev : opts . ev ,
530+ } ;
531+
532+ // create the transition animation from the TransitionController
533+ // this will either create the root transition, or add it as a child transition
534+ const trns = this . _trnsCtrl . get ( this . _trnsId , enteringView , leavingView , animationOpts ) ;
535+
536+ // ensure any swipeback transitions are cleared out
537+ this . _sbTrns && this . _sbTrns . destroy ( ) ;
538+
539+ if ( trns . parent ) {
540+ // this is important for later to know if there
541+ // are any more child tests to check for
542+ trns . parent . hasChildTrns = true ;
543+
544+ } else {
545+ // this is the root transition
546+ if ( opts . progressAnimation ) {
547+ this . _sbTrns = trns ;
548+ }
549+ }
550+
551+ trns . registerStart ( ( ) => {
552+ this . _trnsStart ( trns , enteringView , leavingView , opts , resolve ) ;
553+ if ( trns . parent ) {
554+ trns . parent . start ( ) ;
555+ }
556+ } ) ;
557+
544558 if ( enteringView && enteringView . _state === ViewState . INITIALIZED ) {
545559 // render the entering component in the DOM
546560 // this would also render new child navs/views
0 commit comments