Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 0207778

Browse files
authored
Enable opening the IDE from finder/explorer (#835)
* Enable opening the IDE from finder/explorer * Make opening windows from args a bit more lenient
1 parent d79f32e commit 0207778

File tree

2 files changed

+87
-12
lines changed

2 files changed

+87
-12
lines changed

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

Lines changed: 81 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { inject, injectable } from 'inversify';
2-
import { app, BrowserWindow, BrowserWindowConstructorOptions, ipcMain, screen } from '@theia/core/electron-shared/electron';
2+
import { app, BrowserWindow, BrowserWindowConstructorOptions, ipcMain, screen,EventasElectronEvent } 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,8 @@ 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';
20+
import * as os from '@theia/core/lib/common/os';
1921

2022
app.commandLine.appendSwitch('disable-http-cache');
2123

@@ -36,6 +38,7 @@ const WORKSPACES = 'workspaces';
3638
export class ElectronMainApplication extends TheiaElectronMainApplication {
3739
protected _windows: BrowserWindow[] = [];
3840
protected startup = false;
41+
protected openFilePromise = new Deferred();
3942

4043
@inject(SplashServiceImpl)
4144
protected readonly splashService: SplashServiceImpl;
@@ -45,17 +48,52 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
4548
// See: https://github.com/electron-userland/electron-builder/issues/2468
4649
// Regression in Theia: https://github.com/eclipse-theia/theia/issues/8701
4750
app.on('ready', () => app.setName(config.applicationName));
51+
this.attachFileAssociations();
4852
return super.start(config);
4953
}
5054

55+
attachFileAssociations() {
56+
// OSX: register open-file event
57+
if (os.isOSX) {
58+
app.on('open-file', async (event, uri) => {
59+
event.preventDefault();
60+
if (uri.endsWith('.ino') && await fs.pathExists(uri)) {
61+
this.openFilePromise.reject();
62+
await this.openSketch(dirname(uri));
63+
}
64+
});
65+
setTimeout(() => this.openFilePromise.resolve(), 500);
66+
} else {
67+
this.openFilePromise.resolve();
68+
}
69+
}
70+
71+
protected async isValidSketchPath(uri: string): Promise<boolean | undefined> {
72+
return typeof uri === 'string' && await fs.pathExists(uri);
73+
}
74+
5175
protected async launch(params: ElectronMainExecutionParams): Promise<void> {
76+
try {
77+
// When running on MacOS, we either have to wait until
78+
// 1. The `open-file` command has been received by the app, rejecting the promise
79+
// 2. A short timeout resolves the promise automatically, falling back to the usual app launch
80+
await this.openFilePromise.promise;
81+
} catch {
82+
// Application has received the `open-file` event and will skip the default application launch
83+
return;
84+
}
85+
86+
if (!os.isOSX && await this.launchFromArgs(params)) {
87+
// Application has received a file in its arguments and will skip the default application launch
88+
return;
89+
}
90+
5291
this.startup = true;
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,39 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
67105
}
68106
}
69107

70-
protected async openSketch(workspace: WorkspaceOptions): Promise<BrowserWindow> {
108+
protected async launchFromArgs(params: ElectronMainExecutionParams): Promise<boolean> {
109+
// Copy to prevent manipulation of original array
110+
const argCopy = [...params.argv];
111+
let uri: string | undefined;
112+
for (const possibleUri of argCopy) {
113+
if (possibleUri.endsWith('.ino') && await this.isValidSketchPath(possibleUri)) {
114+
uri = possibleUri;
115+
break;
116+
}
117+
}
118+
if (uri) {
119+
await this.openSketch(dirname(uri));
120+
return true;
121+
}
122+
return false;
123+
}
124+
125+
protected async openSketch(workspace: WorkspaceOptions | string): Promise<BrowserWindow> {
71126
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;
127+
let file: string;
128+
if (typeof workspace === 'object') {
129+
options.x = workspace.x;
130+
options.y = workspace.y;
131+
options.width = workspace.width;
132+
options.height = workspace.height;
133+
options.isMaximized = workspace.isMaximized;
134+
options.isFullScreen = workspace.isFullScreen;
135+
file = workspace.file;
136+
} else {
137+
file = workspace;
138+
}
78139
const [uri, electronWindow] = await Promise.all([this.createWindowUri(), this.createWindow(options)]);
79-
electronWindow.loadURL(uri.withFragment(encodeURI(workspace.file)).toString(true));
140+
electronWindow.loadURL(uri.withFragment(encodeURI(file)).toString(true));
80141
return electronWindow;
81142
}
82143

@@ -101,6 +162,14 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
101162
});
102163
}
103164

165+
protected async onSecondInstance(event: ElectronEvent, argv: string[], cwd: string): Promise<void> {
166+
if (!os.isOSX && await this.launchFromArgs({ cwd, argv, secondInstance: true })) {
167+
// Application has received a file in its arguments
168+
return;
169+
}
170+
super.onSecondInstance(event, argv, cwd);
171+
}
172+
104173
/**
105174
* Use this rather than creating `BrowserWindow` instances from scratch, since some security parameters need to be set, this method will do it.
106175
*

‎electron/build/template-package.json‎

Lines changed: 6 additions & 0 deletions
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)

AltStyle によって変換されたページ (->オリジナル) /