Skip to content

Commit 97d15f7

Browse files
committed
Merge remote-tracking branch 'origin/main' into msujew/theia-update-1.22
# Conflicts: # arduino-ide-extension/src/electron-main/theia/electron-main-application.ts
2 parents 4775259 + 69ac1f4 commit 97d15f7

File tree

3 files changed

+100
-9
lines changed

3 files changed

+100
-9
lines changed

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
}

arduino-ide-extension/src/browser/boards/boards-service-provider.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,8 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
230230
)) {
231231
if (
232232
this.latestValidBoardsConfig.selectedBoard.fqbn === board.fqbn &&
233-
this.latestValidBoardsConfig.selectedBoard.name === board.name
233+
this.latestValidBoardsConfig.selectedBoard.name === board.name &&
234+
this.latestValidBoardsConfig.selectedPort.protocol === board.port?.protocol
234235
) {
235236
this.boardsConfig = {
236237
...this.latestValidBoardsConfig,

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

+95
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,39 @@ import { app, BrowserWindow, BrowserWindowConstructorOptions, ipcMain, screen }
33
import { fork } from 'child_process';
44
import { AddressInfo } from 'net';
55
import { join } from 'path';
6+
import * as fs from 'fs-extra';
67
import { initSplashScreen } from '../splash/splash-screen';
78
import { MaybePromise } from '@theia/core/lib/common/types';
89
import { ElectronSecurityToken } from '@theia/core/lib/electron-common/electron-token';
910
import { FrontendApplicationConfig } from '@theia/application-package/lib/application-props';
1011
import {
1112
ElectronMainApplication as TheiaElectronMainApplication,
13+
ElectronMainExecutionParams,
1214
TheiaBrowserWindowOptions,
1315
} from '@theia/core/lib/electron-main/electron-main-application';
1416
import { SplashServiceImpl } from '../splash/splash-service-impl';
17+
import { URI } from '@theia/core/shared/vscode-uri';
1518
import * as electronRemoteMain from '@theia/core/electron-shared/@electron/remote/main';
1619

1720
app.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()
2036
export 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

Comments
 (0)