1
1
import { Injectable } from "@angular/core" ;
2
2
import { LocationStrategy } from "@angular/common" ;
3
+ import { DefaultUrlSerializer , UrlSegmentGroup , UrlTree } from "@angular/router" ;
3
4
import { routerLog } from "../trace" ;
4
5
import { NavigationTransition } from "tns-core-modules/ui/frame" ;
5
6
import { isPresent } from "../lang-facade" ;
@@ -21,12 +22,15 @@ export interface LocationState {
21
22
title : string ;
22
23
url : string ;
23
24
queryParams : string ;
25
+ segmentGroup : UrlSegmentGroup ;
24
26
isPageNavigation : boolean ;
25
27
}
26
28
27
29
@Injectable ( )
28
30
export class NSLocationStrategy extends LocationStrategy {
29
- private states = new Array < LocationState > ( ) ;
31
+ private statesByOutlet : { [ key : string ] : Array < LocationState > } = { } ;
32
+ private currentUrlTree : UrlTree ;
33
+ private currentOutlet : string ;
30
34
private popStateCallbacks = new Array < ( _ : any ) => any > ( ) ;
31
35
32
36
private _isPageNavigationBack = false ;
@@ -38,8 +42,17 @@ export class NSLocationStrategy extends LocationStrategy {
38
42
}
39
43
40
44
path ( ) : string {
41
- let state = this . peekState ( ) ;
42
- const result = state ? state . url : "/" ;
45
+ if ( ! this . currentUrlTree || ! this . currentOutlet ) {
46
+ return "/" ;
47
+ }
48
+
49
+ const state = this . peekState ( this . currentOutlet ) ;
50
+
51
+ this . currentUrlTree . root . children [ this . currentOutlet ] = state . segmentGroup ;
52
+
53
+ const urlSerializer = new DefaultUrlSerializer ( ) ;
54
+ const url = urlSerializer . serialize ( this . currentUrlTree ) ;
55
+ const result = url ;
43
56
routerLog ( "NSLocationStrategy.path(): " + result ) ;
44
57
return result ;
45
58
}
@@ -56,25 +69,55 @@ export class NSLocationStrategy extends LocationStrategy {
56
69
}
57
70
58
71
pushStateInternal ( state : any , title : string , url : string , queryParams : string ) : void {
59
- let isNewPage = this . states . length === 0 ;
60
- this . states . push ( {
61
- state : state ,
62
- title : title ,
63
- url : url ,
64
- queryParams : queryParams ,
65
- isPageNavigation : isNewPage
72
+ const urlSerializer = new DefaultUrlSerializer ( ) ;
73
+ const stateUrlTree : UrlTree = urlSerializer . parse ( url ) ;
74
+ const rootOutlets = stateUrlTree . root . children ;
75
+
76
+ this . currentUrlTree = stateUrlTree ;
77
+
78
+ Object . keys ( rootOutlets ) . forEach ( outletName => {
79
+ const outletStates = this . statesByOutlet [ outletName ] = this . statesByOutlet [ outletName ] || [ ] ;
80
+ const isNewPage = outletStates . length === 0 ;
81
+ const lastState = this . peekState ( outletName ) ;
82
+
83
+ if ( ! lastState || lastState . toString ( ) !== rootOutlets [ outletName ] . toString ( ) ) {
84
+ outletStates . push ( {
85
+ state : state ,
86
+ title : title ,
87
+ url : url ,
88
+ queryParams : queryParams ,
89
+ segmentGroup : rootOutlets [ outletName ] ,
90
+ isPageNavigation : isNewPage
91
+ } ) ;
92
+ }
66
93
} ) ;
67
94
}
68
95
69
96
replaceState ( state : any , title : string , url : string , queryParams : string ) : void {
70
- if ( this . states . length > 0 ) {
97
+ const states = this . statesByOutlet [ this . currentOutlet ] ;
98
+ if ( states && states . length > 0 ) {
71
99
routerLog ( "NSLocationStrategy.replaceState changing existing state: " +
72
100
`${ state } , title: ${ title } , url: ${ url } , queryParams: ${ queryParams } ` ) ;
73
- const topState = this . peekState ( ) ;
74
- topState . state = state ;
75
- topState . title = title ;
76
- topState . url = url ;
77
- topState . queryParams = queryParams ;
101
+
102
+
103
+ // !!!!! In all the e2e tests this method replaces the url with the same url
104
+ // !!!!! making it obsolete. The only scenario is the initial call that is handled
105
+ // !!!!! in the else statement.
106
+
107
+ // const urlSerializer = new DefaultUrlSerializer();
108
+ // const stateUrlTree: UrlTree = urlSerializer.parse(url);
109
+ // const rootOutlets = stateUrlTree.root.children;
110
+
111
+ // Object.keys(rootOutlets).forEach(outletName => {
112
+ // const outletStates = this.statesByOutlet[outletName] = this.statesByOutlet[outletName] || [];
113
+ // const topState = this.peekState(outletName);
114
+
115
+ // topState.segmentGroup = rootOutlets[outletName];
116
+ // topState.state = state;
117
+ // topState.title = title;
118
+ // topState.url = url;
119
+ // topState.queryParams = queryParams;
120
+ // });
78
121
} else {
79
122
routerLog ( "NSLocationStrategy.replaceState pushing new state: " +
80
123
`${ state } , title: ${ title } , url: ${ url } , queryParams: ${ queryParams } ` ) ;
@@ -88,20 +131,21 @@ export class NSLocationStrategy extends LocationStrategy {
88
131
89
132
back ( ) : void {
90
133
if ( this . _isPageNavigationBack ) {
134
+ const states = this . statesByOutlet [ this . currentOutlet ] ;
91
135
// We are navigating to the previous page
92
136
// clear the stack until we get to a page navigation state
93
- let state = this . states . pop ( ) ;
137
+ let state = states . pop ( ) ;
94
138
let count = 1 ;
95
139
96
140
while ( ! ( state . isPageNavigation ) ) {
97
- state = this . states . pop ( ) ;
141
+ state = states . pop ( ) ;
98
142
count ++ ;
99
143
}
100
144
101
145
routerLog ( "NSLocationStrategy.back() while navigating back. States popped: " + count ) ;
102
146
this . callPopState ( state , true ) ;
103
147
} else {
104
- let state = this . peekState ( ) ;
148
+ let state = this . peekState ( this . currentOutlet ) ;
105
149
if ( state . isPageNavigation ) {
106
150
// This was a page navigation - so navigate through frame.
107
151
routerLog ( "NSLocationStrategy.back() while not navigating back but top" +
@@ -112,14 +156,14 @@ export class NSLocationStrategy extends LocationStrategy {
112
156
// Nested navigation - just pop the state
113
157
routerLog ( "NSLocationStrategy.back() while not navigating back but top" +
114
158
" state is not page - just pop" ) ;
115
- this . callPopState ( this . states . pop ( ) , true ) ;
159
+ this . callPopState ( this . statesByOutlet [ this . currentOutlet ] . pop ( ) , true ) ;
116
160
}
117
161
}
118
162
119
163
}
120
164
121
165
canGoBack ( ) {
122
- return this . states . length > 1 ;
166
+ return this . statesByOutlet [ this . currentOutlet ] . length > 1 ;
123
167
}
124
168
125
169
onPopState ( fn : ( _ : any ) => any ) : void {
@@ -133,33 +177,46 @@ export class NSLocationStrategy extends LocationStrategy {
133
177
}
134
178
135
179
private callPopState ( state : LocationState , pop : boolean = true ) {
136
- const change = { url : state . url , pop : pop } ;
180
+ const urlSerializer = new DefaultUrlSerializer ( ) ;
181
+ const url = urlSerializer . serialize ( this . currentUrlTree ) ;
182
+ const change = { url : url , pop : pop } ;
137
183
for ( let fn of this . popStateCallbacks ) {
138
184
fn ( change ) ;
139
185
}
140
186
}
141
187
142
- private peekState ( ) : LocationState {
143
- if ( this . states . length > 0 ) {
144
- return this . states [ this . states . length - 1 ] ;
188
+ private peekState ( name : string ) {
189
+ const states = this . statesByOutlet [ name ] || [ ] ;
190
+ if ( states . length > 0 ) {
191
+ return states [ states . length - 1 ] ;
145
192
}
146
193
return null ;
147
194
}
148
195
149
196
public toString ( ) {
150
- return this . states
151
- . map ( ( v , i ) => `${ i } .[${ v . isPageNavigation ? "PAGE" : "INTERNAL" } ] "${ v . url } "` )
152
- . reverse ( )
153
- . join ( "\n" ) ;
197
+ let result = [ ] ;
198
+
199
+ Object . keys ( this . statesByOutlet ) . forEach ( outletName => {
200
+ const outletStates = this . statesByOutlet [ outletName ] ;
201
+ const outletLog = outletStates
202
+ . map ( ( v , i ) => `${ i } .[${ v . isPageNavigation ? "PAGE" : "INTERNAL" } ] "${ v . segmentGroup . toString ( ) } "` )
203
+ . reverse ( ) ;
204
+
205
+ result . push ( `${ outletName } :` ) ;
206
+ result = result . concat ( result , outletLog ) ;
207
+ } ) ;
208
+
209
+ return result . join ( "\n" ) ;
154
210
}
155
211
156
212
// Methods for syncing with page navigation in PageRouterOutlet
157
- public _beginBackPageNavigation ( ) {
213
+ public _beginBackPageNavigation ( name : string ) {
158
214
routerLog ( "NSLocationStrategy.startGoBack()" ) ;
159
215
if ( this . _isPageNavigationBack ) {
160
216
throw new Error ( "Calling startGoBack while going back." ) ;
161
217
}
162
218
this . _isPageNavigationBack = true ;
219
+ this . currentOutlet = name ;
163
220
}
164
221
165
222
public _finishBackPageNavigation ( ) {
@@ -174,17 +231,19 @@ export class NSLocationStrategy extends LocationStrategy {
174
231
return this . _isPageNavigationBack ;
175
232
}
176
233
177
- public _beginPageNavigation ( ) : NavigationOptions {
234
+ public _beginPageNavigation ( name : string ) : NavigationOptions {
178
235
routerLog ( "NSLocationStrategy._beginPageNavigation()" ) ;
179
- const lastState = this . peekState ( ) ;
236
+ const lastState = this . peekState ( name ) ;
180
237
if ( lastState ) {
181
238
lastState . isPageNavigation = true ;
182
239
}
183
240
241
+ this . currentOutlet = name ;
242
+
184
243
const navOptions = this . _currentNavigationOptions || defaultNavOptions ;
185
244
if ( navOptions . clearHistory ) {
186
245
routerLog ( "NSLocationStrategy._beginPageNavigation clearing states history" ) ;
187
- this . states = [ lastState ] ;
246
+ this . statesByOutlet [ name ] = [ lastState ] ;
188
247
}
189
248
190
249
this . _currentNavigationOptions = undefined ;
@@ -201,7 +260,7 @@ export class NSLocationStrategy extends LocationStrategy {
201
260
`${ JSON . stringify ( this . _currentNavigationOptions ) } )` ) ;
202
261
}
203
262
204
- public _getStates ( ) : Array < LocationState > {
205
- return this . states . slice ( ) ;
263
+ public _getStates ( ) : { [ key : string ] : Array < LocationState > } {
264
+ return this . statesByOutlet ;
206
265
}
207
266
}
0 commit comments