Skip to content

Commit 2ede39e

Browse files
committed
Enable opening the IDE from finder/explorer
1 parent 9b1f15d commit 2ede39e

File tree

2 files changed

+85
-11
lines changed

2 files changed

+85
-11
lines changed

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

+79-11
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { inject, injectable } from 'inversify';
22
import { app, BrowserWindow, BrowserWindowConstructorOptions, ipcMain, screen } from '@theia/core/electron-shared/electron';
33
import { fork } from 'child_process';
44
import { AddressInfo } from 'net';
5-
import { join } from 'path';
5+
import { join, dirname } from 'path';
66
import * as fs from 'fs-extra';
77
import { initSplashScreen } from '../splash/splash-screen';
88
import { MaybePromise } from '@theia/core/lib/common/types';
@@ -16,6 +16,7 @@ import {
1616
import { SplashServiceImpl } from '../splash/splash-service-impl';
1717
import { URI } from '@theia/core/shared/vscode-uri';
1818
import * as electronRemoteMain from '@theia/core/electron-shared/@electron/remote/main';
19+
import { Deferred } from '@theia/core/lib/common/promise-util';
1920

2021
app.commandLine.appendSwitch('disable-http-cache');
2122

@@ -36,6 +37,7 @@ const WORKSPACES = 'workspaces';
3637
export class ElectronMainApplication extends TheiaElectronMainApplication {
3738
protected _windows: BrowserWindow[] = [];
3839
protected startup = false;
40+
protected openFilePromise = new Deferred();
3941

4042
@inject(SplashServiceImpl)
4143
protected readonly splashService: SplashServiceImpl;
@@ -45,17 +47,53 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
4547
// See: https://github.com/electron-userland/electron-builder/issues/2468
4648
// Regression in Theia: https://github.com/eclipse-theia/theia/issues/8701
4749
app.on('ready', () => app.setName(config.applicationName));
50+
this.attachFileAssociations();
4851
return super.start(config);
4952
}
5053

54+
attachFileAssociations() {
55+
// OSX: register open-file event
56+
if (process.platform === 'darwin') {
57+
app.on('open-file', async (event, uri) => {
58+
event.preventDefault();
59+
if (uri.endsWith('.ino') && await fs.pathExists(uri)) {
60+
this.openFilePromise.reject();
61+
await this.openSketch(dirname(uri));
62+
}
63+
});
64+
setTimeout(() => this.openFilePromise.resolve(), 500);
65+
} else {
66+
this.openFilePromise.resolve();
67+
}
68+
}
69+
70+
protected async isValidSketchPath(uri: string): Promise<boolean | undefined> {
71+
return typeof uri === 'string' && await fs.pathExists(uri);
72+
}
73+
5174
protected async launch(params: ElectronMainExecutionParams): Promise<void> {
5275
this.startup = true;
76+
77+
try {
78+
// When running on MacOS, we either have to wait until
79+
// 1. The `open-file` command has been received by the app, rejecting the promise
80+
// 2. A short timeout resolves the promise automatically, falling back to the usual app launch
81+
await this.openFilePromise.promise;
82+
} catch {
83+
// Application has received the `open-file` event and will skip the default application launch
84+
return;
85+
}
86+
87+
if (process.platform === 'win32' && await this.launchWindowsOpen()) {
88+
// Application has received a file in its arguments and will skip the default application launch
89+
return;
90+
}
91+
5392
const workspaces: WorkspaceOptions[] | undefined = this.electronStore.get(WORKSPACES);
5493
let useDefault = true;
5594
if (workspaces && workspaces.length > 0) {
5695
for (const workspace of workspaces) {
57-
const file = workspace.file;
58-
if (typeof file === 'string' && await fs.pathExists(file)) {
96+
if (await this.isValidSketchPath(workspace.file)) {
5997
useDefault = false;
6098
await this.openSketch(workspace);
6199
}
@@ -67,16 +105,46 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
67105
}
68106
}
69107

70-
protected async openSketch(workspace: WorkspaceOptions): Promise<BrowserWindow> {
108+
protected async launchWindowsOpen(): Promise<boolean> {
109+
// Copy to prevent manipulation of original array
110+
const argCopy = [...process.argv];
111+
if (app.isPackaged) {
112+
// workaround for missing executable argument when app is packaged
113+
argCopy.unshift('packaged');
114+
}
115+
const possibleUris = argCopy.slice(2) || null;
116+
if (possibleUris) {
117+
let uri: string | undefined;
118+
for (const possibleUri of possibleUris) {
119+
if (possibleUri.endsWith('.ino') && await this.isValidSketchPath(possibleUri)) {
120+
uri = possibleUri;
121+
break;
122+
}
123+
}
124+
if (uri) {
125+
await this.openSketch(dirname(uri));
126+
return true;
127+
}
128+
}
129+
return false;
130+
}
131+
132+
protected async openSketch(workspace: WorkspaceOptions | string): Promise<BrowserWindow> {
71133
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;
134+
let file: string;
135+
if (typeof workspace === 'object') {
136+
options.x = workspace.x;
137+
options.y = workspace.y;
138+
options.width = workspace.width;
139+
options.height = workspace.height;
140+
options.isMaximized = workspace.isMaximized;
141+
options.isFullScreen = workspace.isFullScreen;
142+
file = workspace.file;
143+
} else {
144+
file = workspace;
145+
}
78146
const [uri, electronWindow] = await Promise.all([this.createWindowUri(), this.createWindow(options)]);
79-
electronWindow.loadURL(uri.withFragment(encodeURI(workspace.file)).toString(true));
147+
electronWindow.loadURL(uri.withFragment(encodeURI(file)).toString(true));
80148
return electronWindow;
81149
}
82150

Diff for: electron/build/template-package.json

+6
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@
6060
"directories": {
6161
"buildResources": "resources"
6262
},
63+
"fileAssociations": [
64+
{
65+
"ext": "ino",
66+
"role": "Editor"
67+
}
68+
],
6369
"files": [
6470
"src-gen",
6571
"lib",

0 commit comments

Comments
 (0)