Skip to content

Commit 25989de

Browse files
author
Akos Kitta
committed
Avoid deleting the workspace when it's still in use.
- From now on, NSFW service disposes after last reference is removed. No more 10sec delay. - Moved the temp workspace deletion to a startup task. - Can set initial task for the window from electron-main. - Removed the `browser-app`. Closes #39 Signed-off-by: Akos Kitta <[email protected]>
1 parent dcc0c0a commit 25989de

36 files changed

+554
-575
lines changed

Diff for: .vscode/launch.json

-31
Original file line numberDiff line numberDiff line change
@@ -80,37 +80,6 @@
8080
"port": 9222,
8181
"webRoot": "${workspaceFolder}/electron-app"
8282
},
83-
{
84-
"type": "node",
85-
"request": "launch",
86-
"name": "App (Browser)",
87-
"program": "${workspaceRoot}/browser-app/src-gen/backend/main.js",
88-
"args": [
89-
"--hostname=0.0.0.0",
90-
"--port=3000",
91-
"--no-cluster",
92-
"--no-app-auto-install",
93-
"--plugins=local-dir:plugins"
94-
],
95-
"windows": {
96-
"env": {
97-
"NODE_ENV": "development",
98-
"NODE_PRESERVE_SYMLINKS": "1"
99-
}
100-
},
101-
"env": {
102-
"NODE_ENV": "development"
103-
},
104-
"sourceMaps": true,
105-
"outFiles": [
106-
"${workspaceRoot}/browser-app/src-gen/backend/*.js",
107-
"${workspaceRoot}/browser-app/lib/**/*.js",
108-
"${workspaceRoot}/arduino-ide-extension/lib/**/*.js"
109-
],
110-
"smartStep": true,
111-
"internalConsoleOptions": "openOnSessionStart",
112-
"outputCapture": "std"
113-
},
11483
{
11584
"type": "node",
11685
"request": "launch",

Diff for: .vscode/tasks.json

-30
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,6 @@
1212
"clear": false
1313
}
1414
},
15-
{
16-
"label": "Arduino IDE - Start Browser App",
17-
"type": "shell",
18-
"command": "yarn --cwd ./browser-app start",
19-
"group": "build",
20-
"presentation": {
21-
"reveal": "always",
22-
"panel": "new",
23-
"clear": true
24-
}
25-
},
2615
{
2716
"label": "Arduino IDE - Watch IDE Extension",
2817
"type": "shell",
@@ -34,17 +23,6 @@
3423
"clear": false
3524
}
3625
},
37-
{
38-
"label": "Arduino IDE - Watch Browser App",
39-
"type": "shell",
40-
"command": "yarn --cwd ./browser-app watch",
41-
"group": "build",
42-
"presentation": {
43-
"reveal": "always",
44-
"panel": "new",
45-
"clear": false
46-
}
47-
},
4826
{
4927
"label": "Arduino IDE - Watch Electron App",
5028
"type": "shell",
@@ -56,14 +34,6 @@
5634
"clear": false
5735
}
5836
},
59-
{
60-
"label": "Arduino IDE - Watch All [Browser]",
61-
"type": "shell",
62-
"dependsOn": [
63-
"Arduino IDE - Watch IDE Extension",
64-
"Arduino IDE - Watch Browser App"
65-
]
66-
},
6737
{
6838
"label": "Arduino IDE - Watch All [Electron]",
6939
"type": "shell",

Diff for: arduino-ide-extension/package.json

-2
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,9 @@
147147
"frontend": "lib/browser/arduino-ide-frontend-module"
148148
},
149149
{
150-
"frontend": "lib/browser/theia/core/browser-menu-module",
151150
"frontendElectron": "lib/electron-browser/theia/core/electron-menu-module"
152151
},
153152
{
154-
"frontend": "lib/browser/theia/core/browser-window-module",
155153
"frontendElectron": "lib/electron-browser/theia/core/electron-window-module"
156154
},
157155
{

Diff for: arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ import {
105105
} from '@theia/core/lib/browser/connection-status-service';
106106
import { BoardsDataMenuUpdater } from './boards/boards-data-menu-updater';
107107
import { BoardsDataStore } from './boards/boards-data-store';
108-
import { ILogger } from '@theia/core';
108+
import { ILogger } from '@theia/core/lib/common/logger';
109+
import { bindContributionProvider } from '@theia/core/lib/common/contribution-provider';
109110
import {
110111
FileSystemExt,
111112
FileSystemExtPath,
@@ -308,7 +309,7 @@ import { CoreErrorHandler } from './contributions/core-error-handler';
308309
import { CompilerErrors } from './contributions/compiler-errors';
309310
import { WidgetManager } from './theia/core/widget-manager';
310311
import { WidgetManager as TheiaWidgetManager } from '@theia/core/lib/browser/widget-manager';
311-
import { StartupTasks } from './widgets/sketchbook/startup-task';
312+
import { StartupTasks } from './contributions/startup-task';
312313
import { IndexesUpdateProgress } from './contributions/indexes-update-progress';
313314
import { Daemon } from './contributions/daemon';
314315
import { FirstStartupInstaller } from './contributions/first-startup-installer';
@@ -334,6 +335,8 @@ import {
334335
} from './widgets/component-list/filter-renderer';
335336
import { CheckForUpdates } from './contributions/check-for-updates';
336337
import { OutputEditorFactory } from './theia/output/output-editor-factory';
338+
import { StartupTaskProvider } from '../electron-common/startup-task';
339+
import { DeleteSketch } from './contributions/delete-sketch';
337340

338341
const registerArduinoThemes = () => {
339342
const themes: MonacoThemeJson[] = [
@@ -433,6 +436,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
433436
// Boards service client to receive and delegate notifications from the backend.
434437
bind(BoardsServiceProvider).toSelf().inSingletonScope();
435438
bind(FrontendApplicationContribution).toService(BoardsServiceProvider);
439+
bind(CommandContribution).toService(BoardsServiceProvider);
436440

437441
// To be able to track, and update the menu based on the core settings (aka. board details) of the currently selected board.
438442
bind(FrontendApplicationContribution)
@@ -757,6 +761,10 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
757761
Contribution.configure(bind, OpenBoardsConfig);
758762
Contribution.configure(bind, SketchFilesTracker);
759763
Contribution.configure(bind, CheckForUpdates);
764+
Contribution.configure(bind, DeleteSketch);
765+
766+
bindContributionProvider(bind, StartupTaskProvider);
767+
bind(StartupTaskProvider).toService(BoardsServiceProvider); // to reuse the boards config in another window
760768

761769
// Disabled the quick-pick customization from Theia when multiple formatters are available.
762770
// Use the default VS Code behavior, and pick the first one. In the IDE2, clang-format has `exclusive` selectors.

Diff for: arduino-ide-extension/src/browser/boards/boards-config.tsx

-48
Original file line numberDiff line numberDiff line change
@@ -413,53 +413,5 @@ export namespace BoardsConfig {
413413
const { name } = selectedBoard;
414414
return `${name}${port ? ` at ${port.address}` : ''}`;
415415
}
416-
417-
export function setConfig(
418-
config: Config | undefined,
419-
urlToAttachTo: URL
420-
): URL {
421-
const copy = new URL(urlToAttachTo.toString());
422-
if (!config) {
423-
copy.searchParams.delete('boards-config');
424-
return copy;
425-
}
426-
427-
const selectedBoard = config.selectedBoard
428-
? {
429-
name: config.selectedBoard.name,
430-
fqbn: config.selectedBoard.fqbn,
431-
}
432-
: undefined;
433-
const selectedPort = config.selectedPort
434-
? {
435-
protocol: config.selectedPort.protocol,
436-
address: config.selectedPort.address,
437-
}
438-
: undefined;
439-
const jsonConfig = JSON.stringify({ selectedBoard, selectedPort });
440-
copy.searchParams.set('boards-config', encodeURIComponent(jsonConfig));
441-
return copy;
442-
}
443-
444-
export function getConfig(url: URL): Config | undefined {
445-
const encoded = url.searchParams.get('boards-config');
446-
if (!encoded) {
447-
return undefined;
448-
}
449-
try {
450-
const raw = decodeURIComponent(encoded);
451-
const candidate = JSON.parse(raw);
452-
if (typeof candidate === 'object') {
453-
return candidate;
454-
}
455-
console.warn(
456-
`Expected candidate to be an object. It was ${typeof candidate}. URL was: ${url}`
457-
);
458-
return undefined;
459-
} catch (e) {
460-
console.log(`Could not get board config from URL: ${url}.`, e);
461-
return undefined;
462-
}
463-
}
464416
}
465417
}

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

+54-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { injectable, inject } from '@theia/core/shared/inversify';
22
import { Emitter } from '@theia/core/lib/common/event';
33
import { ILogger } from '@theia/core/lib/common/logger';
4-
import { CommandService } from '@theia/core/lib/common/command';
4+
import {
5+
Command,
6+
CommandContribution,
7+
CommandRegistry,
8+
CommandService,
9+
} from '@theia/core/lib/common/command';
510
import { MessageService } from '@theia/core/lib/common/message-service';
611
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application';
712
import { RecursiveRequired } from '../../common/types';
@@ -23,9 +28,18 @@ import { nls } from '@theia/core/lib/common';
2328
import { Deferred } from '@theia/core/lib/common/promise-util';
2429
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
2530
import { Unknown } from '../../common/nls';
31+
import {
32+
StartupTask,
33+
StartupTaskProvider,
34+
} from '../../electron-common/startup-task';
2635

2736
@injectable()
28-
export class BoardsServiceProvider implements FrontendApplicationContribution {
37+
export class BoardsServiceProvider
38+
implements
39+
FrontendApplicationContribution,
40+
StartupTaskProvider,
41+
CommandContribution
42+
{
2943
@inject(ILogger)
3044
protected logger: ILogger;
3145

@@ -50,6 +64,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
5064
AvailableBoard[]
5165
>();
5266
protected readonly onAvailablePortsChangedEmitter = new Emitter<Port[]>();
67+
private readonly inheritedConfig = new Deferred<BoardsConfig.Config>();
5368

5469
/**
5570
* Used for the auto-reconnecting. Sometimes, the attached board gets disconnected after uploading something to it.
@@ -115,6 +130,13 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
115130
});
116131
}
117132

133+
registerCommands(registry: CommandRegistry): void {
134+
registry.registerCommand(USE_INHERITED_CONFIG, {
135+
execute: (inheritedConfig: BoardsConfig.Config) =>
136+
this.inheritedConfig.resolve(inheritedConfig),
137+
});
138+
}
139+
118140
get reconciled(): Promise<void> {
119141
return this._reconciled.promise;
120142
}
@@ -655,11 +677,14 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
655677
let storedLatestBoardsConfig = await this.getData<
656678
BoardsConfig.Config | undefined
657679
>('latest-boards-config');
658-
// Try to get from the URL if it was not persisted.
680+
// Try to get from the startup task. Wait for it, then timeout. Maybe it never arrives.
659681
if (!storedLatestBoardsConfig) {
660-
storedLatestBoardsConfig = BoardsConfig.Config.getConfig(
661-
new URL(window.location.href)
662-
);
682+
storedLatestBoardsConfig = await Promise.race([
683+
this.inheritedConfig.promise,
684+
new Promise<undefined>((resolve) =>
685+
setTimeout(() => resolve(undefined), 2_000)
686+
),
687+
]);
663688
}
664689
if (storedLatestBoardsConfig) {
665690
this.latestBoardsConfig = storedLatestBoardsConfig;
@@ -682,8 +707,31 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
682707
key
683708
);
684709
}
710+
711+
tasks(): StartupTask[] {
712+
return [
713+
{
714+
command: USE_INHERITED_CONFIG.id,
715+
args: [this.boardsConfig],
716+
},
717+
];
718+
}
685719
}
686720

721+
/**
722+
* It should be neither visible nor called from outside.
723+
*
724+
* This service creates a startup task with the current board config and
725+
* passes the task to the electron-main process so that the new window
726+
* can inherit the boards config state of this service.
727+
*
728+
* Note that the state is always set, but new windows might ignore it.
729+
* For example, the new window already has a valid boards config persisted to the local storage.
730+
*/
731+
const USE_INHERITED_CONFIG: Command = {
732+
id: 'arduino-use-inherited-boards-config',
733+
};
734+
687735
/**
688736
* Representation of a ready-to-use board, either the user has configured it or was automatically recognized by the CLI.
689737
* An available board was not necessarily recognized by the CLI (e.g.: it is a 3rd party board) or correctly configured but ready for `verify`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { injectable } from '@theia/core/shared/inversify';
2+
import { SketchesError } from '../../common/protocol';
3+
import {
4+
Command,
5+
CommandRegistry,
6+
SketchContribution,
7+
Sketch,
8+
} from './contribution';
9+
10+
@injectable()
11+
export class DeleteSketch extends SketchContribution {
12+
override registerCommands(registry: CommandRegistry): void {
13+
registry.registerCommand(DeleteSketch.Commands.DELETE_SKETCH, {
14+
execute: (uri: string) => this.deleteSketch(uri),
15+
});
16+
}
17+
18+
private async deleteSketch(uri: string): Promise<void> {
19+
const sketch = await this.loadSketch(uri);
20+
if (!sketch) {
21+
console.info(`Sketch not found at ${uri}. Skipping deletion.`);
22+
return;
23+
}
24+
return this.sketchService.deleteSketch(sketch);
25+
}
26+
27+
private async loadSketch(uri: string): Promise<Sketch | undefined> {
28+
try {
29+
const sketch = await this.sketchService.loadSketch(uri);
30+
return sketch;
31+
} catch (err) {
32+
if (SketchesError.NotFound.is(err)) {
33+
return undefined;
34+
}
35+
throw err;
36+
}
37+
}
38+
}
39+
export namespace DeleteSketch {
40+
export namespace Commands {
41+
export const DELETE_SKETCH: Command = {
42+
id: 'arduino-delete-sketch',
43+
};
44+
}
45+
}

0 commit comments

Comments
 (0)