mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-07-10 21:06:33 +00:00
ATL-1206: Reuse selected board for new sketches.
Closes #95. Signed-off-by: Akos Kitta <kittaakos@typefox.io>
This commit is contained in:
parent
fa9334eb7a
commit
c86d82d273
@ -158,6 +158,7 @@ import { MonacoEditorProvider } from './theia/monaco/monaco-editor-provider';
|
||||
import { MonacoEditorProvider as TheiaMonacoEditorProvider } from '@theia/monaco/lib/browser/monaco-editor-provider';
|
||||
import { DebugEditorModel } from './theia/debug/debug-editor-model';
|
||||
import { DebugEditorModelFactory } from '@theia/debug/lib/browser/editor/debug-editor-model';
|
||||
import { StorageWrapper } from './storage-wrapper';
|
||||
|
||||
const ElementQueries = require('css-element-queries/src/ElementQueries');
|
||||
|
||||
@ -435,4 +436,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
bind(SettingsDialogProps).toConstantValue({
|
||||
title: 'Preferences'
|
||||
});
|
||||
|
||||
bind(StorageWrapper).toSelf().inSingletonScope();
|
||||
bind(CommandContribution).toService(StorageWrapper);
|
||||
});
|
||||
|
@ -281,6 +281,39 @@ export namespace BoardsConfig {
|
||||
return `${name}${port ? ' at ' + Port.toString(port) : ''}`;
|
||||
}
|
||||
|
||||
export function setConfig(config: Config | undefined, urlToAttachTo: URL): URL {
|
||||
const copy = new URL(urlToAttachTo.toString());
|
||||
if (!config) {
|
||||
copy.searchParams.delete('boards-config');
|
||||
return copy;
|
||||
}
|
||||
|
||||
const selectedBoard = config.selectedBoard ? { name: config.selectedBoard.name, fqbn: config.selectedBoard.fqbn } : undefined;
|
||||
const selectedPort = config.selectedPort ? { protocol: config.selectedPort.protocol, address: config.selectedPort.address } : undefined;
|
||||
const jsonConfig = JSON.stringify({ selectedBoard, selectedPort });
|
||||
copy.searchParams.set('boards-config', encodeURIComponent(jsonConfig));
|
||||
return copy;
|
||||
}
|
||||
|
||||
export function getConfig(url: URL): Config | undefined {
|
||||
const encoded = url.searchParams.get('boards-config');
|
||||
if (!encoded) {
|
||||
return undefined;
|
||||
}
|
||||
try {
|
||||
const raw = decodeURIComponent(encoded);
|
||||
const candidate = JSON.parse(raw);
|
||||
if (typeof candidate === 'object') {
|
||||
return candidate;
|
||||
}
|
||||
console.warn(`Expected candidate to be an object. It was ${typeof candidate}. URL was: ${url}`);
|
||||
return undefined;
|
||||
} catch (e) {
|
||||
console.log(`Could not get board config from URL: ${url}.`, e);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { injectable, inject } from 'inversify';
|
||||
import { Emitter } from '@theia/core/lib/common/event';
|
||||
import { ILogger } from '@theia/core/lib/common/logger';
|
||||
import { CommandService } from '@theia/core/lib/common/command';
|
||||
import { MessageService } from '@theia/core/lib/common/message-service';
|
||||
import { StorageService } from '@theia/core/lib/browser/storage-service';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application';
|
||||
import { RecursiveRequired } from '../../common/types';
|
||||
import {
|
||||
@ -16,8 +16,8 @@ import {
|
||||
import { BoardsConfig } from './boards-config';
|
||||
import { naturalCompare } from '../../common/utils';
|
||||
import { NotificationCenter } from '../notification-center';
|
||||
import { CommandService } from '@theia/core';
|
||||
import { ArduinoCommands } from '../arduino-commands';
|
||||
import { StorageWrapper } from '../storage-wrapper';
|
||||
|
||||
@injectable()
|
||||
export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
@ -28,8 +28,6 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
@inject(MessageService)
|
||||
protected messageService: MessageService;
|
||||
|
||||
@inject(StorageService)
|
||||
protected storageService: StorageService;
|
||||
|
||||
@inject(BoardsService)
|
||||
protected boardsService: BoardsService;
|
||||
@ -349,7 +347,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
return undefined;
|
||||
}
|
||||
const key = this.getLastSelectedBoardOnPortKey(port);
|
||||
return this.storageService.getData<Board>(key);
|
||||
return this.getData<Board>(key);
|
||||
}
|
||||
|
||||
protected async saveState(): Promise<void> {
|
||||
@ -360,11 +358,11 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
const { selectedBoard, selectedPort } = this.boardsConfig;
|
||||
if (selectedBoard && selectedPort) {
|
||||
const key = this.getLastSelectedBoardOnPortKey(selectedPort);
|
||||
await this.storageService.setData(key, selectedBoard);
|
||||
await this.setData(key, selectedBoard);
|
||||
}
|
||||
await Promise.all([
|
||||
this.storageService.setData('latest-valid-boards-config', this.latestValidBoardsConfig),
|
||||
this.storageService.setData('latest-boards-config', this.latestBoardsConfig)
|
||||
this.setData('latest-valid-boards-config', this.latestValidBoardsConfig),
|
||||
this.setData('latest-boards-config', this.latestBoardsConfig)
|
||||
]);
|
||||
}
|
||||
|
||||
@ -374,7 +372,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
}
|
||||
|
||||
protected async loadState(): Promise<void> {
|
||||
const storedLatestValidBoardsConfig = await this.storageService.getData<RecursiveRequired<BoardsConfig.Config>>('latest-valid-boards-config');
|
||||
const storedLatestValidBoardsConfig = await this.getData<RecursiveRequired<BoardsConfig.Config>>('latest-valid-boards-config');
|
||||
if (storedLatestValidBoardsConfig) {
|
||||
this.latestValidBoardsConfig = storedLatestValidBoardsConfig;
|
||||
if (this.canUploadTo(this.latestValidBoardsConfig)) {
|
||||
@ -382,13 +380,25 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
}
|
||||
} else {
|
||||
// If we could not restore the latest valid config, try to restore something, the board at least.
|
||||
const storedLatestBoardsConfig = await this.storageService.getData<BoardsConfig.Config | undefined>('latest-boards-config');
|
||||
let storedLatestBoardsConfig = await this.getData<BoardsConfig.Config | undefined>('latest-boards-config');
|
||||
// Try to get from the URL if it was not persisted.
|
||||
if (!storedLatestBoardsConfig) {
|
||||
storedLatestBoardsConfig = BoardsConfig.Config.getConfig(new URL(window.location.href));
|
||||
}
|
||||
if (storedLatestBoardsConfig) {
|
||||
this.latestBoardsConfig = storedLatestBoardsConfig;
|
||||
this.boardsConfig = this.latestBoardsConfig;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private setData<T>(key: string, value: T): Promise<void> {
|
||||
return this.commandService.executeCommand(StorageWrapper.Commands.SET_DATA.id, key, value);
|
||||
}
|
||||
|
||||
private getData<T>(key: string): Promise<T | undefined> {
|
||||
return this.commandService.executeCommand<T>(StorageWrapper.Commands.GET_DATA.id, key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
33
arduino-ide-extension/src/browser/storage-wrapper.ts
Normal file
33
arduino-ide-extension/src/browser/storage-wrapper.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { injectable, inject } from 'inversify';
|
||||
import { StorageService } from '@theia/core/lib/browser/storage-service';
|
||||
import { Command, CommandContribution, CommandRegistry } from '@theia/core/lib/common/command';
|
||||
|
||||
/**
|
||||
* This is a workaround to break cycles in the dependency injection. Provides commands for `setData` and `getData`.
|
||||
*/
|
||||
@injectable()
|
||||
export class StorageWrapper implements CommandContribution {
|
||||
|
||||
@inject(StorageService)
|
||||
protected storageService: StorageService;
|
||||
|
||||
registerCommands(commands: CommandRegistry): void {
|
||||
commands.registerCommand(StorageWrapper.Commands.GET_DATA, {
|
||||
execute: (key: string, defaultValue?: any) => this.storageService.getData(key, defaultValue)
|
||||
});
|
||||
commands.registerCommand(StorageWrapper.Commands.SET_DATA, {
|
||||
execute: (key: string, value: any) => this.storageService.setData(key, value)
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
export namespace StorageWrapper {
|
||||
export namespace Commands {
|
||||
export const SET_DATA: Command = {
|
||||
id: 'arduino-store-wrapper-set'
|
||||
};
|
||||
export const GET_DATA: Command = {
|
||||
id: 'arduino-store-wrapper-get'
|
||||
};
|
||||
}
|
||||
}
|
@ -11,6 +11,8 @@ import { WorkspaceService as TheiaWorkspaceService } from '@theia/workspace/lib/
|
||||
import { ConfigService } from '../../../common/protocol/config-service';
|
||||
import { SketchesService, Sketch, SketchContainer } from '../../../common/protocol/sketches-service';
|
||||
import { ArduinoWorkspaceRootResolver } from '../../arduino-workspace-resolver';
|
||||
import { BoardsServiceProvider } from '../../boards/boards-service-provider';
|
||||
import { BoardsConfig } from '../../boards/boards-config';
|
||||
|
||||
@injectable()
|
||||
export class WorkspaceService extends TheiaWorkspaceService {
|
||||
@ -33,6 +35,9 @@ export class WorkspaceService extends TheiaWorkspaceService {
|
||||
@inject(FrontendApplicationStateService)
|
||||
protected readonly appStateService: FrontendApplicationStateService;
|
||||
|
||||
@inject(BoardsServiceProvider)
|
||||
protected readonly boardsServiceProvider: BoardsServiceProvider;
|
||||
|
||||
private application: FrontendApplication;
|
||||
private workspaceUri?: Promise<string | undefined>;
|
||||
private version?: string;
|
||||
@ -80,6 +85,13 @@ export class WorkspaceService extends TheiaWorkspaceService {
|
||||
return this.workspaceUri;
|
||||
}
|
||||
|
||||
protected openNewWindow(workspacePath: string): void {
|
||||
const { boardsConfig } = this.boardsServiceProvider;
|
||||
const url = BoardsConfig.Config.setConfig(boardsConfig, new URL(window.location.href)); // Set the current boards config for the new browser window.
|
||||
url.hash = workspacePath;
|
||||
this.windowService.openNewWindow(url.toString());
|
||||
}
|
||||
|
||||
private async isValid(uri: string): Promise<boolean> {
|
||||
const exists = await this.fileService.exists(new URI(uri));
|
||||
if (!exists) {
|
||||
|
@ -11,7 +11,8 @@ export class ElectronMainWindowServiceImpl extends TheiaElectronMainWindowServic
|
||||
|
||||
openNewWindow(url: string, { external }: NewWindowOptions): undefined {
|
||||
if (!external) {
|
||||
const existing = this.app.windows.find(window => window.webContents.getURL() === url);
|
||||
const sanitizedUrl = this.sanitize(url);
|
||||
const existing = this.app.windows.find(window => this.sanitize(window.webContents.getURL()) === sanitizedUrl);
|
||||
if (existing) {
|
||||
existing.focus();
|
||||
return;
|
||||
@ -20,5 +21,14 @@ export class ElectronMainWindowServiceImpl extends TheiaElectronMainWindowServic
|
||||
return super.openNewWindow(url, { external });
|
||||
}
|
||||
|
||||
private sanitize(url: string): string {
|
||||
const copy = new URL(url);
|
||||
const searchParams: string[] = [];
|
||||
copy.searchParams.forEach((_, key) => searchParams.push(key));
|
||||
for (const param of searchParams) {
|
||||
copy.searchParams.delete(param);
|
||||
}
|
||||
return copy.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user