@@ -8,19 +8,34 @@ import {
8
8
import { fork } from 'child_process' ;
9
9
import { AddressInfo } from 'net' ;
10
10
import { join } from 'path' ;
11
+ import * as fs from 'fs-extra' ;
11
12
import { initSplashScreen } from '../splash/splash-screen' ;
12
13
import { MaybePromise } from '@theia/core/lib/common/types' ;
13
14
import { ElectronSecurityToken } from '@theia/core/lib/electron-common/electron-token' ;
14
15
import { FrontendApplicationConfig } from '@theia/application-package/lib/application-props' ;
15
16
import {
16
17
ElectronMainApplication as TheiaElectronMainApplication ,
18
+ ElectronMainExecutionParams ,
17
19
TheiaBrowserWindowOptions ,
18
20
} from '@theia/core/lib/electron-main/electron-main-application' ;
19
21
import { SplashServiceImpl } from '../splash/splash-service-impl' ;
20
22
import { ipcMain } from '@theia/core/shared/electron' ;
23
+ import { URI } from '@theia/core/shared/vscode-uri' ;
21
24
22
25
app . commandLine . appendSwitch ( 'disable-http-cache' ) ;
23
26
27
+ interface WorkspaceOptions {
28
+ file : string
29
+ x : number
30
+ y : number
31
+ width : number
32
+ height : number
33
+ isMaximized : boolean
34
+ time : number
35
+ }
36
+
37
+ const WORKSPACES = 'workspaces' ;
38
+
24
39
@injectable ( )
25
40
export class ElectronMainApplication extends TheiaElectronMainApplication {
26
41
protected _windows : BrowserWindow [ ] = [ ] ;
@@ -36,6 +51,42 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
36
51
return super . start ( config ) ;
37
52
}
38
53
54
+ protected async launch ( params : ElectronMainExecutionParams ) : Promise < void > {
55
+ const workspaces : WorkspaceOptions [ ] | undefined = this . electronStore . get ( WORKSPACES ) ;
56
+ let useDefault = true ;
57
+ if ( workspaces && workspaces . length > 0 ) {
58
+ for ( const workspace of workspaces ) {
59
+ const file = workspace . file ;
60
+ if ( typeof file === 'string' && await fs . pathExists ( file ) ) {
61
+ useDefault = false ;
62
+ await this . openSketch ( workspace ) ;
63
+ }
64
+ }
65
+ }
66
+ if ( useDefault ) {
67
+ super . launch ( params ) ;
68
+ }
69
+ }
70
+
71
+ protected async openSketch ( workspace : WorkspaceOptions ) : Promise < BrowserWindow > {
72
+ const options = await this . getLastWindowOptions ( ) ;
73
+ options . x = workspace . x ;
74
+ options . y = workspace . y ;
75
+ options . width = workspace . width ;
76
+ options . height = workspace . height ;
77
+ options . isMaximized = workspace . isMaximized ;
78
+ const [ uri , electronWindow ] = await Promise . all ( [ this . createWindowUri ( ) , this . createWindow ( options ) ] ) ;
79
+ electronWindow . loadURL ( uri . withFragment ( encodeURI ( workspace . file ) ) . toString ( true ) ) ;
80
+ return electronWindow ;
81
+ }
82
+
83
+ protected avoidOverlap ( options : TheiaBrowserWindowOptions ) : TheiaBrowserWindowOptions {
84
+ if ( options . isMaximized ) {
85
+ return options ;
86
+ }
87
+ return super . avoidOverlap ( options ) ;
88
+ }
89
+
39
90
protected getTitleBarStyle ( ) : 'native' | 'custom' {
40
91
return 'native' ;
41
92
}
@@ -148,6 +199,7 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
148
199
}
149
200
}
150
201
} ) ;
202
+ this . attachClosedWorkspace ( electronWindow ) ;
151
203
this . attachReadyToShow ( electronWindow ) ;
152
204
this . attachSaveWindowState ( electronWindow ) ;
153
205
this . attachGlobalShortcuts ( electronWindow ) ;
@@ -218,6 +270,43 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
218
270
}
219
271
}
220
272
273
+ protected closedWorkspaces : WorkspaceOptions [ ] = [ ] ;
274
+
275
+ protected attachClosedWorkspace ( window : BrowserWindow ) : void {
276
+ // Since the `before-quit` event is only fired when closing the *last* window
277
+ // We need to keep track of recently closed windows/workspaces manually
278
+ window . on ( 'close' , ( ) => {
279
+ const url = window . webContents . getURL ( ) ;
280
+ const workspace = URI . parse ( url ) . fragment ;
281
+ if ( workspace ) {
282
+ const workspaceUri = URI . file ( workspace ) ;
283
+ const bounds = window . getNormalBounds ( ) ;
284
+ this . closedWorkspaces . push ( {
285
+ ...bounds ,
286
+ isMaximized : window . isMaximized ( ) ,
287
+ file : workspaceUri . fsPath ,
288
+ time : Date . now ( )
289
+ } )
290
+ }
291
+ } ) ;
292
+ }
293
+
294
+ protected onWillQuit ( event : Electron . Event ) : void {
295
+ // Only add workspaces which were closed within the last second (1000 milliseconds)
296
+ const threshold = Date . now ( ) - 1000 ;
297
+ const visited = new Set < string > ( ) ;
298
+ const workspaces = this . closedWorkspaces . filter ( e => {
299
+ if ( e . time < threshold || visited . has ( e . file ) ) {
300
+ return false ;
301
+ }
302
+ visited . add ( e . file ) ;
303
+ return true ;
304
+ } ) . sort ( ( a , b ) => a . file . localeCompare ( b . file ) ) ;
305
+ this . electronStore . set ( WORKSPACES , workspaces ) ;
306
+
307
+ super . onWillQuit ( event ) ;
308
+ }
309
+
221
310
get windows ( ) : BrowserWindow [ ] {
222
311
return this . _windows . slice ( ) ;
223
312
}
0 commit comments