@@ -32,6 +32,7 @@ registerContextMenu({
32
32
33
33
import { reportStartupEvents } from './report-install-event' ;
34
34
import { menu } from './menu' ;
35
+ import { getDeferred } from './util' ;
35
36
36
37
const rmRF = promisify ( rimraf ) ;
37
38
@@ -141,18 +142,6 @@ if (!amMainInstance) {
141
142
process . exit ( 1 ) ; // Safe to hard exit - we haven't opened/started anything yet.
142
143
}
143
144
144
- app . on ( 'ready' , ( ) => {
145
- Menu . setApplicationMenu ( menu ) ;
146
- } ) ;
147
-
148
- app . on ( 'window-all-closed' , ( ) => {
149
- // On OS X it is common for applications and their menu bar
150
- // to stay active until the user quits explicitly with Cmd + Q
151
- if ( process . platform !== 'darwin' ) {
152
- app . quit ( ) ;
153
- }
154
- } ) ;
155
-
156
145
let serverKilled = false ;
157
146
app . on ( 'will-quit' , ( event ) => {
158
147
if ( server && ! serverKilled ) {
@@ -186,14 +175,6 @@ if (!amMainInstance) {
186
175
}
187
176
} ) ;
188
177
189
- app . on ( 'activate' , ( ) => {
190
- // On OS X it's common to re-create a window in the app when the
191
- // dock icon is clicked and there are no other windows open.
192
- if ( windows . length === 0 ) {
193
- createWindow ( ) ;
194
- }
195
- } ) ;
196
-
197
178
app . on ( 'web-contents-created' , ( _event , contents ) => {
198
179
function injectValue ( name : string , value : string ) {
199
180
// Set a variable globally, and self-postmessage it too (to ping
@@ -400,17 +381,47 @@ if (!amMainInstance) {
400
381
reportStartupEvents ( ) ;
401
382
402
383
cleanupOldServers ( ) . catch ( console . log )
403
- . then ( ( ) => startServer ( ) )
404
- . catch ( ( err ) => {
384
+ . then ( ( ) =>
385
+ startServer ( )
386
+ ) . catch ( ( err ) => {
405
387
console . error ( 'Failed to start server, exiting.' , err ) ;
406
388
407
389
// Hide immediately, shutdown entirely after a brief pause for Sentry
408
390
windows . forEach ( window => window . hide ( ) ) ;
409
391
setTimeout ( ( ) => process . exit ( 1 ) , 500 ) ;
410
392
} ) ;
411
393
412
- app . on ( 'ready' , ( ) => createWindow ( ) ) ;
394
+ // Use a promise to organize events around 'ready', and ensure they never
395
+ // fire before, as Electron will refuse to do various things if they do.
396
+ const appReady = getDeferred ( ) ;
397
+ app . on ( 'ready' , ( ) => appReady . resolve ( ) ) ;
398
+
399
+ appReady . promise . then ( ( ) => {
400
+ Menu . setApplicationMenu ( menu ) ;
401
+ createWindow ( ) ;
402
+ } ) ;
403
+
413
404
// We use a single process instance to manage the server, but we
414
405
// do allow multiple windows.
415
- app . on ( 'second-instance' , ( ) => createWindow ( ) ) ;
406
+ app . on ( 'second-instance' , ( ) =>
407
+ appReady . promise . then ( ( ) => createWindow ( ) )
408
+ ) ;
409
+
410
+ app . on ( 'activate' , ( ) => {
411
+ // On OS X it's common to re-create a window in the app when the
412
+ // dock icon is clicked and there are no other windows open.
413
+ if ( windows . length === 0 ) {
414
+ // Wait until the ready event - it's possible that this can fire
415
+ // before the app is ready (not sure how) in which case things break!
416
+ appReady . promise . then ( ( ) => createWindow ( ) ) ;
417
+ }
418
+ } ) ;
419
+
420
+ app . on ( 'window-all-closed' , ( ) => {
421
+ // On OS X it is common for applications and their menu bar
422
+ // to stay active until the user quits explicitly with Cmd + Q
423
+ if ( process . platform !== 'darwin' ) {
424
+ app . quit ( ) ;
425
+ }
426
+ } ) ;
416
427
}
0 commit comments