@@ -18,7 +18,7 @@ import {
18
18
import { AnimationBuilder } from '@ionic/vue' ;
19
19
20
20
export const createIonRouter = ( opts : IonicVueRouterOptions , router : Router ) => {
21
- let currentNavigationInfo : NavigationInformation = { direction : undefined , action : undefined } ;
21
+ let currentNavigationInfo : NavigationInformation = { direction : undefined , action : undefined , delta : undefined } ;
22
22
23
23
/**
24
24
* Ionic Vue should only react to navigation
@@ -32,7 +32,7 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
32
32
router . afterEach ( ( to : RouteLocationNormalized , _ : RouteLocationNormalized , failure ?: NavigationFailure ) => {
33
33
if ( failure ) return ;
34
34
35
- const { direction, action } = currentNavigationInfo ;
35
+ const { direction, action, delta } = currentNavigationInfo ;
36
36
37
37
/**
38
38
* When calling router.replace, we are not informed
@@ -42,13 +42,26 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
42
42
* We need to use opts.history rather than window.history
43
43
* because window.history will be undefined when using SSR.
44
44
*/
45
+
46
+ currentHistoryPosition = opts . history . state . position as number ;
47
+
45
48
const replaceAction = opts . history . state . replaced ? 'replace' : undefined ;
46
- handleHistoryChange ( to , action || replaceAction , direction ) ;
49
+ handleHistoryChange ( to , action || replaceAction , direction , delta ) ;
47
50
48
- currentNavigationInfo = { direction : undefined , action : undefined } ;
51
+ currentNavigationInfo = { direction : undefined , action : undefined , delta : undefined } ;
49
52
} ) ;
50
53
51
54
const locationHistory = createLocationHistory ( ) ;
55
+
56
+ /**
57
+ * Keeping track of the history position
58
+ * allows us to determine if a user is pushing
59
+ * new pages or updating history via the forward
60
+ * and back browser buttons.
61
+ */
62
+ const initialHistoryPosition = opts . history . state . position as number ;
63
+ let currentHistoryPosition = opts . history . state . position as number ;
64
+
52
65
let currentRouteInfo : RouteInfo ;
53
66
let incomingRouteParams : RouteParams ;
54
67
let currentTab : string | undefined ;
@@ -78,14 +91,21 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
78
91
* router.beforeEach
79
92
*/
80
93
currentNavigationInfo = {
81
- action : info . type ,
94
+ delta : info . delta ,
95
+
96
+ /**
97
+ * Both the browser forward and backward actions
98
+ * are considered "pop" actions, but when going forward
99
+ * we want to make sure the forward animation is used.
100
+ */
101
+ action : ( info . type === 'pop' && info . delta >= 1 ) ? 'push' : info . type ,
82
102
direction : info . direction === '' ? 'forward' : info . direction
83
103
} ;
84
104
} ) ;
85
105
86
106
const handleNavigateBack = ( defaultHref ?: string , routerAnimation ?: AnimationBuilder ) => {
87
107
// todo grab default back button href from config
88
- const routeInfo = locationHistory . current ( ) ;
108
+ const routeInfo = locationHistory . current ( initialHistoryPosition , currentHistoryPosition ) ;
89
109
if ( routeInfo && routeInfo . pushedByRoute ) {
90
110
const prevInfo = locationHistory . findLastLocation ( routeInfo ) ;
91
111
if ( prevInfo ) {
@@ -131,16 +151,23 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
131
151
}
132
152
133
153
// TODO RouteLocationNormalized
134
- const handleHistoryChange = ( location : any , action ?: RouteAction , direction ?: RouteDirection ) => {
154
+ const handleHistoryChange = (
155
+ location : any ,
156
+ action ?: RouteAction ,
157
+ direction ?: RouteDirection ,
158
+ delta ?: number
159
+ ) => {
135
160
let leavingLocationInfo : RouteInfo ;
136
161
if ( incomingRouteParams ) {
137
162
if ( incomingRouteParams . routerAction === 'replace' ) {
138
163
leavingLocationInfo = locationHistory . previous ( ) ;
164
+ } else if ( incomingRouteParams . routerAction === 'pop' ) {
165
+ leavingLocationInfo = locationHistory . current ( initialHistoryPosition , currentHistoryPosition + 1 ) ;
139
166
} else {
140
- leavingLocationInfo = locationHistory . current ( ) ;
167
+ leavingLocationInfo = locationHistory . current ( initialHistoryPosition , currentHistoryPosition - 1 ) ;
141
168
}
142
169
} else {
143
- leavingLocationInfo = locationHistory . current ( ) ;
170
+ leavingLocationInfo = currentRouteInfo ;
144
171
}
145
172
146
173
if ( ! leavingLocationInfo ) {
@@ -160,9 +187,10 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
160
187
tab : currentTab
161
188
}
162
189
} else if ( action === 'pop' ) {
163
- const routeInfo = locationHistory . current ( ) ;
190
+ const routeInfo = locationHistory . current ( initialHistoryPosition , currentHistoryPosition - delta ) ;
191
+
164
192
if ( routeInfo && routeInfo . pushedByRoute ) {
165
- const prevRouteInfo = locationHistory . findLastLocation ( routeInfo ) ;
193
+ const prevRouteInfo = locationHistory . findLastLocation ( routeInfo , delta ) ;
166
194
incomingRouteParams = {
167
195
...prevRouteInfo ,
168
196
routerAction : 'pop' ,
@@ -191,7 +219,6 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
191
219
...incomingRouteParams ,
192
220
lastPathname : leavingLocationInfo . pathname
193
221
}
194
- locationHistory . add ( routeInfo ) ;
195
222
196
223
} else {
197
224
const isPushed = incomingRouteParams . routerAction === 'push' && incomingRouteParams . routerDirection === 'forward' ;
@@ -215,7 +242,7 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
215
242
const lastRoute = locationHistory . getCurrentRouteInfoForTab ( routeInfo . tab ) ;
216
243
routeInfo . pushedByRoute = lastRoute ?. pushedByRoute ;
217
244
} else if ( routeInfo . routerAction === 'replace' ) {
218
- const currentRouteInfo = locationHistory . current ( ) ;
245
+ const currentRouteInfo = locationHistory . last ( ) ;
219
246
220
247
/**
221
248
* If going from /home to /child, then replacing from
@@ -232,8 +259,27 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
232
259
routeInfo . prevRouteLastPathname = currentRouteInfo ?. lastPathname ;
233
260
}
234
261
262
+ }
263
+
264
+ routeInfo . position = currentHistoryPosition ;
265
+ const historySize = locationHistory . size ( ) ;
266
+ const historyDiff = currentHistoryPosition - initialHistoryPosition ;
267
+
268
+ /**
269
+ * If the size of location history is greater
270
+ * than the difference between the current history
271
+ * position and the initial history position
272
+ * then we are guaranteed to already have a history
273
+ * item for this route. In other words, a user
274
+ * is navigating within the history without pushing
275
+ * new items within the stack.
276
+ */
277
+ if ( historySize > historyDiff && routeInfo . tab === undefined ) {
278
+ locationHistory . updateByHistoryPosition ( routeInfo ) ;
279
+ } else {
235
280
locationHistory . add ( routeInfo ) ;
236
281
}
282
+
237
283
currentRouteInfo = routeInfo ;
238
284
}
239
285
incomingRouteParams = undefined ;
@@ -301,7 +347,7 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
301
347
const handleSetCurrentTab = ( tab : string ) => {
302
348
currentTab = tab ;
303
349
304
- const ri = { ...locationHistory . current ( ) } ;
350
+ const ri = { ...locationHistory . last ( ) } ;
305
351
if ( ri . tab !== tab ) {
306
352
ri . tab = tab ;
307
353
locationHistory . update ( ri ) ;
@@ -313,7 +359,12 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
313
359
historyChangeListeners . push ( cb ) ;
314
360
}
315
361
362
+ const getLeavingRouteInfo = ( ) => {
363
+ return locationHistory . current ( initialHistoryPosition , currentHistoryPosition ) ;
364
+ }
365
+
316
366
return {
367
+ getLeavingRouteInfo,
317
368
handleNavigateBack,
318
369
handleSetCurrentTab,
319
370
getCurrentRouteInfo,
0 commit comments