@@ -3,22 +3,39 @@ import { app, BrowserWindow, BrowserWindowConstructorOptions, ipcMain, screen }
33import { fork } from 'child_process' ;
44import { AddressInfo } from 'net' ;
55import { join } from 'path' ;
6+ import * as fs from 'fs-extra' ;
67import { initSplashScreen } from '../splash/splash-screen' ;
78import { MaybePromise } from '@theia/core/lib/common/types' ;
89import { ElectronSecurityToken } from '@theia/core/lib/electron-common/electron-token' ;
910import { FrontendApplicationConfig } from '@theia/application-package/lib/application-props' ;
1011import {
1112 ElectronMainApplication as TheiaElectronMainApplication ,
13+ ElectronMainExecutionParams ,
1214 TheiaBrowserWindowOptions ,
1315} from '@theia/core/lib/electron-main/electron-main-application' ;
1416import { SplashServiceImpl } from '../splash/splash-service-impl' ;
17+ import { URI } from '@theia/core/shared/vscode-uri' ;
1518import * as electronRemoteMain from '@theia/core/electron-shared/@electron/remote/main' ;
1619
1720app . commandLine . appendSwitch ( 'disable-http-cache' ) ;
1821
22+ interface WorkspaceOptions {
23+ file : string
24+ x : number
25+ y : number
26+ width : number
27+ height : number
28+ isMaximized : boolean
29+ isFullScreen : boolean
30+ time : number
31+ }
32+ 33+ const WORKSPACES = 'workspaces' ;
34+ 1935@injectable ( )
2036export class ElectronMainApplication extends TheiaElectronMainApplication {
2137 protected _windows : BrowserWindow [ ] = [ ] ;
38+ protected startup = false ;
2239
2340 @inject ( SplashServiceImpl )
2441 protected readonly splashService : SplashServiceImpl ;
@@ -31,6 +48,45 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
3148 return super . start ( config ) ;
3249 }
3350
51+ protected async launch ( params : ElectronMainExecutionParams ) : Promise < void > {
52+ this . startup = true ;
53+ const workspaces : WorkspaceOptions [ ] | undefined = this . electronStore . get ( WORKSPACES ) ;
54+ let useDefault = true ;
55+ if ( workspaces && workspaces . length > 0 ) {
56+ for ( const workspace of workspaces ) {
57+ const file = workspace . file ;
58+ if ( typeof file === 'string' && await fs . pathExists ( file ) ) {
59+ useDefault = false ;
60+ await this . openSketch ( workspace ) ;
61+ }
62+ }
63+ }
64+ this . startup = false ;
65+ if ( useDefault ) {
66+ super . launch ( params ) ;
67+ }
68+ }
69+ 70+ protected async openSketch ( workspace : WorkspaceOptions ) : Promise < BrowserWindow > {
71+ const options = await this . getLastWindowOptions ( ) ;
72+ options . x = workspace . x ;
73+ options . y = workspace . y ;
74+ options . width = workspace . width ;
75+ options . height = workspace . height ;
76+ options . isMaximized = workspace . isMaximized ;
77+ options . isFullScreen = workspace . isFullScreen ;
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 ( this . startup ) {
85+ return options ;
86+ }
87+ return super . avoidOverlap ( options ) ;
88+ }
89+ 3490 protected getTitleBarStyle ( ) : 'native' | 'custom' {
3591 return 'native' ;
3692 }
@@ -143,6 +199,7 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
143199 }
144200 }
145201 } ) ;
202+ this . attachClosedWorkspace ( electronWindow ) ;
146203 this . attachReadyToShow ( electronWindow ) ;
147204 this . attachSaveWindowState ( electronWindow ) ;
148205 this . attachGlobalShortcuts ( electronWindow ) ;
@@ -214,6 +271,44 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
214271 }
215272 }
216273
274+ protected closedWorkspaces : WorkspaceOptions [ ] = [ ] ;
275+ 276+ protected attachClosedWorkspace ( window : BrowserWindow ) : void {
277+ // Since the `before-quit` event is only fired when closing the *last* window
278+ // We need to keep track of recently closed windows/workspaces manually
279+ window . on ( 'close' , ( ) => {
280+ const url = window . webContents . getURL ( ) ;
281+ const workspace = URI . parse ( url ) . fragment ;
282+ if ( workspace ) {
283+ const workspaceUri = URI . file ( workspace ) ;
284+ const bounds = window . getNormalBounds ( ) ;
285+ this . closedWorkspaces . push ( {
286+ ...bounds ,
287+ isMaximized : window . isMaximized ( ) ,
288+ isFullScreen : window . isFullScreen ( ) ,
289+ file : workspaceUri . fsPath ,
290+ time : Date . now ( )
291+ } )
292+ }
293+ } ) ;
294+ }
295+ 296+ protected onWillQuit ( event : Electron . Event ) : void {
297+ // Only add workspaces which were closed within the last second (1000 milliseconds)
298+ const threshold = Date . now ( ) - 1000 ;
299+ const visited = new Set < string > ( ) ;
300+ const workspaces = this . closedWorkspaces . filter ( e => {
301+ if ( e . time < threshold || visited . has ( e . file ) ) {
302+ return false ;
303+ }
304+ visited . add ( e . file ) ;
305+ return true ;
306+ } ) . sort ( ( a , b ) => a . file . localeCompare ( b . file ) ) ;
307+ this . electronStore . set ( WORKSPACES , workspaces ) ;
308+ 309+ super . onWillQuit ( event ) ;
310+ }
311+ 217312 get windows ( ) : BrowserWindow [ ] {
218313 return this . _windows . slice ( ) ;
219314 }
0 commit comments