@@ -6,7 +6,7 @@ import "./zone-js/dist/zone-nativescript";
6
6
import "reflect-metadata" ;
7
7
import "./polyfills/array" ;
8
8
import "./polyfills/console" ;
9
- import { profile , log , uptime } from "tns-core-modules/profiling" ;
9
+ import { profile , uptime } from "tns-core-modules/profiling" ;
10
10
11
11
import {
12
12
Type ,
@@ -18,27 +18,32 @@ import {
18
18
EventEmitter ,
19
19
Sanitizer ,
20
20
InjectionToken ,
21
- StaticProvider
21
+ StaticProvider ,
22
22
} from "@angular/core" ;
23
23
import { DOCUMENT } from "@angular/common" ;
24
24
25
- import { rendererLog , rendererError } from "./trace" ;
26
- import {
27
- PAGE_FACTORY ,
28
- PageFactory ,
29
- defaultPageFactoryProvider ,
30
- setRootPage
31
- } from "./platform-providers" ;
25
+ import { bootstrapLog , bootstrapLogError } from "./trace" ;
26
+ import { PAGE_FACTORY , PageFactory , defaultPageFactoryProvider , setRootPage } from "./platform-providers" ;
32
27
33
- import { start , setCssFileName } from "tns-core-modules/application" ;
34
- import { topmost , NavigationEntry } from "tns-core-modules/ui/frame" ;
28
+ import {
29
+ setCssFileName ,
30
+ run as applicationRun ,
31
+ on ,
32
+ off ,
33
+ launchEvent ,
34
+ LaunchEventData ,
35
+ ios as iosApp ,
36
+ } from "tns-core-modules/application" ;
37
+ import { NavigationEntry } from "tns-core-modules/ui/frame" ;
35
38
import { Page } from "tns-core-modules/ui/page" ;
39
+ import { ContentView } from "tns-core-modules/ui/content-view" ;
36
40
import { TextView } from "tns-core-modules/ui/text-view" ;
37
41
38
42
import "nativescript-intl" ;
43
+ import { View , Color } from "tns-core-modules/ui/core/view/view" ;
39
44
40
45
export const onBeforeLivesync = new EventEmitter < NgModuleRef < any > > ( ) ;
41
- export const onAfterLivesync = new EventEmitter < NgModuleRef < any > > ( ) ;
46
+ export const onAfterLivesync = new EventEmitter < { moduleRef ?: NgModuleRef < any > ; error ?: Error } > ( ) ;
42
47
let lastBootstrappedModule : WeakRef < NgModuleRef < any > > ;
43
48
type BootstrapperAction = ( ) => Promise < NgModuleRef < any > > ;
44
49
@@ -65,7 +70,7 @@ export class NativeScriptSanitizer extends Sanitizer {
65
70
// Add a fake polyfill for the document object
66
71
( < any > global ) . document = ( < any > global ) . document || { } ;
67
72
const doc = ( < any > global ) . document ;
68
- doc . body = Object . assign ( ( doc . body || { } ) , {
73
+ doc . body = Object . assign ( doc . body || { } , {
69
74
isOverride : true ,
70
75
} ) ;
71
76
@@ -84,7 +89,7 @@ export const COMMON_PROVIDERS = [
84
89
export class NativeScriptPlatformRef extends PlatformRef {
85
90
private _bootstrapper : BootstrapperAction ;
86
91
87
- constructor ( private platform : PlatformRef , private appOptions ? : AppOptions ) {
92
+ constructor ( private platform : PlatformRef , private appOptions : AppOptions = { } ) {
88
93
super ( ) ;
89
94
}
90
95
@@ -101,7 +106,7 @@ export class NativeScriptPlatformRef extends PlatformRef {
101
106
bootstrapModule < M > (
102
107
moduleType : Type < M > ,
103
108
compilerOptions : CompilerOptions | CompilerOptions [ ] = [ ]
104
- ) : Promise < NgModuleRef < M > > {
109
+ ) : Promise < NgModuleRef < M > > {
105
110
this . _bootstrapper = ( ) => this . platform . bootstrapModule ( moduleType , compilerOptions ) ;
106
111
107
112
this . bootstrapApp ( ) ;
@@ -111,39 +116,15 @@ export class NativeScriptPlatformRef extends PlatformRef {
111
116
112
117
@profile
113
118
private bootstrapApp ( ) {
114
- ( < any > global ) . __onLiveSyncCore = ( ) => this . livesyncModule ( ) ;
115
-
116
- const mainPageEntry = this . createNavigationEntry ( this . _bootstrapper ) ;
119
+ ( < any > global ) . __onLiveSyncCore = ( ) => {
120
+ this . livesync ( ) ;
121
+ } ;
117
122
118
123
if ( this . appOptions && typeof this . appOptions . cssFile === "string" ) {
119
- // TODO: All exported fields in ES6 modules should be read-only
120
- // Change the case when tns-core-modules become ES6 compatible and there is a legal way to set cssFile
121
124
setCssFileName ( this . appOptions . cssFile ) ;
122
125
}
123
- start ( mainPageEntry ) ;
124
- }
125
-
126
- livesyncModule ( ) : void {
127
- rendererLog ( "ANGULAR LiveSync Started" ) ;
128
-
129
- onBeforeLivesync . next ( lastBootstrappedModule ? lastBootstrappedModule . get ( ) : null ) ;
130
126
131
- const mainPageEntry = this . createNavigationEntry (
132
- this . _bootstrapper ,
133
- compRef => onAfterLivesync . next ( compRef ) ,
134
- error => onAfterLivesync . error ( error ) ,
135
- true
136
- ) ;
137
- mainPageEntry . animated = false ;
138
- mainPageEntry . clearHistory = true ;
139
-
140
- const frame = topmost ( ) ;
141
- if ( frame ) {
142
- if ( frame . currentPage && frame . currentPage . modal ) {
143
- frame . currentPage . modal . closeModal ( ) ;
144
- }
145
- frame . navigate ( mainPageEntry ) ;
146
- }
127
+ this . bootstrapNativeScriptApp ( ) ;
147
128
}
148
129
149
130
onDestroy ( callback : ( ) => void ) : void {
@@ -163,75 +144,117 @@ export class NativeScriptPlatformRef extends PlatformRef {
163
144
}
164
145
165
146
@profile
166
- private createNavigationEntry (
167
- bootstrapAction : BootstrapperAction ,
168
- resolve ?: ( comp : NgModuleRef < any > ) => void ,
169
- reject ?: ( e : Error ) => void ,
170
- isLivesync : boolean = false ,
171
- isReboot : boolean = false ) : NavigationEntry {
172
-
173
- const pageFactory : PageFactory = this . platform . injector . get ( PAGE_FACTORY ) ;
174
-
175
- const navEntry : NavigationEntry = {
176
- create : ( ) : Page => {
177
- const page = pageFactory ( { isBootstrap : true , isLivesync } ) ;
178
- setRootPage ( page ) ;
179
- if ( this . appOptions ) {
180
- page . actionBarHidden = this . appOptions . startPageActionBarHidden ;
181
- }
182
-
183
- const initHandlerMethodName =
184
- "nativescript-angular/platform-common.initHandler" ;
185
- const initHandler = profile ( initHandlerMethodName , ( ) => {
186
- page . off ( Page . navigatingToEvent , initHandler ) ;
187
- // profiling.stop("application-start");
188
- rendererLog ( "Page loaded" ) ;
189
-
190
- // profiling.start("ng-bootstrap");
191
- rendererLog ( "BOOTSTRAPPING..." ) ;
192
-
193
- const bootstrapMethodName =
194
- "nativescript-angular/platform-common.postBootstrapAction" ;
195
- bootstrapAction ( ) . then ( profile ( bootstrapMethodName , moduleRef => {
196
- // profiling.stop("ng-bootstrap");
197
- log ( `ANGULAR BOOTSTRAP DONE. ${ uptime ( ) } ` ) ;
147
+ private bootstrapNativeScriptApp ( ) {
148
+ // Create a temp page for root of the renderer
149
+ const tempRootView = new RootView ( ) ;
150
+ setRootPage ( < any > tempRootView ) ;
151
+ let rootContent : View ;
152
+
153
+ bootstrapLog ( "NativeScriptPlatform bootstrap started." ) ;
154
+ const launchCallback = profile (
155
+ "nativescript-angular/platform-common.launchCallback" ,
156
+ ( args : LaunchEventData ) => {
157
+ bootstrapLog ( "Application launch event fired" ) ;
158
+ off ( launchEvent , launchCallback ) ;
159
+
160
+ let bootstrapPromiseCompleted = false ;
161
+ this . _bootstrapper ( ) . then (
162
+ moduleRef => {
163
+ bootstrapPromiseCompleted = true ;
164
+
165
+ bootstrapLog ( `Angular bootstrap bootstrap done. uptime: ${ uptime ( ) } ` ) ;
166
+ rootContent = tempRootView . content ;
167
+ tempRootView . content = null ;
168
+ rootContent . parentNode = tempRootView ;
198
169
lastBootstrappedModule = new WeakRef ( moduleRef ) ;
170
+ } ,
171
+ err => {
172
+ bootstrapPromiseCompleted = true ;
199
173
200
- if ( resolve ) {
201
- resolve ( moduleRef ) ;
202
- }
203
- return moduleRef ;
204
- } ) , err => {
205
- rendererError ( "ERROR BOOTSTRAPPING ANGULAR" ) ;
206
174
const errorMessage = err . message + "\n\n" + err . stack ;
207
- rendererError ( errorMessage ) ;
175
+ bootstrapLogError ( "ERROR BOOTSTRAPPING ANGULAR" ) ;
176
+ bootstrapLogError ( errorMessage ) ;
208
177
209
- let view = new TextView ( ) ;
210
- view . text = errorMessage ;
211
- page . content = view ;
178
+ rootContent = this . createErrorUI ( errorMessage ) ;
179
+ }
180
+ ) ;
212
181
213
- if ( reject ) {
214
- reject ( err ) ;
215
- }
216
- } ) ;
182
+ bootstrapLog ( "bootstrapAction called, draining micro tasks queue. Root: " + rootContent ) ;
183
+ ( < any > global ) . Zone . drainMicroTaskQueue ( ) ;
184
+ bootstrapLog ( "bootstrapAction called, draining micro tasks queue finished! Root: " + rootContent ) ;
217
185
218
- ( < any > global ) . Zone . drainMicroTaskQueue ( ) ;
219
- } ) ;
186
+ if ( ! bootstrapPromiseCompleted ) {
187
+ const errorMessage = "Bootstrap promise didn't resolve" ;
188
+ bootstrapLogError ( errorMessage ) ;
189
+ rootContent = this . createErrorUI ( errorMessage ) ;
190
+ }
220
191
221
- page . on ( Page . navigatingToEvent , initHandler ) ;
192
+ args . root = rootContent ;
193
+ }
194
+ ) ;
195
+ on ( launchEvent , launchCallback ) ;
196
+
197
+ applicationRun ( ) ;
198
+ }
199
+
200
+ @profile
201
+ private livesync ( ) {
202
+ bootstrapLog ( "Angular livesync started." ) ;
203
+
204
+ onBeforeLivesync . next ( lastBootstrappedModule ? lastBootstrappedModule . get ( ) : null ) ;
222
205
223
- return page ;
206
+ const tempRootView = new RootView ( ) ;
207
+ setRootPage ( < any > tempRootView ) ;
208
+ let rootContent : View ;
209
+
210
+ let bootstrapPromiseCompleted = false ;
211
+ this . _bootstrapper ( ) . then (
212
+ moduleRef => {
213
+ bootstrapPromiseCompleted = true ;
214
+ bootstrapLog ( "Angular livesync done." ) ;
215
+ onAfterLivesync . next ( { moduleRef } ) ;
216
+
217
+ rootContent = tempRootView . content ;
218
+ tempRootView . content = null ;
219
+ rootContent . parentNode = tempRootView ;
220
+ lastBootstrappedModule = new WeakRef ( moduleRef ) ;
224
221
} ,
225
- animated : false
226
- } ;
222
+ error => {
223
+ bootstrapPromiseCompleted = true ;
224
+ bootstrapLogError ( "ERROR LIVESYNC BOOTSTRAPPING ANGULAR" ) ;
225
+ const errorMessage = error . message + "\n\n" + error . stack ;
226
+ bootstrapLogError ( errorMessage ) ;
227
227
228
- if ( isReboot ) {
229
- navEntry . clearHistory = true ;
228
+ rootContent = this . createErrorUI ( errorMessage ) ;
229
+
230
+ onAfterLivesync . next ( { error } ) ;
231
+ }
232
+ ) ;
233
+
234
+ bootstrapLog ( "livesync bootstrapAction called, draining micro tasks queue. Root: " + rootContent ) ;
235
+ ( < any > global ) . Zone . drainMicroTaskQueue ( ) ;
236
+ bootstrapLog ( "livesync bootstrapAction called, draining micro tasks queue finished! Root: " + rootContent ) ;
237
+
238
+ if ( ! bootstrapPromiseCompleted ) {
239
+ const errorMessage = "Livesync bootstrap promise didn't resolve" ;
240
+ bootstrapLogError ( errorMessage ) ;
241
+ rootContent = this . createErrorUI ( errorMessage ) ;
242
+
243
+ onAfterLivesync . next ( { error : new Error ( errorMessage ) } ) ;
230
244
}
231
245
232
- return navEntry ;
246
+ // TODO: use application._resetRootView method
247
+ if ( iosApp ) {
248
+ ( < any > iosApp ) . setWindowContent ( rootContent ) ;
249
+ }
233
250
}
234
251
235
- liveSyncApp ( ) {
252
+ private createErrorUI ( message : string ) : View {
253
+ const errorTextBox = new TextView ( ) ;
254
+ errorTextBox . text = message ;
255
+ errorTextBox . color = new Color ( "red" ) ;
256
+ return errorTextBox ;
236
257
}
237
258
}
259
+
260
+ class RootView extends ContentView { }
0 commit comments