Skip to content

Commit 6c749f6

Browse files
committed
Open all closed workspaces on startup
1 parent 1d88263 commit 6c749f6

File tree

2 files changed

+92
-8
lines changed

2 files changed

+92
-8
lines changed

Diff for: arduino-ide-extension/src/browser/arduino-workspace-resolver.ts

+3-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { toUnix } from 'upath';
2-
import URI from '@theia/core/lib/common/uri';
1+
import { URI } from '@theia/core/shared/vscode-uri';
32
import { isWindows } from '@theia/core/lib/common/os';
43
import { notEmpty } from '@theia/core/lib/common/objects';
54
import { MaybePromise } from '@theia/core/lib/common/types';
@@ -61,12 +60,8 @@ export class ArduinoWorkspaceRootResolver {
6160
// - https://github.com/eclipse-theia/theia/blob/8196e9dcf9c8de8ea0910efeb5334a974f426966/packages/workspace/src/browser/workspace-service.ts#L423
6261
protected hashToUri(hash: string | undefined): string | undefined {
6362
if (hash && hash.length > 1 && hash.startsWith('#')) {
64-
const path = hash.slice(1); // Trim the leading `#`.
65-
return new URI(
66-
toUnix(path.slice(isWindows && hash.startsWith('/') ? 1 : 0))
67-
)
68-
.withScheme('file')
69-
.toString();
63+
const path = decodeURI(hash.slice(1)).replace(/\\/g, '/'); // Trim the leading `#`, decode the URI and replace Windows separators
64+
return URI.file(path.slice(isWindows && hash.startsWith('/') ? 1 : 0)).toString();
7065
}
7166
return undefined;
7267
}

Diff for: arduino-ide-extension/src/electron-main/theia/electron-main-application.ts

+89
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,34 @@ import {
88
import { fork } from 'child_process';
99
import { AddressInfo } from 'net';
1010
import { join } from 'path';
11+
import * as fs from 'fs-extra';
1112
import { initSplashScreen } from '../splash/splash-screen';
1213
import { MaybePromise } from '@theia/core/lib/common/types';
1314
import { ElectronSecurityToken } from '@theia/core/lib/electron-common/electron-token';
1415
import { FrontendApplicationConfig } from '@theia/application-package/lib/application-props';
1516
import {
1617
ElectronMainApplication as TheiaElectronMainApplication,
18+
ElectronMainExecutionParams,
1719
TheiaBrowserWindowOptions,
1820
} from '@theia/core/lib/electron-main/electron-main-application';
1921
import { SplashServiceImpl } from '../splash/splash-service-impl';
2022
import { ipcMain } from '@theia/core/shared/electron';
23+
import { URI } from '@theia/core/shared/vscode-uri';
2124

2225
app.commandLine.appendSwitch('disable-http-cache');
2326

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+
2439
@injectable()
2540
export class ElectronMainApplication extends TheiaElectronMainApplication {
2641
protected _windows: BrowserWindow[] = [];
@@ -36,6 +51,42 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
3651
return super.start(config);
3752
}
3853

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+
3990
protected getTitleBarStyle(): 'native' | 'custom' {
4091
return 'native';
4192
}
@@ -148,6 +199,7 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
148199
}
149200
}
150201
});
202+
this.attachClosedWorkspace(electronWindow);
151203
this.attachReadyToShow(electronWindow);
152204
this.attachSaveWindowState(electronWindow);
153205
this.attachGlobalShortcuts(electronWindow);
@@ -218,6 +270,43 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
218270
}
219271
}
220272

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+
221310
get windows(): BrowserWindow[] {
222311
return this._windows.slice();
223312
}

0 commit comments

Comments
 (0)