1
1
import { Location } from '@angular/common' ;
2
2
import { ComponentRef , NgZone } from '@angular/core' ;
3
3
import { ActivatedRoute , Router } from '@angular/router' ;
4
- import { AnimationBuilder , RouterDirection } from '@ionic/core' ;
4
+ import { AnimationBuilder , NavDirection , RouterDirection } from '@ionic/core' ;
5
5
6
6
import { bindLifecycleEvents } from '../../providers/angular-delegate' ;
7
7
import { NavController } from '../../providers/nav-controller' ;
@@ -62,14 +62,8 @@ export class StackController {
62
62
}
63
63
64
64
setActive ( enteringView : RouteView ) : Promise < StackDidChangeEvent > {
65
- const consumeResult = this . navCtrl . consumeTransition ( ) ;
65
+ const { isDirectionBasedOnNavigationIds , ... consumeResult } = this . navCtrl . consumeTransition ( ) ;
66
66
let { direction, animation, animationBuilder } = consumeResult ;
67
- const leavingView = this . activeView ;
68
- const tabSwitch = isTabSwitch ( enteringView , leavingView ) ;
69
- if ( tabSwitch ) {
70
- direction = 'back' ;
71
- animation = undefined ;
72
- }
73
67
74
68
const viewsSnapshot = this . views . slice ( ) ;
75
69
@@ -87,25 +81,65 @@ export class StackController {
87
81
}
88
82
89
83
/**
90
- * If the navigation action
91
- * sets `replaceUrl: true`
92
- * then we need to make sure
93
- * we remove the last item
94
- * from our views stack
84
+ * If the navigation action sets `replaceUrl: true` then we need to make sure
85
+ * we remove the last item from our views stack
95
86
*/
96
- if ( currentNavigation ?. extras ?. replaceUrl ) {
87
+ if ( currentNavigation ?. extras ?. replaceUrl && currentNavigation ?. trigger !== 'popstate' ) {
97
88
if ( this . views . length > 0 ) {
98
89
this . views . splice ( - 1 , 1 ) ;
99
90
}
100
91
}
101
92
102
- const reused = this . views . includes ( enteringView ) ;
93
+ // determine direction based on the order of the views in the stack
94
+ const leavingView = this . activeView ;
95
+ const isEnteringViewReused = this . views . includes ( enteringView ) ;
96
+ const leavingViewIndex = leavingView ? this . views . indexOf ( leavingView ) : - 1 ;
97
+ const enteringViewIndex = isEnteringViewReused ? this . views . indexOf ( enteringView ) : this . views . length ;
98
+ const suggestedDirectionBasedOnStackOrder : NavDirection | undefined =
99
+ leavingViewIndex === - 1 ? undefined : enteringViewIndex < leavingViewIndex ? 'back' : 'forward' ;
100
+
101
+ /**
102
+ * The user triggered a back navigation on a page that was navigated to with root. In this case, the new page
103
+ * becomes the root and the leavingView is removed.
104
+ *
105
+ * This can happen when e.g.:
106
+ * - using the NavController's navigateBack on a root page
107
+ * - navigating to a page with navigateRoot and then using the browser back button
108
+ */
109
+ if (
110
+ direction === 'back' &&
111
+ isDirectionBasedOnNavigationIds &&
112
+ leavingView ?. root &&
113
+ currentNavigation ?. trigger === 'popstate'
114
+ ) {
115
+ if ( leavingViewIndex >= 0 ) {
116
+ this . views . splice ( leavingViewIndex , 1 ) ;
117
+ }
118
+ }
119
+
120
+ /**
121
+ * direction based on stack order takes precedence over direction based on navigation ids
122
+ *
123
+ * only applied if the user did not explicitly set the direction
124
+ * (e.g. via the NavController, routerLink directive etc.)
125
+ */
126
+ if ( isDirectionBasedOnNavigationIds && suggestedDirectionBasedOnStackOrder ) {
127
+ direction = suggestedDirectionBasedOnStackOrder ;
128
+ animation = suggestedDirectionBasedOnStackOrder ;
129
+ }
130
+
131
+ const tabSwitch = isTabSwitch ( enteringView , leavingView ) ;
132
+ if ( tabSwitch ) {
133
+ direction = 'back' ;
134
+ animation = undefined ;
135
+ }
136
+
103
137
const views = this . insertView ( enteringView , direction ) ;
104
138
105
139
// Trigger change detection before transition starts
106
140
// This will call ngOnInit() the first time too, just after the view
107
141
// was attached to the dom, but BEFORE the transition starts
108
- if ( ! reused ) {
142
+ if ( ! isEnteringViewReused ) {
109
143
enteringView . ref . changeDetectorRef . detectChanges ( ) ;
110
144
}
111
145
0 commit comments