mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-07-27 05:06:42 +00:00
Open all closed workspaces on startup (#780)
This commit is contained in:
parent
a20899ff43
commit
69ac1f4779
@ -1,5 +1,4 @@
|
|||||||
import { toUnix } from 'upath';
|
import { URI } from '@theia/core/shared/vscode-uri';
|
||||||
import URI from '@theia/core/lib/common/uri';
|
|
||||||
import { isWindows } from '@theia/core/lib/common/os';
|
import { isWindows } from '@theia/core/lib/common/os';
|
||||||
import { notEmpty } from '@theia/core/lib/common/objects';
|
import { notEmpty } from '@theia/core/lib/common/objects';
|
||||||
import { MaybePromise } from '@theia/core/lib/common/types';
|
import { MaybePromise } from '@theia/core/lib/common/types';
|
||||||
@ -61,12 +60,8 @@ export class ArduinoWorkspaceRootResolver {
|
|||||||
// - https://github.com/eclipse-theia/theia/blob/8196e9dcf9c8de8ea0910efeb5334a974f426966/packages/workspace/src/browser/workspace-service.ts#L423
|
// - https://github.com/eclipse-theia/theia/blob/8196e9dcf9c8de8ea0910efeb5334a974f426966/packages/workspace/src/browser/workspace-service.ts#L423
|
||||||
protected hashToUri(hash: string | undefined): string | undefined {
|
protected hashToUri(hash: string | undefined): string | undefined {
|
||||||
if (hash && hash.length > 1 && hash.startsWith('#')) {
|
if (hash && hash.length > 1 && hash.startsWith('#')) {
|
||||||
const path = hash.slice(1); // Trim the leading `#`.
|
const path = decodeURI(hash.slice(1)).replace(/\\/g, '/'); // Trim the leading `#`, decode the URI and replace Windows separators
|
||||||
return new URI(
|
return URI.file(path.slice(isWindows && hash.startsWith('/') ? 1 : 0)).toString();
|
||||||
toUnix(path.slice(isWindows && hash.startsWith('/') ? 1 : 0))
|
|
||||||
)
|
|
||||||
.withScheme('file')
|
|
||||||
.toString();
|
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
@ -8,22 +8,39 @@ import {
|
|||||||
import { fork } from 'child_process';
|
import { fork } from 'child_process';
|
||||||
import { AddressInfo } from 'net';
|
import { AddressInfo } from 'net';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
|
import * as fs from 'fs-extra';
|
||||||
import { initSplashScreen } from '../splash/splash-screen';
|
import { initSplashScreen } from '../splash/splash-screen';
|
||||||
import { MaybePromise } from '@theia/core/lib/common/types';
|
import { MaybePromise } from '@theia/core/lib/common/types';
|
||||||
import { ElectronSecurityToken } from '@theia/core/lib/electron-common/electron-token';
|
import { ElectronSecurityToken } from '@theia/core/lib/electron-common/electron-token';
|
||||||
import { FrontendApplicationConfig } from '@theia/application-package/lib/application-props';
|
import { FrontendApplicationConfig } from '@theia/application-package/lib/application-props';
|
||||||
import {
|
import {
|
||||||
ElectronMainApplication as TheiaElectronMainApplication,
|
ElectronMainApplication as TheiaElectronMainApplication,
|
||||||
|
ElectronMainExecutionParams,
|
||||||
TheiaBrowserWindowOptions,
|
TheiaBrowserWindowOptions,
|
||||||
} from '@theia/core/lib/electron-main/electron-main-application';
|
} from '@theia/core/lib/electron-main/electron-main-application';
|
||||||
import { SplashServiceImpl } from '../splash/splash-service-impl';
|
import { SplashServiceImpl } from '../splash/splash-service-impl';
|
||||||
import { ipcMain } from '@theia/core/shared/electron';
|
import { ipcMain } from '@theia/core/shared/electron';
|
||||||
|
import { URI } from '@theia/core/shared/vscode-uri';
|
||||||
|
|
||||||
app.commandLine.appendSwitch('disable-http-cache');
|
app.commandLine.appendSwitch('disable-http-cache');
|
||||||
|
|
||||||
|
interface WorkspaceOptions {
|
||||||
|
file: string
|
||||||
|
x: number
|
||||||
|
y: number
|
||||||
|
width: number
|
||||||
|
height: number
|
||||||
|
isMaximized: boolean
|
||||||
|
isFullScreen: boolean
|
||||||
|
time: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const WORKSPACES = 'workspaces';
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class ElectronMainApplication extends TheiaElectronMainApplication {
|
export class ElectronMainApplication extends TheiaElectronMainApplication {
|
||||||
protected _windows: BrowserWindow[] = [];
|
protected _windows: BrowserWindow[] = [];
|
||||||
|
protected startup = false;
|
||||||
|
|
||||||
@inject(SplashServiceImpl)
|
@inject(SplashServiceImpl)
|
||||||
protected readonly splashService: SplashServiceImpl;
|
protected readonly splashService: SplashServiceImpl;
|
||||||
@ -36,6 +53,45 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
|
|||||||
return super.start(config);
|
return super.start(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected async launch(params: ElectronMainExecutionParams): Promise<void> {
|
||||||
|
this.startup = true;
|
||||||
|
const workspaces: WorkspaceOptions[] | undefined = this.electronStore.get(WORKSPACES);
|
||||||
|
let useDefault = true;
|
||||||
|
if (workspaces && workspaces.length > 0) {
|
||||||
|
for (const workspace of workspaces) {
|
||||||
|
const file = workspace.file;
|
||||||
|
if (typeof file === 'string' && await fs.pathExists(file)) {
|
||||||
|
useDefault = false;
|
||||||
|
await this.openSketch(workspace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.startup = false;
|
||||||
|
if (useDefault) {
|
||||||
|
super.launch(params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async openSketch(workspace: WorkspaceOptions): Promise<BrowserWindow> {
|
||||||
|
const options = await this.getLastWindowOptions();
|
||||||
|
options.x = workspace.x;
|
||||||
|
options.y = workspace.y;
|
||||||
|
options.width = workspace.width;
|
||||||
|
options.height = workspace.height;
|
||||||
|
options.isMaximized = workspace.isMaximized;
|
||||||
|
options.isFullScreen = workspace.isFullScreen;
|
||||||
|
const [uri, electronWindow] = await Promise.all([this.createWindowUri(), this.createWindow(options)]);
|
||||||
|
electronWindow.loadURL(uri.withFragment(encodeURI(workspace.file)).toString(true));
|
||||||
|
return electronWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected avoidOverlap(options: TheiaBrowserWindowOptions): TheiaBrowserWindowOptions {
|
||||||
|
if (this.startup) {
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
return super.avoidOverlap(options);
|
||||||
|
}
|
||||||
|
|
||||||
protected getTitleBarStyle(): 'native' | 'custom' {
|
protected getTitleBarStyle(): 'native' | 'custom' {
|
||||||
return 'native';
|
return 'native';
|
||||||
}
|
}
|
||||||
@ -148,6 +204,7 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.attachClosedWorkspace(electronWindow);
|
||||||
this.attachReadyToShow(electronWindow);
|
this.attachReadyToShow(electronWindow);
|
||||||
this.attachSaveWindowState(electronWindow);
|
this.attachSaveWindowState(electronWindow);
|
||||||
this.attachGlobalShortcuts(electronWindow);
|
this.attachGlobalShortcuts(electronWindow);
|
||||||
@ -218,6 +275,44 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected closedWorkspaces: WorkspaceOptions[] = [];
|
||||||
|
|
||||||
|
protected attachClosedWorkspace(window: BrowserWindow): void {
|
||||||
|
// Since the `before-quit` event is only fired when closing the *last* window
|
||||||
|
// We need to keep track of recently closed windows/workspaces manually
|
||||||
|
window.on('close', () => {
|
||||||
|
const url = window.webContents.getURL();
|
||||||
|
const workspace = URI.parse(url).fragment;
|
||||||
|
if (workspace) {
|
||||||
|
const workspaceUri = URI.file(workspace);
|
||||||
|
const bounds = window.getNormalBounds();
|
||||||
|
this.closedWorkspaces.push({
|
||||||
|
...bounds,
|
||||||
|
isMaximized: window.isMaximized(),
|
||||||
|
isFullScreen: window.isFullScreen(),
|
||||||
|
file: workspaceUri.fsPath,
|
||||||
|
time: Date.now()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected onWillQuit(event: Electron.Event): void {
|
||||||
|
// Only add workspaces which were closed within the last second (1000 milliseconds)
|
||||||
|
const threshold = Date.now() - 1000;
|
||||||
|
const visited = new Set<string>();
|
||||||
|
const workspaces = this.closedWorkspaces.filter(e => {
|
||||||
|
if (e.time < threshold || visited.has(e.file)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
visited.add(e.file);
|
||||||
|
return true;
|
||||||
|
}).sort((a, b) => a.file.localeCompare(b.file));
|
||||||
|
this.electronStore.set(WORKSPACES, workspaces);
|
||||||
|
|
||||||
|
super.onWillQuit(event);
|
||||||
|
}
|
||||||
|
|
||||||
get windows(): BrowserWindow[] {
|
get windows(): BrowserWindow[] {
|
||||||
return this._windows.slice();
|
return this._windows.slice();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user