mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-10-09 11:28:33 +00:00
Make tab width 2 spaces (#445)
This commit is contained in:
11
.prettierrc
11
.prettierrc
@@ -1,13 +1,6 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"tabWidth": 4,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.{json,yml}",
|
||||
"options": {
|
||||
"tabWidth": 2
|
||||
}
|
||||
}
|
||||
]
|
||||
"printWidth": 80
|
||||
}
|
||||
|
@@ -1,18 +1,38 @@
|
||||
import { Mutex } from 'async-mutex';
|
||||
import { MAIN_MENU_BAR, MenuContribution, MenuModelRegistry, SelectionService, ILogger, DisposableCollection } from '@theia/core';
|
||||
import {
|
||||
MAIN_MENU_BAR,
|
||||
MenuContribution,
|
||||
MenuModelRegistry,
|
||||
SelectionService,
|
||||
ILogger,
|
||||
DisposableCollection,
|
||||
} from '@theia/core';
|
||||
import {
|
||||
ContextMenuRenderer,
|
||||
FrontendApplication, FrontendApplicationContribution,
|
||||
OpenerService, StatusBar, StatusBarAlignment
|
||||
FrontendApplication,
|
||||
FrontendApplicationContribution,
|
||||
OpenerService,
|
||||
StatusBar,
|
||||
StatusBarAlignment,
|
||||
} from '@theia/core/lib/browser';
|
||||
import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution';
|
||||
import { ColorRegistry } from '@theia/core/lib/browser/color-registry';
|
||||
import { CommonMenus } from '@theia/core/lib/browser/common-frontend-contribution';
|
||||
import { TabBarToolbarContribution, TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
|
||||
import { CommandContribution, CommandRegistry } from '@theia/core/lib/common/command';
|
||||
import {
|
||||
TabBarToolbarContribution,
|
||||
TabBarToolbarRegistry,
|
||||
} from '@theia/core/lib/browser/shell/tab-bar-toolbar';
|
||||
import {
|
||||
CommandContribution,
|
||||
CommandRegistry,
|
||||
} from '@theia/core/lib/common/command';
|
||||
import { MessageService } from '@theia/core/lib/common/message-service';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import { EditorMainMenu, EditorManager, EditorOpenerOptions } from '@theia/editor/lib/browser';
|
||||
import {
|
||||
EditorMainMenu,
|
||||
EditorManager,
|
||||
EditorOpenerOptions,
|
||||
} from '@theia/editor/lib/browser';
|
||||
import { FileDialogService } from '@theia/filesystem/lib/browser/file-dialog';
|
||||
import { ProblemContribution } from '@theia/markers/lib/browser/problem/problem-contribution';
|
||||
import { MonacoMenus } from '@theia/monaco/lib/browser/monaco-menu';
|
||||
@@ -26,7 +46,14 @@ import { inject, injectable, postConstruct } from 'inversify';
|
||||
import * as React from 'react';
|
||||
import { remote } from 'electron';
|
||||
import { MainMenuManager } from '../common/main-menu-manager';
|
||||
import { BoardsService, CoreService, Port, SketchesService, ExecutableService, Sketch } from '../common/protocol';
|
||||
import {
|
||||
BoardsService,
|
||||
CoreService,
|
||||
Port,
|
||||
SketchesService,
|
||||
ExecutableService,
|
||||
Sketch,
|
||||
} from '../common/protocol';
|
||||
import { ArduinoDaemon } from '../common/protocol/arduino-daemon';
|
||||
import { ConfigService } from '../common/protocol/config-service';
|
||||
import { FileSystemExt } from '../common/protocol/filesystem-ext';
|
||||
@@ -53,9 +80,14 @@ import { FrontendApplicationStateService } from '@theia/core/lib/browser/fronten
|
||||
import { SketchbookWidgetContribution } from './widgets/sketchbook/sketchbook-widget-contribution';
|
||||
|
||||
@injectable()
|
||||
export class ArduinoFrontendContribution implements FrontendApplicationContribution,
|
||||
TabBarToolbarContribution, CommandContribution, MenuContribution, ColorContribution {
|
||||
|
||||
export class ArduinoFrontendContribution
|
||||
implements
|
||||
FrontendApplicationContribution,
|
||||
TabBarToolbarContribution,
|
||||
CommandContribution,
|
||||
MenuContribution,
|
||||
ColorContribution
|
||||
{
|
||||
@inject(ILogger)
|
||||
protected logger: ILogger;
|
||||
|
||||
@@ -167,48 +199,67 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
|
||||
@inject(FrontendApplicationStateService)
|
||||
protected readonly appStateService: FrontendApplicationStateService;
|
||||
|
||||
protected invalidConfigPopup: Promise<void | 'No' | 'Yes' | undefined> | undefined;
|
||||
protected invalidConfigPopup:
|
||||
| Promise<void | 'No' | 'Yes' | undefined>
|
||||
| undefined;
|
||||
protected toDisposeOnStop = new DisposableCollection();
|
||||
|
||||
@postConstruct()
|
||||
protected async init(): Promise<void> {
|
||||
if (!window.navigator.onLine) {
|
||||
// tslint:disable-next-line:max-line-length
|
||||
this.messageService.warn('You appear to be offline. Without an Internet connection, the Arduino CLI might not be able to download the required resources and could cause malfunction. Please connect to the Internet and restart the application.');
|
||||
this.messageService.warn(
|
||||
'You appear to be offline. Without an Internet connection, the Arduino CLI might not be able to download the required resources and could cause malfunction. Please connect to the Internet and restart the application.'
|
||||
);
|
||||
}
|
||||
const updateStatusBar = ({ selectedBoard, selectedPort }: BoardsConfig.Config) => {
|
||||
const updateStatusBar = ({
|
||||
selectedBoard,
|
||||
selectedPort,
|
||||
}: BoardsConfig.Config) => {
|
||||
this.statusBar.setElement('arduino-selected-board', {
|
||||
alignment: StatusBarAlignment.RIGHT,
|
||||
text: selectedBoard ? `$(microchip) ${selectedBoard.name}` : '$(close) no board selected',
|
||||
className: 'arduino-selected-board'
|
||||
text: selectedBoard
|
||||
? `$(microchip) ${selectedBoard.name}`
|
||||
: '$(close) no board selected',
|
||||
className: 'arduino-selected-board',
|
||||
});
|
||||
if (selectedBoard) {
|
||||
this.statusBar.setElement('arduino-selected-port', {
|
||||
alignment: StatusBarAlignment.RIGHT,
|
||||
text: selectedPort ? `on ${Port.toString(selectedPort)}` : '[not connected]',
|
||||
className: 'arduino-selected-port'
|
||||
text: selectedPort
|
||||
? `on ${Port.toString(selectedPort)}`
|
||||
: '[not connected]',
|
||||
className: 'arduino-selected-port',
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
this.boardsServiceClientImpl.onBoardsConfigChanged(updateStatusBar);
|
||||
updateStatusBar(this.boardsServiceClientImpl.boardsConfig);
|
||||
this.appStateService.reachedState('ready').then(async () => {
|
||||
const sketch = await this.sketchServiceClient.currentSketch();
|
||||
if (sketch && (!await this.sketchService.isTemp(sketch))) {
|
||||
if (sketch && !(await this.sketchService.isTemp(sketch))) {
|
||||
this.toDisposeOnStop.push(this.fileService.watch(new URI(sketch.uri)));
|
||||
this.toDisposeOnStop.push(this.fileService.onDidFilesChange(async event => {
|
||||
this.toDisposeOnStop.push(
|
||||
this.fileService.onDidFilesChange(async (event) => {
|
||||
for (const { type, resource } of event.changes) {
|
||||
if (type === FileChangeType.ADDED && resource.parent.toString() === sketch.uri) {
|
||||
const reloadedSketch = await this.sketchService.loadSketch(sketch.uri)
|
||||
if (
|
||||
type === FileChangeType.ADDED &&
|
||||
resource.parent.toString() === sketch.uri
|
||||
) {
|
||||
const reloadedSketch = await this.sketchService.loadSketch(
|
||||
sketch.uri
|
||||
);
|
||||
if (Sketch.isInSketch(resource, reloadedSketch)) {
|
||||
this.ensureOpened(resource.toString(), true, { mode: 'open' });
|
||||
this.ensureOpened(resource.toString(), true, {
|
||||
mode: 'open',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
onStart(app: FrontendApplication): void {
|
||||
@@ -220,7 +271,8 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
|
||||
this.problemContribution,
|
||||
this.scmContribution,
|
||||
this.siwContribution,
|
||||
this.sketchbookWidgetContribution] as Array<FrontendApplicationContribution>) {
|
||||
this.sketchbookWidgetContribution,
|
||||
] as Array<FrontendApplicationContribution>) {
|
||||
if (viewContribution.initializeLayout) {
|
||||
viewContribution.initializeLayout(app);
|
||||
}
|
||||
@@ -234,8 +286,11 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
|
||||
}
|
||||
};
|
||||
this.boardsServiceClientImpl.onBoardsConfigChanged(start);
|
||||
this.arduinoPreferences.onPreferenceChanged(event => {
|
||||
if (event.preferenceName === 'arduino.language.log' && event.newValue !== event.oldValue) {
|
||||
this.arduinoPreferences.onPreferenceChanged((event) => {
|
||||
if (
|
||||
event.preferenceName === 'arduino.language.log' &&
|
||||
event.newValue !== event.oldValue
|
||||
) {
|
||||
start(this.boardsServiceClientImpl.boardsConfig);
|
||||
}
|
||||
});
|
||||
@@ -244,8 +299,12 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
|
||||
const zoomLevel = this.arduinoPreferences.get('arduino.window.zoomLevel');
|
||||
webContents.setZoomLevel(zoomLevel);
|
||||
});
|
||||
this.arduinoPreferences.onPreferenceChanged(event => {
|
||||
if (event.preferenceName === 'arduino.window.zoomLevel' && typeof event.newValue === 'number' && event.newValue !== event.oldValue) {
|
||||
this.arduinoPreferences.onPreferenceChanged((event) => {
|
||||
if (
|
||||
event.preferenceName === 'arduino.window.zoomLevel' &&
|
||||
typeof event.newValue === 'number' &&
|
||||
event.newValue !== event.oldValue
|
||||
) {
|
||||
const webContents = remote.getCurrentWebContents();
|
||||
webContents.setZoomLevel(event.newValue || 0);
|
||||
}
|
||||
@@ -259,21 +318,33 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
|
||||
|
||||
protected languageServerFqbn?: string;
|
||||
protected languageServerStartMutex = new Mutex();
|
||||
protected async startLanguageServer(fqbn: string, name: string | undefined): Promise<void> {
|
||||
protected async startLanguageServer(
|
||||
fqbn: string,
|
||||
name: string | undefined
|
||||
): Promise<void> {
|
||||
const release = await this.languageServerStartMutex.acquire();
|
||||
try {
|
||||
await this.hostedPluginSupport.didStart;
|
||||
const details = await this.boardsService.getBoardDetails({ fqbn });
|
||||
if (!details) {
|
||||
// Core is not installed for the selected board.
|
||||
console.info(`Could not start language server for ${fqbn}. The core is not installed for the board.`);
|
||||
console.info(
|
||||
`Could not start language server for ${fqbn}. The core is not installed for the board.`
|
||||
);
|
||||
if (this.languageServerFqbn) {
|
||||
try {
|
||||
await this.commandRegistry.executeCommand('arduino.languageserver.stop');
|
||||
console.info(`Stopped language server process for ${this.languageServerFqbn}.`);
|
||||
await this.commandRegistry.executeCommand(
|
||||
'arduino.languageserver.stop'
|
||||
);
|
||||
console.info(
|
||||
`Stopped language server process for ${this.languageServerFqbn}.`
|
||||
);
|
||||
this.languageServerFqbn = undefined;
|
||||
} catch (e) {
|
||||
console.error(`Failed to start language server process for ${this.languageServerFqbn}`, e);
|
||||
console.error(
|
||||
`Failed to start language server process for ${this.languageServerFqbn}`,
|
||||
e
|
||||
);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@@ -289,7 +360,9 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
|
||||
if (log) {
|
||||
const currentSketch = await this.sketchServiceClient.currentSketch();
|
||||
if (currentSketch) {
|
||||
currentSketchPath = await this.fileService.fsPath(new URI(currentSketch.uri));
|
||||
currentSketchPath = await this.fileService.fsPath(
|
||||
new URI(currentSketch.uri)
|
||||
);
|
||||
}
|
||||
}
|
||||
const { clangdUri, cliUri, lsUri } = await this.executableService.list();
|
||||
@@ -297,11 +370,20 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
|
||||
this.fileService.fsPath(new URI(clangdUri)),
|
||||
this.fileService.fsPath(new URI(cliUri)),
|
||||
this.fileService.fsPath(new URI(lsUri)),
|
||||
this.fileService.fsPath(new URI(await this.configService.getCliConfigFileUri()))
|
||||
this.fileService.fsPath(
|
||||
new URI(await this.configService.getCliConfigFileUri())
|
||||
),
|
||||
]);
|
||||
this.languageServerFqbn = await Promise.race([
|
||||
new Promise<undefined>((_, reject) => setTimeout(() => reject(new Error(`Timeout after ${20_000} ms.`)), 20_000)),
|
||||
this.commandRegistry.executeCommand<string>('arduino.languageserver.start', {
|
||||
new Promise<undefined>((_, reject) =>
|
||||
setTimeout(
|
||||
() => reject(new Error(`Timeout after ${20_000} ms.`)),
|
||||
20_000
|
||||
)
|
||||
),
|
||||
this.commandRegistry.executeCommand<string>(
|
||||
'arduino.languageserver.start',
|
||||
{
|
||||
lsPath,
|
||||
cliPath,
|
||||
clangdPath,
|
||||
@@ -309,9 +391,10 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
|
||||
cliConfigPath,
|
||||
board: {
|
||||
fqbn,
|
||||
name: name ? `"${name}"` : undefined
|
||||
name: name ? `"${name}"` : undefined,
|
||||
},
|
||||
}
|
||||
})
|
||||
),
|
||||
]);
|
||||
} catch (e) {
|
||||
console.log(`Failed to start language server for ${fqbn}`, e);
|
||||
@@ -324,29 +407,33 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
|
||||
registerToolbarItems(registry: TabBarToolbarRegistry): void {
|
||||
registry.registerItem({
|
||||
id: BoardsToolBarItem.TOOLBAR_ID,
|
||||
render: () => <BoardsToolBarItem
|
||||
key='boardsToolbarItem'
|
||||
render: () => (
|
||||
<BoardsToolBarItem
|
||||
key="boardsToolbarItem"
|
||||
commands={this.commandRegistry}
|
||||
boardsServiceClient={this.boardsServiceClientImpl} />,
|
||||
isVisible: widget => ArduinoToolbar.is(widget) && widget.side === 'left',
|
||||
priority: 7
|
||||
boardsServiceClient={this.boardsServiceClientImpl}
|
||||
/>
|
||||
),
|
||||
isVisible: (widget) =>
|
||||
ArduinoToolbar.is(widget) && widget.side === 'left',
|
||||
priority: 7,
|
||||
});
|
||||
registry.registerItem({
|
||||
id: 'toggle-serial-monitor',
|
||||
command: MonitorViewContribution.TOGGLE_SERIAL_MONITOR_TOOLBAR,
|
||||
tooltip: 'Serial Monitor'
|
||||
tooltip: 'Serial Monitor',
|
||||
});
|
||||
}
|
||||
|
||||
registerCommands(registry: CommandRegistry): void {
|
||||
registry.registerCommand(ArduinoCommands.TOGGLE_COMPILE_FOR_DEBUG, {
|
||||
execute: () => this.editorMode.toggleCompileForDebug(),
|
||||
isToggled: () => this.editorMode.compileForDebug
|
||||
isToggled: () => this.editorMode.compileForDebug,
|
||||
});
|
||||
registry.registerCommand(ArduinoCommands.OPEN_SKETCH_FILES, {
|
||||
execute: async (uri: URI) => {
|
||||
this.openSketchFiles(uri);
|
||||
}
|
||||
},
|
||||
});
|
||||
registry.registerCommand(ArduinoCommands.OPEN_BOARDS_DIALOG, {
|
||||
execute: async (query?: string | undefined) => {
|
||||
@@ -354,7 +441,7 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
|
||||
if (boardsConfig) {
|
||||
this.boardsServiceClientImpl.boardsConfig = boardsConfig;
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -363,7 +450,7 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
|
||||
const index = menuPath.length - 1;
|
||||
const menuId = menuPath[index];
|
||||
return menuId;
|
||||
}
|
||||
};
|
||||
registry.getMenu(MAIN_MENU_BAR).removeNode(menuId(MonacoMenus.SELECTION));
|
||||
registry.getMenu(MAIN_MENU_BAR).removeNode(menuId(EditorMainMenu.GO));
|
||||
registry.getMenu(MAIN_MENU_BAR).removeNode(menuId(TerminalMenus.TERMINAL));
|
||||
@@ -374,7 +461,7 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
|
||||
registry.registerMenuAction(ArduinoMenus.SKETCH__MAIN_GROUP, {
|
||||
commandId: ArduinoCommands.TOGGLE_COMPILE_FOR_DEBUG.id,
|
||||
label: 'Optimize for Debugging',
|
||||
order: '4'
|
||||
order: '4',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -388,9 +475,18 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
|
||||
await this.ensureOpened(mainFileUri, true);
|
||||
if (mainFileUri.endsWith('.pde')) {
|
||||
const message = `The '${sketch.name}' still uses the old \`.pde\` format. Do you want to switch to the new \`.ino\` extension?`;
|
||||
this.messageService.info(message, 'Later', 'Yes').then(async answer => {
|
||||
this.messageService
|
||||
.info(message, 'Later', 'Yes')
|
||||
.then(async (answer) => {
|
||||
if (answer === 'Yes') {
|
||||
this.commandRegistry.executeCommand(SaveAsSketch.Commands.SAVE_AS_SKETCH.id, { execOnlyIfTemp: false, openAfterMove: true, wipeOriginal: false });
|
||||
this.commandRegistry.executeCommand(
|
||||
SaveAsSketch.Commands.SAVE_AS_SKETCH.id,
|
||||
{
|
||||
execOnlyIfTemp: false,
|
||||
openAfterMove: true,
|
||||
wipeOriginal: false,
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -401,8 +497,14 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
|
||||
}
|
||||
}
|
||||
|
||||
protected async ensureOpened(uri: string, forceOpen = false, options?: EditorOpenerOptions | undefined): Promise<any> {
|
||||
const widget = this.editorManager.all.find(widget => widget.editor.uri.toString() === uri);
|
||||
protected async ensureOpened(
|
||||
uri: string,
|
||||
forceOpen = false,
|
||||
options?: EditorOpenerOptions | undefined
|
||||
): Promise<any> {
|
||||
const widget = this.editorManager.all.find(
|
||||
(widget) => widget.editor.uri.toString() === uri
|
||||
);
|
||||
if (!widget || forceOpen) {
|
||||
return this.editorManager.open(new URI(uri), options);
|
||||
}
|
||||
@@ -414,73 +516,78 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
|
||||
id: 'arduino.branding.primary',
|
||||
defaults: {
|
||||
dark: 'statusBar.background',
|
||||
light: 'statusBar.background'
|
||||
light: 'statusBar.background',
|
||||
},
|
||||
description: 'The primary branding color, such as dialog titles, library, and board manager list labels.'
|
||||
description:
|
||||
'The primary branding color, such as dialog titles, library, and board manager list labels.',
|
||||
},
|
||||
{
|
||||
id: 'arduino.branding.secondary',
|
||||
defaults: {
|
||||
dark: 'statusBar.background',
|
||||
light: 'statusBar.background'
|
||||
light: 'statusBar.background',
|
||||
},
|
||||
description: 'Secondary branding color for list selections, dropdowns, and widget borders.'
|
||||
description:
|
||||
'Secondary branding color for list selections, dropdowns, and widget borders.',
|
||||
},
|
||||
{
|
||||
id: 'arduino.foreground',
|
||||
defaults: {
|
||||
dark: 'editorWidget.background',
|
||||
light: 'editorWidget.background',
|
||||
hc: 'editorWidget.background'
|
||||
hc: 'editorWidget.background',
|
||||
},
|
||||
description: 'Color of the Arduino IDE foreground which is used for dialogs, such as the Select Board dialog.'
|
||||
description:
|
||||
'Color of the Arduino IDE foreground which is used for dialogs, such as the Select Board dialog.',
|
||||
},
|
||||
{
|
||||
id: 'arduino.toolbar.background',
|
||||
defaults: {
|
||||
dark: 'button.background',
|
||||
light: 'button.background',
|
||||
hc: 'activityBar.inactiveForeground'
|
||||
hc: 'activityBar.inactiveForeground',
|
||||
},
|
||||
description: 'Background color of the toolbar items. Such as Upload, Verify, etc.'
|
||||
description:
|
||||
'Background color of the toolbar items. Such as Upload, Verify, etc.',
|
||||
},
|
||||
{
|
||||
id: 'arduino.toolbar.hoverBackground',
|
||||
defaults: {
|
||||
dark: 'button.hoverBackground',
|
||||
light: 'button.foreground',
|
||||
hc: 'textLink.foreground'
|
||||
hc: 'textLink.foreground',
|
||||
},
|
||||
description: 'Background color of the toolbar items when hovering over them. Such as Upload, Verify, etc.'
|
||||
description:
|
||||
'Background color of the toolbar items when hovering over them. Such as Upload, Verify, etc.',
|
||||
},
|
||||
{
|
||||
id: 'arduino.toolbar.toggleBackground',
|
||||
defaults: {
|
||||
dark: 'editor.selectionBackground',
|
||||
light: 'editor.selectionBackground',
|
||||
hc: 'textPreformat.foreground'
|
||||
hc: 'textPreformat.foreground',
|
||||
},
|
||||
description: 'Toggle color of the toolbar items when they are currently toggled (the command is in progress)'
|
||||
description:
|
||||
'Toggle color of the toolbar items when they are currently toggled (the command is in progress)',
|
||||
},
|
||||
{
|
||||
id: 'arduino.output.foreground',
|
||||
defaults: {
|
||||
dark: 'editor.foreground',
|
||||
light: 'editor.foreground',
|
||||
hc: 'editor.foreground'
|
||||
hc: 'editor.foreground',
|
||||
},
|
||||
description: 'Color of the text in the Output view.'
|
||||
description: 'Color of the text in the Output view.',
|
||||
},
|
||||
{
|
||||
id: 'arduino.output.background',
|
||||
defaults: {
|
||||
dark: 'editor.background',
|
||||
light: 'editor.background',
|
||||
hc: 'editor.background'
|
||||
hc: 'editor.background',
|
||||
},
|
||||
description: 'Background color of the Output view.'
|
||||
description: 'Background color of the Output view.',
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -255,9 +255,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
bind(CommandContribution).toService(ArduinoFrontendContribution);
|
||||
bind(MenuContribution).toService(ArduinoFrontendContribution);
|
||||
bind(TabBarToolbarContribution).toService(ArduinoFrontendContribution);
|
||||
bind(FrontendApplicationContribution).toService(
|
||||
ArduinoFrontendContribution
|
||||
);
|
||||
bind(FrontendApplicationContribution).toService(ArduinoFrontendContribution);
|
||||
bind(ColorContribution).toService(ArduinoFrontendContribution);
|
||||
|
||||
bind(ArduinoToolbarContribution).toSelf().inSingletonScope();
|
||||
@@ -382,9 +380,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
// Frontend binding for the serial monitor service
|
||||
bind(MonitorService)
|
||||
.toDynamicValue((context) => {
|
||||
const connection = context.container.get(
|
||||
WebSocketConnectionProvider
|
||||
);
|
||||
const connection = context.container.get(WebSocketConnectionProvider);
|
||||
const client = context.container.get(MonitorServiceClientImpl);
|
||||
return connection.createProxy(MonitorServicePath, client);
|
||||
})
|
||||
@@ -647,8 +643,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
.toDynamicValue(
|
||||
({ container }) =>
|
||||
<DebugEditorModelFactory>(
|
||||
((editor) =>
|
||||
DebugEditorModel.createModel(container, editor))
|
||||
((editor) => DebugEditorModel.createModel(container, editor))
|
||||
)
|
||||
)
|
||||
.inSingletonScope();
|
||||
@@ -679,9 +674,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
createSketchbookTreeWidget(container)
|
||||
);
|
||||
bindViewContribution(bind, SketchbookWidgetContribution);
|
||||
bind(FrontendApplicationContribution).toService(
|
||||
SketchbookWidgetContribution
|
||||
);
|
||||
bind(FrontendApplicationContribution).toService(SketchbookWidgetContribution);
|
||||
bind(WidgetFactory).toDynamicValue(({ container }) => ({
|
||||
id: 'arduino-sketchbook-widget',
|
||||
createWidget: () => container.get(SketchbookWidget),
|
||||
@@ -696,9 +689,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
bind(ShareSketchDialog).toSelf().inSingletonScope();
|
||||
bind(AuthenticationClientService).toSelf().inSingletonScope();
|
||||
bind(CommandContribution).toService(AuthenticationClientService);
|
||||
bind(FrontendApplicationContribution).toService(
|
||||
AuthenticationClientService
|
||||
);
|
||||
bind(FrontendApplicationContribution).toService(AuthenticationClientService);
|
||||
bind(AuthenticationService)
|
||||
.toDynamicValue((context) =>
|
||||
WebSocketConnectionProvider.createProxy(
|
||||
|
@@ -146,8 +146,7 @@ export function createArduinoPreferences(
|
||||
|
||||
export function bindArduinoPreferences(bind: interfaces.Bind): void {
|
||||
bind(ArduinoPreferences).toDynamicValue((ctx) => {
|
||||
const preferences =
|
||||
ctx.container.get<PreferenceService>(PreferenceService);
|
||||
const preferences = ctx.container.get<PreferenceService>(PreferenceService);
|
||||
return createArduinoPreferences(preferences);
|
||||
});
|
||||
bind(PreferenceContribution).toConstantValue({
|
||||
|
@@ -47,9 +47,7 @@ export class BoardsAutoInstaller implements FrontendApplicationContribution {
|
||||
const { selectedBoard } = config;
|
||||
if (
|
||||
selectedBoard &&
|
||||
!this.notifications.find((board) =>
|
||||
Board.sameAs(board, selectedBoard)
|
||||
)
|
||||
!this.notifications.find((board) => Board.sameAs(board, selectedBoard))
|
||||
) {
|
||||
this.notifications.push(selectedBoard);
|
||||
this.boardsService.search({}).then((packages) => {
|
||||
@@ -60,16 +58,12 @@ export class BoardsAutoInstaller implements FrontendApplicationContribution {
|
||||
const packagesForBoard = packages.filter(
|
||||
(pkg) =>
|
||||
BoardsPackage.contains(selectedBoard, pkg) ||
|
||||
pkg.boards.some(
|
||||
(board) => board.name === selectedBoard.name
|
||||
)
|
||||
pkg.boards.some((board) => board.name === selectedBoard.name)
|
||||
);
|
||||
|
||||
// check if one of the packages for the board is already installed. if so, no hint
|
||||
if (
|
||||
packagesForBoard.some(
|
||||
({ installedVersion }) => !!installedVersion
|
||||
)
|
||||
packagesForBoard.some(({ installedVersion }) => !!installedVersion)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -95,8 +89,8 @@ export class BoardsAutoInstaller implements FrontendApplicationContribution {
|
||||
'Yes'
|
||||
)
|
||||
.then(async (answer) => {
|
||||
const index = this.notifications.findIndex(
|
||||
(board) => Board.sameAs(board, selectedBoard)
|
||||
const index = this.notifications.findIndex((board) =>
|
||||
Board.sameAs(board, selectedBoard)
|
||||
);
|
||||
if (index !== -1) {
|
||||
this.notifications.splice(index, 1);
|
||||
@@ -115,9 +109,7 @@ export class BoardsAutoInstaller implements FrontendApplicationContribution {
|
||||
this.boardsManagerFrontendContribution
|
||||
.openView({ reveal: true })
|
||||
.then((widget) =>
|
||||
widget.refresh(
|
||||
candidate.name.toLocaleLowerCase()
|
||||
)
|
||||
widget.refresh(candidate.name.toLocaleLowerCase())
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@@ -54,9 +54,7 @@ export class BoardsConfigDialogWidget extends ReactWidget {
|
||||
notificationCenter={this.notificationCenter}
|
||||
onConfigChange={this.fireConfigChanged}
|
||||
onFocusNodeSet={this.setFocusNode}
|
||||
onFilteredTextDidChangeEvent={
|
||||
this.onFilterTextDidChangeEmitter.event
|
||||
}
|
||||
onFilteredTextDidChangeEvent={this.onFilterTextDidChangeEmitter.event}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@@ -131,9 +131,7 @@ export class BoardsConfig extends React.Component<
|
||||
this.setState({ searchResults: [] })
|
||||
),
|
||||
this.props.onFilteredTextDidChangeEvent((query) =>
|
||||
this.setState({ query }, () =>
|
||||
this.updateBoards(this.state.query)
|
||||
)
|
||||
this.setState({ query }, () => this.updateBoards(this.state.query))
|
||||
),
|
||||
]);
|
||||
}
|
||||
@@ -231,9 +229,7 @@ export class BoardsConfig extends React.Component<
|
||||
<div className="content">
|
||||
<div className="title">{title}</div>
|
||||
{contentRenderer()}
|
||||
<div className="footer">
|
||||
{footerRenderer ? footerRenderer() : ''}
|
||||
</div>
|
||||
<div className="footer">{footerRenderer ? footerRenderer() : ''}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -245,13 +241,8 @@ export class BoardsConfig extends React.Component<
|
||||
// It is tricky when the core is not yet installed, no FQBNs are available.
|
||||
const distinctBoards = new Map<string, Board.Detailed>();
|
||||
const toKey = ({ name, packageName, fqbn }: Board.Detailed) =>
|
||||
!!fqbn
|
||||
? `${name}-${packageName}-${fqbn}`
|
||||
: `${name}-${packageName}`;
|
||||
for (const board of Board.decorateBoards(
|
||||
selectedBoard,
|
||||
searchResults
|
||||
)) {
|
||||
!!fqbn ? `${name}-${packageName}-${fqbn}` : `${name}-${packageName}`;
|
||||
for (const board of Board.decorateBoards(selectedBoard, searchResults)) {
|
||||
const key = toKey(board);
|
||||
if (!distinctBoards.has(key)) {
|
||||
distinctBoards.set(key, board);
|
||||
@@ -380,10 +371,7 @@ export namespace BoardsConfig {
|
||||
}
|
||||
: undefined;
|
||||
const jsonConfig = JSON.stringify({ selectedBoard, selectedPort });
|
||||
copy.searchParams.set(
|
||||
'boards-config',
|
||||
encodeURIComponent(jsonConfig)
|
||||
);
|
||||
copy.searchParams.set('boards-config', encodeURIComponent(jsonConfig));
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
@@ -34,9 +34,7 @@ export class BoardsDataMenuUpdater implements FrontendApplicationContribution {
|
||||
protected readonly toDisposeOnBoardChange = new DisposableCollection();
|
||||
|
||||
async onStart(): Promise<void> {
|
||||
this.updateMenuActions(
|
||||
this.boardsServiceClient.boardsConfig.selectedBoard
|
||||
);
|
||||
this.updateMenuActions(this.boardsServiceClient.boardsConfig.selectedBoard);
|
||||
this.boardsDataStore.onChanged(() =>
|
||||
this.updateMenuActions(
|
||||
this.boardsServiceClient.boardsConfig.selectedBoard
|
||||
@@ -63,17 +61,10 @@ export class BoardsDataMenuUpdater implements FrontendApplicationContribution {
|
||||
...ArduinoMenus.TOOLS__BOARD_SETTINGS_GROUP,
|
||||
'z01_boardsConfig',
|
||||
]; // `z_` is for ordering.
|
||||
for (const {
|
||||
label,
|
||||
option,
|
||||
values,
|
||||
} of configOptions.sort(
|
||||
for (const { label, option, values } of configOptions.sort(
|
||||
ConfigOption.LABEL_COMPARATOR
|
||||
)) {
|
||||
const menuPath = [
|
||||
...boardsConfigMenuPath,
|
||||
`${option}`,
|
||||
];
|
||||
const menuPath = [...boardsConfigMenuPath, `${option}`];
|
||||
const commands = new Map<
|
||||
string,
|
||||
Disposable & { label: string }
|
||||
@@ -84,18 +75,17 @@ export class BoardsDataMenuUpdater implements FrontendApplicationContribution {
|
||||
const selectedValue = value.value;
|
||||
const handler = {
|
||||
execute: () =>
|
||||
this.boardsDataStore.selectConfigOption(
|
||||
{ fqbn, option, selectedValue }
|
||||
),
|
||||
this.boardsDataStore.selectConfigOption({
|
||||
fqbn,
|
||||
option,
|
||||
selectedValue,
|
||||
}),
|
||||
isToggled: () => value.selected,
|
||||
};
|
||||
commands.set(
|
||||
id,
|
||||
Object.assign(
|
||||
this.commandRegistry.registerCommand(
|
||||
command,
|
||||
handler
|
||||
),
|
||||
this.commandRegistry.registerCommand(command, handler),
|
||||
{ label: value.label }
|
||||
)
|
||||
);
|
||||
@@ -104,26 +94,19 @@ export class BoardsDataMenuUpdater implements FrontendApplicationContribution {
|
||||
this.toDisposeOnBoardChange.pushAll([
|
||||
...commands.values(),
|
||||
Disposable.create(() =>
|
||||
unregisterSubmenu(
|
||||
menuPath,
|
||||
this.menuRegistry
|
||||
)
|
||||
unregisterSubmenu(menuPath, this.menuRegistry)
|
||||
),
|
||||
...Array.from(commands.keys()).map(
|
||||
(commandId, i) => {
|
||||
const { label } =
|
||||
commands.get(commandId)!;
|
||||
this.menuRegistry.registerMenuAction(
|
||||
menuPath,
|
||||
{ commandId, order: `${i}`, label }
|
||||
);
|
||||
...Array.from(commands.keys()).map((commandId, i) => {
|
||||
const { label } = commands.get(commandId)!;
|
||||
this.menuRegistry.registerMenuAction(menuPath, {
|
||||
commandId,
|
||||
order: `${i}`,
|
||||
label,
|
||||
});
|
||||
return Disposable.create(() =>
|
||||
this.menuRegistry.unregisterMenuAction(
|
||||
commandId
|
||||
)
|
||||
this.menuRegistry.unregisterMenuAction(commandId)
|
||||
);
|
||||
}
|
||||
),
|
||||
}),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -135,16 +118,10 @@ export class BoardsDataMenuUpdater implements FrontendApplicationContribution {
|
||||
const label = selectedProgrammer
|
||||
? `Programmer: "${selectedProgrammer.name}"`
|
||||
: 'Programmer';
|
||||
this.menuRegistry.registerSubmenu(
|
||||
programmersMenuPath,
|
||||
label
|
||||
);
|
||||
this.menuRegistry.registerSubmenu(programmersMenuPath, label);
|
||||
this.toDisposeOnBoardChange.push(
|
||||
Disposable.create(() =>
|
||||
unregisterSubmenu(
|
||||
programmersMenuPath,
|
||||
this.menuRegistry
|
||||
)
|
||||
unregisterSubmenu(programmersMenuPath, this.menuRegistry)
|
||||
)
|
||||
);
|
||||
for (const programmer of programmers) {
|
||||
@@ -157,29 +134,19 @@ export class BoardsDataMenuUpdater implements FrontendApplicationContribution {
|
||||
selectedProgrammer: programmer,
|
||||
}),
|
||||
isToggled: () =>
|
||||
Programmer.equals(
|
||||
programmer,
|
||||
selectedProgrammer
|
||||
),
|
||||
Programmer.equals(programmer, selectedProgrammer),
|
||||
};
|
||||
this.menuRegistry.registerMenuAction(
|
||||
programmersMenuPath,
|
||||
{ commandId: command.id, label: name }
|
||||
);
|
||||
this.commandRegistry.registerCommand(
|
||||
command,
|
||||
handler
|
||||
);
|
||||
this.menuRegistry.registerMenuAction(programmersMenuPath, {
|
||||
commandId: command.id,
|
||||
label: name,
|
||||
});
|
||||
this.commandRegistry.registerCommand(command, handler);
|
||||
this.toDisposeOnBoardChange.pushAll([
|
||||
Disposable.create(() =>
|
||||
this.commandRegistry.unregisterCommand(
|
||||
command
|
||||
)
|
||||
this.commandRegistry.unregisterCommand(command)
|
||||
),
|
||||
Disposable.create(() =>
|
||||
this.menuRegistry.unregisterMenuAction(
|
||||
command.id
|
||||
)
|
||||
this.menuRegistry.unregisterMenuAction(command.id)
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
@@ -80,10 +80,7 @@ export class BoardsDataStore implements FrontendApplicationContribution {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const { configOptions } = await this.getData(
|
||||
fqbn,
|
||||
boardsPackageVersion
|
||||
);
|
||||
const { configOptions } = await this.getData(fqbn, boardsPackageVersion);
|
||||
return ConfigOption.decorate(fqbn, configOptions);
|
||||
}
|
||||
|
||||
@@ -133,9 +130,7 @@ export class BoardsDataStore implements FrontendApplicationContribution {
|
||||
): Promise<boolean> {
|
||||
const data = deepClone(await this.getData(fqbn, boardsPackageVersion));
|
||||
const { programmers } = data;
|
||||
if (
|
||||
!programmers.find((p) => Programmer.equals(selectedProgrammer, p))
|
||||
) {
|
||||
if (!programmers.find((p) => Programmer.equals(selectedProgrammer, p))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -204,10 +199,7 @@ export class BoardsDataStore implements FrontendApplicationContribution {
|
||||
return this.storageService.setData(key, data);
|
||||
}
|
||||
|
||||
protected getStorageKey(
|
||||
fqbn: string,
|
||||
version: Installable.Version
|
||||
): string {
|
||||
protected getStorageKey(fqbn: string, version: Installable.Version): string {
|
||||
return `.arduinoIDE-configOptions-${version}-${fqbn}`;
|
||||
}
|
||||
|
||||
@@ -246,9 +238,9 @@ export class BoardsDataStore implements FrontendApplicationContribution {
|
||||
if (!fqbn) {
|
||||
return undefined;
|
||||
}
|
||||
const boardsPackage = await this.boardsService.getContainerBoardPackage(
|
||||
{ fqbn }
|
||||
);
|
||||
const boardsPackage = await this.boardsService.getContainerBoardPackage({
|
||||
fqbn,
|
||||
});
|
||||
if (!boardsPackage) {
|
||||
return undefined;
|
||||
}
|
||||
|
@@ -114,8 +114,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
);
|
||||
if (
|
||||
installedBoard &&
|
||||
(!selectedBoard.fqbn ||
|
||||
selectedBoard.fqbn === installedBoard.fqbn)
|
||||
(!selectedBoard.fqbn || selectedBoard.fqbn === installedBoard.fqbn)
|
||||
) {
|
||||
this.logger.info(
|
||||
`Board package ${id}[${installedVersion}] was installed. Updating the FQBN of the currently selected ${selectedBoard.name} board. [FQBN: ${installedBoard.fqbn}]`
|
||||
@@ -165,10 +164,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
const uninstalledBoard = event.item.boards.find(
|
||||
({ name }) => name === selectedBoard.name
|
||||
);
|
||||
if (
|
||||
uninstalledBoard &&
|
||||
uninstalledBoard.fqbn === selectedBoard.fqbn
|
||||
) {
|
||||
if (uninstalledBoard && uninstalledBoard.fqbn === selectedBoard.fqbn) {
|
||||
// We should not unset the FQBN, if the selected board is an attached, recognized board.
|
||||
// Attach Uno and install AVR, select Uno. Uninstall the AVR core while Uno is selected. We do not want to discard the FQBN of the Uno board.
|
||||
// Dev note: We cannot assume the `selectedBoard` is a type of `AvailableBoard`.
|
||||
@@ -182,8 +178,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
if (
|
||||
selectedAvailableBoard &&
|
||||
selectedAvailableBoard.selected &&
|
||||
selectedAvailableBoard.state ===
|
||||
AvailableBoard.State.recognized
|
||||
selectedAvailableBoard.state === AvailableBoard.State.recognized
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -203,22 +198,14 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
}
|
||||
|
||||
protected async tryReconnect(): Promise<boolean> {
|
||||
if (
|
||||
this.latestValidBoardsConfig &&
|
||||
!this.canUploadTo(this.boardsConfig)
|
||||
) {
|
||||
if (this.latestValidBoardsConfig && !this.canUploadTo(this.boardsConfig)) {
|
||||
for (const board of this.availableBoards.filter(
|
||||
({ state }) => state !== AvailableBoard.State.incomplete
|
||||
)) {
|
||||
if (
|
||||
this.latestValidBoardsConfig.selectedBoard.fqbn ===
|
||||
board.fqbn &&
|
||||
this.latestValidBoardsConfig.selectedBoard.name ===
|
||||
board.name &&
|
||||
Port.sameAs(
|
||||
this.latestValidBoardsConfig.selectedPort,
|
||||
board.port
|
||||
)
|
||||
this.latestValidBoardsConfig.selectedBoard.fqbn === board.fqbn &&
|
||||
this.latestValidBoardsConfig.selectedBoard.name === board.name &&
|
||||
Port.sameAs(this.latestValidBoardsConfig.selectedPort, board.port)
|
||||
) {
|
||||
this.boardsConfig = this.latestValidBoardsConfig;
|
||||
return true;
|
||||
@@ -230,10 +217,8 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
({ state }) => state !== AvailableBoard.State.incomplete
|
||||
)) {
|
||||
if (
|
||||
this.latestValidBoardsConfig.selectedBoard.fqbn ===
|
||||
board.fqbn &&
|
||||
this.latestValidBoardsConfig.selectedBoard.name ===
|
||||
board.name
|
||||
this.latestValidBoardsConfig.selectedBoard.fqbn === board.fqbn &&
|
||||
this.latestValidBoardsConfig.selectedBoard.name === board.name
|
||||
) {
|
||||
this.boardsConfig = {
|
||||
...this.latestValidBoardsConfig,
|
||||
@@ -316,10 +301,9 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
const { name } = config.selectedBoard;
|
||||
if (!config.selectedPort) {
|
||||
if (!options.silent) {
|
||||
this.messageService.warn(
|
||||
`No ports selected for board: '${name}'.`,
|
||||
{ timeout: 3000 }
|
||||
);
|
||||
this.messageService.warn(`No ports selected for board: '${name}'.`, {
|
||||
timeout: 3000,
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -345,21 +329,16 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
what: Board & { port: Port },
|
||||
timeout?: number
|
||||
): Promise<void> {
|
||||
const find = (
|
||||
needle: Board & { port: Port },
|
||||
haystack: AvailableBoard[]
|
||||
) =>
|
||||
const find = (needle: Board & { port: Port }, haystack: AvailableBoard[]) =>
|
||||
haystack.find(
|
||||
(board) =>
|
||||
Board.equals(needle, board) &&
|
||||
Port.equals(needle.port, board.port)
|
||||
Board.equals(needle, board) && Port.equals(needle.port, board.port)
|
||||
);
|
||||
const timeoutTask =
|
||||
!!timeout && timeout > 0
|
||||
? new Promise<void>((_, reject) =>
|
||||
setTimeout(
|
||||
() =>
|
||||
reject(new Error(`Timeout after ${timeout} ms.`)),
|
||||
() => reject(new Error(`Timeout after ${timeout} ms.`)),
|
||||
timeout
|
||||
)
|
||||
)
|
||||
@@ -372,15 +351,13 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
const disposable = this.onAvailableBoardsChanged(
|
||||
(availableBoards) => {
|
||||
const disposable = this.onAvailableBoardsChanged((availableBoards) => {
|
||||
candidate = find(what, availableBoards);
|
||||
if (candidate) {
|
||||
disposable.dispose();
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
return await Promise.race([waitUntilTask, timeoutTask]);
|
||||
}
|
||||
@@ -405,9 +382,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
const currentAvailableBoards = this._availableBoards;
|
||||
const availableBoards: AvailableBoard[] = [];
|
||||
const availableBoardPorts = availablePorts.filter(Port.isBoardPort);
|
||||
const attachedSerialBoards = attachedBoards.filter(
|
||||
({ port }) => !!port
|
||||
);
|
||||
const attachedSerialBoards = attachedBoards.filter(({ port }) => !!port);
|
||||
|
||||
for (const boardPort of availableBoardPorts) {
|
||||
let state = AvailableBoard.State.incomplete; // Initial pessimism.
|
||||
@@ -437,10 +412,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
state,
|
||||
});
|
||||
} else {
|
||||
const selected = BoardsConfig.Config.sameAs(
|
||||
boardsConfig,
|
||||
board
|
||||
);
|
||||
const selected = BoardsConfig.Config.sameAs(boardsConfig, board);
|
||||
availableBoards.push({
|
||||
...board,
|
||||
state,
|
||||
@@ -462,9 +434,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
});
|
||||
}
|
||||
|
||||
const sortedAvailableBoards = availableBoards.sort(
|
||||
AvailableBoard.compare
|
||||
);
|
||||
const sortedAvailableBoards = availableBoards.sort(AvailableBoard.compare);
|
||||
let hasChanged =
|
||||
sortedAvailableBoards.length !== currentAvailableBoards.length;
|
||||
for (let i = 0; !hasChanged && i < sortedAvailableBoards.length; i++) {
|
||||
@@ -501,10 +471,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
await this.setData(key, selectedBoard);
|
||||
}
|
||||
await Promise.all([
|
||||
this.setData(
|
||||
'latest-valid-boards-config',
|
||||
this.latestValidBoardsConfig
|
||||
),
|
||||
this.setData('latest-valid-boards-config', this.latestValidBoardsConfig),
|
||||
this.setData('latest-boards-config', this.latestBoardsConfig),
|
||||
]);
|
||||
}
|
||||
|
@@ -20,9 +20,7 @@ export interface BoardsDropDownListCoords {
|
||||
export namespace BoardsDropDown {
|
||||
export interface Props {
|
||||
readonly coords: BoardsDropDownListCoords | 'hidden';
|
||||
readonly items: Array<
|
||||
AvailableBoard & { onClick: () => void; port: Port }
|
||||
>;
|
||||
readonly items: Array<AvailableBoard & { onClick: () => void; port: Port }>;
|
||||
readonly openBoardsConfig: () => void;
|
||||
}
|
||||
}
|
||||
@@ -86,9 +84,7 @@ export class BoardsDropDown extends React.Component<BoardsDropDown.Props> {
|
||||
return (
|
||||
<div
|
||||
key={label}
|
||||
className={`arduino-boards-dropdown-item ${
|
||||
selected ? 'selected' : ''
|
||||
}`}
|
||||
className={`arduino-boards-dropdown-item ${selected ? 'selected' : ''}`}
|
||||
onClick={onClick}
|
||||
>
|
||||
<div>{label}</div>
|
||||
@@ -122,8 +118,8 @@ export class BoardsToolBarItem extends React.Component<
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.props.boardsServiceClient.onAvailableBoardsChanged(
|
||||
(availableBoards) => this.setState({ availableBoards })
|
||||
this.props.boardsServiceClient.onAvailableBoardsChanged((availableBoards) =>
|
||||
this.setState({ availableBoards })
|
||||
);
|
||||
}
|
||||
|
||||
@@ -159,9 +155,7 @@ export class BoardsToolBarItem extends React.Component<
|
||||
default: 'no board selected',
|
||||
});
|
||||
const decorator = (() => {
|
||||
const selectedBoard = availableBoards.find(
|
||||
({ selected }) => selected
|
||||
);
|
||||
const selectedBoard = availableBoards.find(({ selected }) => selected);
|
||||
if (!selectedBoard || !selectedBoard.port) {
|
||||
return 'fa fa-times notAttached';
|
||||
}
|
||||
@@ -178,9 +172,7 @@ export class BoardsToolBarItem extends React.Component<
|
||||
<div className="inner-container" onClick={this.show}>
|
||||
<span className={decorator} />
|
||||
<div className="label noWrapInfo">
|
||||
<div className="noWrapInfo noselect">
|
||||
{title}
|
||||
</div>
|
||||
<div className="noWrapInfo noselect">{title}</div>
|
||||
</div>
|
||||
<span className="fa fa-caret-down caret" />
|
||||
</div>
|
||||
@@ -193,18 +185,13 @@ export class BoardsToolBarItem extends React.Component<
|
||||
.map((board) => ({
|
||||
...board,
|
||||
onClick: () => {
|
||||
if (
|
||||
board.state ===
|
||||
AvailableBoard.State.incomplete
|
||||
) {
|
||||
this.props.boardsServiceClient.boardsConfig =
|
||||
{
|
||||
if (board.state === AvailableBoard.State.incomplete) {
|
||||
this.props.boardsServiceClient.boardsConfig = {
|
||||
selectedPort: board.port,
|
||||
};
|
||||
this.openDialog();
|
||||
} else {
|
||||
this.props.boardsServiceClient.boardsConfig =
|
||||
{
|
||||
this.props.boardsServiceClient.boardsConfig = {
|
||||
selectedBoard: board,
|
||||
selectedPort: board.port,
|
||||
};
|
||||
@@ -218,9 +205,7 @@ export class BoardsToolBarItem extends React.Component<
|
||||
}
|
||||
|
||||
protected openDialog = () => {
|
||||
this.props.commands.executeCommand(
|
||||
ArduinoCommands.OPEN_BOARDS_DIALOG.id
|
||||
);
|
||||
this.props.commands.executeCommand(ArduinoCommands.OPEN_BOARDS_DIALOG.id);
|
||||
this.setState({ coords: 'hidden' });
|
||||
};
|
||||
}
|
||||
|
@@ -42,9 +42,7 @@ export class About extends Contribution {
|
||||
status: cliStatus,
|
||||
} = await this.configService.getVersion();
|
||||
const buildDate = this.buildDate;
|
||||
const detail = (
|
||||
showAll: boolean
|
||||
) => `Version: ${remote.app.getVersion()}
|
||||
const detail = (showAll: boolean) => `Version: ${remote.app.getVersion()}
|
||||
Date: ${buildDate ? buildDate : 'dev build'}${
|
||||
buildDate && showAll ? ` (${this.ago(buildDate)})` : ''
|
||||
}
|
||||
@@ -87,9 +85,7 @@ ${showAll ? `Copyright © ${new Date().getFullYear()} Arduino SA` : ''}
|
||||
const other = moment(isoTime);
|
||||
let result = now.diff(other, 'minute');
|
||||
if (result < 60) {
|
||||
return result === 1
|
||||
? `${result} minute ago`
|
||||
: `${result} minute ago`;
|
||||
return result === 1 ? `${result} minute ago` : `${result} minute ago`;
|
||||
}
|
||||
result = now.diff(other, 'hour');
|
||||
if (result < 25) {
|
||||
@@ -105,9 +101,7 @@ ${showAll ? `Copyright © ${new Date().getFullYear()} Arduino SA` : ''}
|
||||
}
|
||||
result = now.diff(other, 'month');
|
||||
if (result < 13) {
|
||||
return result === 1
|
||||
? `${result} month ago`
|
||||
: `${result} months ago`;
|
||||
return result === 1 ? `${result} month ago` : `${result} months ago`;
|
||||
}
|
||||
result = now.diff(other, 'year');
|
||||
return result === 1 ? `${result} year ago` : `${result} years ago`;
|
||||
|
@@ -80,17 +80,13 @@ export class AddZipLibrary extends SketchContribution {
|
||||
}
|
||||
}
|
||||
|
||||
private async doInstall(
|
||||
zipUri: string,
|
||||
overwrite?: boolean
|
||||
): Promise<void> {
|
||||
private async doInstall(zipUri: string, overwrite?: boolean): Promise<void> {
|
||||
try {
|
||||
await Installable.doWithProgress({
|
||||
messageService: this.messageService,
|
||||
progressText: `Processing ${new URI(zipUri).path.base}`,
|
||||
responseService: this.responseService,
|
||||
run: () =>
|
||||
this.libraryService.installZip({ zipUri, overwrite }),
|
||||
run: () => this.libraryService.installZip({ zipUri, overwrite }),
|
||||
});
|
||||
this.messageService.info(
|
||||
`Successfully installed library from ${
|
||||
@@ -100,9 +96,7 @@ export class AddZipLibrary extends SketchContribution {
|
||||
);
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
const match = error.message.match(
|
||||
/library (.*?) already installed/
|
||||
);
|
||||
const match = error.message.match(/library (.*?) already installed/);
|
||||
if (match && match.length >= 2) {
|
||||
const name = match[1].trim();
|
||||
if (name) {
|
||||
|
@@ -77,16 +77,13 @@ export class BoardSelection extends SketchContribution {
|
||||
const detail = `BN: ${selectedBoard.name}
|
||||
VID: ${VID}
|
||||
PID: ${PID}`;
|
||||
await remote.dialog.showMessageBox(
|
||||
remote.getCurrentWindow(),
|
||||
{
|
||||
await remote.dialog.showMessageBox(remote.getCurrentWindow(), {
|
||||
message: 'Board Info',
|
||||
title: 'Board Info',
|
||||
type: 'info',
|
||||
detail,
|
||||
buttons: ['OK'],
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -94,12 +91,8 @@ PID: ${PID}`;
|
||||
|
||||
onStart(): void {
|
||||
this.updateMenus();
|
||||
this.notificationCenter.onPlatformInstalled(
|
||||
this.updateMenus.bind(this)
|
||||
);
|
||||
this.notificationCenter.onPlatformUninstalled(
|
||||
this.updateMenus.bind(this)
|
||||
);
|
||||
this.notificationCenter.onPlatformInstalled(this.updateMenus.bind(this));
|
||||
this.notificationCenter.onPlatformUninstalled(this.updateMenus.bind(this));
|
||||
this.boardsServiceProvider.onBoardsConfigChanged(
|
||||
this.updateMenus.bind(this)
|
||||
);
|
||||
@@ -190,50 +183,38 @@ PID: ${PID}`;
|
||||
// Platform submenu
|
||||
const platformMenuPath = [...boardsPackagesGroup, packageId];
|
||||
// Note: Registering the same submenu twice is a noop. No need to group the boards per platform.
|
||||
this.menuModelRegistry.registerSubmenu(
|
||||
platformMenuPath,
|
||||
packageName
|
||||
);
|
||||
this.menuModelRegistry.registerSubmenu(platformMenuPath, packageName);
|
||||
|
||||
const id = `arduino-select-board--${fqbn}`;
|
||||
const command = { id };
|
||||
const handler = {
|
||||
execute: () => {
|
||||
if (
|
||||
fqbn !==
|
||||
this.boardsServiceProvider.boardsConfig.selectedBoard
|
||||
?.fqbn
|
||||
fqbn !== this.boardsServiceProvider.boardsConfig.selectedBoard?.fqbn
|
||||
) {
|
||||
this.boardsServiceProvider.boardsConfig = {
|
||||
selectedBoard: {
|
||||
name,
|
||||
fqbn,
|
||||
port: this.boardsServiceProvider.boardsConfig
|
||||
.selectedBoard?.port, // TODO: verify!
|
||||
port: this.boardsServiceProvider.boardsConfig.selectedBoard
|
||||
?.port, // TODO: verify!
|
||||
},
|
||||
selectedPort:
|
||||
this.boardsServiceProvider.boardsConfig
|
||||
.selectedPort,
|
||||
this.boardsServiceProvider.boardsConfig.selectedPort,
|
||||
};
|
||||
}
|
||||
},
|
||||
isToggled: () =>
|
||||
fqbn ===
|
||||
this.boardsServiceProvider.boardsConfig.selectedBoard?.fqbn,
|
||||
fqbn === this.boardsServiceProvider.boardsConfig.selectedBoard?.fqbn,
|
||||
};
|
||||
|
||||
// Board menu
|
||||
const menuAction = { commandId: id, label: name };
|
||||
this.commandRegistry.registerCommand(command, handler);
|
||||
this.toDisposeBeforeMenuRebuild.push(
|
||||
Disposable.create(() =>
|
||||
this.commandRegistry.unregisterCommand(command)
|
||||
)
|
||||
);
|
||||
this.menuModelRegistry.registerMenuAction(
|
||||
platformMenuPath,
|
||||
menuAction
|
||||
Disposable.create(() => this.commandRegistry.unregisterCommand(command))
|
||||
);
|
||||
this.menuModelRegistry.registerMenuAction(platformMenuPath, menuAction);
|
||||
// Note: we do not dispose the menu actions individually. Calling `unregisterSubmenu` on the parent will wipe the children menu nodes recursively.
|
||||
}
|
||||
|
||||
@@ -277,14 +258,12 @@ PID: ${PID}`;
|
||||
if (
|
||||
!Port.equals(
|
||||
port,
|
||||
this.boardsServiceProvider.boardsConfig
|
||||
.selectedPort
|
||||
this.boardsServiceProvider.boardsConfig.selectedPort
|
||||
)
|
||||
) {
|
||||
this.boardsServiceProvider.boardsConfig = {
|
||||
selectedBoard:
|
||||
this.boardsServiceProvider
|
||||
.boardsConfig.selectedBoard,
|
||||
this.boardsServiceProvider.boardsConfig.selectedBoard,
|
||||
selectedPort: port,
|
||||
};
|
||||
}
|
||||
@@ -292,8 +271,7 @@ PID: ${PID}`;
|
||||
isToggled: () =>
|
||||
Port.equals(
|
||||
port,
|
||||
this.boardsServiceProvider.boardsConfig
|
||||
.selectedPort
|
||||
this.boardsServiceProvider.boardsConfig.selectedPort
|
||||
),
|
||||
};
|
||||
const label = `${address}${name ? ` (${name})` : ''}`;
|
||||
@@ -308,10 +286,7 @@ PID: ${PID}`;
|
||||
this.commandRegistry.unregisterCommand(command)
|
||||
)
|
||||
);
|
||||
this.menuModelRegistry.registerMenuAction(
|
||||
menuPath,
|
||||
menuAction
|
||||
);
|
||||
this.menuModelRegistry.registerMenuAction(menuPath, menuAction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -56,9 +56,7 @@ export class BurnBootloader extends SketchContribution {
|
||||
this.boardsDataStore.appendConfigToFqbn(
|
||||
boardsConfig.selectedBoard?.fqbn
|
||||
),
|
||||
this.boardsDataStore.getData(
|
||||
boardsConfig.selectedBoard?.fqbn
|
||||
),
|
||||
this.boardsDataStore.getData(boardsConfig.selectedBoard?.fqbn),
|
||||
this.preferences.get('arduino.upload.verify'),
|
||||
this.preferences.get('arduino.upload.verbose'),
|
||||
]);
|
||||
|
@@ -46,10 +46,7 @@ export class Close extends SketchContribution {
|
||||
const currentWidgetInMain = toArray(
|
||||
this.shell.mainPanel.widgets()
|
||||
).find((widget) => widget === currentWidget);
|
||||
if (
|
||||
currentWidgetInMain &&
|
||||
currentWidgetInMain.title.closable
|
||||
) {
|
||||
if (currentWidgetInMain && currentWidgetInMain.title.closable) {
|
||||
return currentWidgetInMain.close();
|
||||
}
|
||||
}
|
||||
@@ -116,10 +113,7 @@ export class Close extends SketchContribution {
|
||||
if (editorWidget) {
|
||||
const { editor } = editorWidget;
|
||||
if (editor instanceof MonacoEditor) {
|
||||
const versionId = editor
|
||||
.getControl()
|
||||
.getModel()
|
||||
?.getVersionId();
|
||||
const versionId = editor.getControl().getModel()?.getVersionId();
|
||||
if (Number.isInteger(versionId) && versionId! > 1) {
|
||||
return true;
|
||||
}
|
||||
|
@@ -130,10 +130,7 @@ export abstract class SketchContribution extends Contribution {
|
||||
if (sketch) {
|
||||
for (const editor of this.editorManager.all) {
|
||||
const uri = editor.editor.uri;
|
||||
if (
|
||||
Saveable.isDirty(editor) &&
|
||||
Sketch.isInSketch(uri, sketch)
|
||||
) {
|
||||
if (Saveable.isDirty(editor) && Sketch.isInSketch(uri, sketch)) {
|
||||
override[uri.toString()] = editor.editor.document.getText();
|
||||
}
|
||||
}
|
||||
|
@@ -34,9 +34,7 @@ export class Debug extends SketchContribution {
|
||||
* If `undefined`, debugging is enabled. Otherwise, the reason why it's disabled.
|
||||
*/
|
||||
protected _disabledMessages?: string = 'No board selected'; // Initial pessimism.
|
||||
protected disabledMessageDidChangeEmitter = new Emitter<
|
||||
string | undefined
|
||||
>();
|
||||
protected disabledMessageDidChangeEmitter = new Emitter<string | undefined>();
|
||||
protected onDisabledMessageDidChange =
|
||||
this.disabledMessageDidChangeEmitter.event;
|
||||
|
||||
@@ -151,10 +149,7 @@ export class Debug extends SketchContribution {
|
||||
sketchPath,
|
||||
configPath,
|
||||
};
|
||||
return this.commandService.executeCommand(
|
||||
'arduino.debug.start',
|
||||
config
|
||||
);
|
||||
return this.commandService.executeCommand('arduino.debug.start', config);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -48,12 +48,9 @@ export class EditContributions extends Contribution {
|
||||
execute: () => this.run('editor.action.nextMatchFindAction'),
|
||||
});
|
||||
registry.registerCommand(EditContributions.Commands.USE_FOR_FIND, {
|
||||
execute: () =>
|
||||
this.run('editor.action.previousSelectionMatchFindAction'),
|
||||
execute: () => this.run('editor.action.previousSelectionMatchFindAction'),
|
||||
});
|
||||
registry.registerCommand(
|
||||
EditContributions.Commands.INCREASE_FONT_SIZE,
|
||||
{
|
||||
registry.registerCommand(EditContributions.Commands.INCREASE_FONT_SIZE, {
|
||||
execute: async () => {
|
||||
const settings = await this.settingsService.settings();
|
||||
if (settings.autoScaleInterface) {
|
||||
@@ -64,11 +61,8 @@ export class EditContributions extends Contribution {
|
||||
await this.settingsService.update(settings);
|
||||
await this.settingsService.save();
|
||||
},
|
||||
}
|
||||
);
|
||||
registry.registerCommand(
|
||||
EditContributions.Commands.DECREASE_FONT_SIZE,
|
||||
{
|
||||
});
|
||||
registry.registerCommand(EditContributions.Commands.DECREASE_FONT_SIZE, {
|
||||
execute: async () => {
|
||||
const settings = await this.settingsService.settings();
|
||||
if (settings.autoScaleInterface) {
|
||||
@@ -79,8 +73,7 @@ export class EditContributions extends Contribution {
|
||||
await this.settingsService.update(settings);
|
||||
await this.settingsService.save();
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
/* Tools */ registry.registerCommand(
|
||||
EditContributions.Commands.AUTO_FORMAT,
|
||||
{ execute: () => this.run('editor.action.formatDocument') }
|
||||
|
@@ -59,12 +59,8 @@ export abstract class Examples extends SketchContribution {
|
||||
const index = ArduinoMenus.FILE__EXAMPLES_SUBMENU.length - 1;
|
||||
const menuId = ArduinoMenus.FILE__EXAMPLES_SUBMENU[index];
|
||||
const groupPath =
|
||||
index === 0
|
||||
? []
|
||||
: ArduinoMenus.FILE__EXAMPLES_SUBMENU.slice(0, index);
|
||||
const parent: CompositeMenuNode = (registry as any).findGroup(
|
||||
groupPath
|
||||
);
|
||||
index === 0 ? [] : ArduinoMenus.FILE__EXAMPLES_SUBMENU.slice(0, index);
|
||||
const parent: CompositeMenuNode = (registry as any).findGroup(groupPath);
|
||||
const examples = new CompositeMenuNode(menuId, '', { order: '4' });
|
||||
parent.addNode(examples);
|
||||
} catch (e) {
|
||||
@@ -73,11 +69,9 @@ export abstract class Examples extends SketchContribution {
|
||||
}
|
||||
// Registering the same submenu multiple times has no side-effect.
|
||||
// TODO: unregister submenu? https://github.com/eclipse-theia/theia/issues/7300
|
||||
registry.registerSubmenu(
|
||||
ArduinoMenus.FILE__EXAMPLES_SUBMENU,
|
||||
'Examples',
|
||||
{ order: '4' }
|
||||
);
|
||||
registry.registerSubmenu(ArduinoMenus.FILE__EXAMPLES_SUBMENU, 'Examples', {
|
||||
order: '4',
|
||||
});
|
||||
}
|
||||
|
||||
registerRecursively(
|
||||
@@ -108,11 +102,7 @@ export abstract class Examples extends SketchContribution {
|
||||
if (SketchContainer.is(sketchContainerOrPlaceholder)) {
|
||||
const { label } = sketchContainerOrPlaceholder;
|
||||
submenuPath = [...menuPath, label];
|
||||
this.menuRegistry.registerSubmenu(
|
||||
submenuPath,
|
||||
label,
|
||||
subMenuOptions
|
||||
);
|
||||
this.menuRegistry.registerSubmenu(submenuPath, label, subMenuOptions);
|
||||
sketches.push(...sketchContainerOrPlaceholder.sketches);
|
||||
children.push(...sketchContainerOrPlaceholder.children);
|
||||
} else {
|
||||
@@ -176,9 +166,7 @@ export class BuiltInExamples extends Examples {
|
||||
sketchContainers = await this.examplesService.builtIns();
|
||||
} catch (e) {
|
||||
console.error('Could not initialize built-in examples.', e);
|
||||
this.messageService.error(
|
||||
'Could not initialize built-in examples.'
|
||||
);
|
||||
this.messageService.error('Could not initialize built-in examples.');
|
||||
return;
|
||||
}
|
||||
this.toDispose.dispose();
|
||||
@@ -219,9 +207,9 @@ export class LibraryExamples extends Examples {
|
||||
const fqbn = board?.fqbn;
|
||||
const name = board?.name;
|
||||
// Shows all examples when no board is selected, or the platform of the currently selected board is not installed.
|
||||
const { user, current, any } = await this.examplesService.installed(
|
||||
{ fqbn }
|
||||
);
|
||||
const { user, current, any } = await this.examplesService.installed({
|
||||
fqbn,
|
||||
});
|
||||
if (user.length) {
|
||||
(user as any).unshift('Examples from Custom Libraries');
|
||||
}
|
||||
|
@@ -51,18 +51,11 @@ export class Help extends Contribution {
|
||||
execute: async () => {
|
||||
let searchFor: string | undefined = undefined;
|
||||
const { currentEditor } = this.editorManager;
|
||||
if (
|
||||
currentEditor &&
|
||||
currentEditor.editor instanceof MonacoEditor
|
||||
) {
|
||||
if (currentEditor && currentEditor.editor instanceof MonacoEditor) {
|
||||
const codeEditor = currentEditor.editor.getControl();
|
||||
const selection = codeEditor.getSelection();
|
||||
const model = codeEditor.getModel();
|
||||
if (
|
||||
model &&
|
||||
selection &&
|
||||
!monaco.Range.isEmpty(selection)
|
||||
) {
|
||||
if (model && selection && !monaco.Range.isEmpty(selection)) {
|
||||
searchFor = model.getValueInRange(selection);
|
||||
}
|
||||
}
|
||||
|
@@ -47,9 +47,7 @@ export class IncludeLibrary extends SketchContribution {
|
||||
this.boardsServiceClient.onBoardsConfigChanged(() =>
|
||||
this.updateMenuActions()
|
||||
);
|
||||
this.notificationCenter.onLibraryInstalled(() =>
|
||||
this.updateMenuActions()
|
||||
);
|
||||
this.notificationCenter.onLibraryInstalled(() => this.updateMenuActions());
|
||||
this.notificationCenter.onLibraryUninstalled(() =>
|
||||
this.updateMenuActions()
|
||||
);
|
||||
@@ -86,8 +84,7 @@ export class IncludeLibrary extends SketchContribution {
|
||||
this.toDispose.dispose();
|
||||
this.mainMenuManager.update();
|
||||
const libraries: LibraryPackage[] = [];
|
||||
const fqbn =
|
||||
this.boardsServiceClient.boardsConfig.selectedBoard?.fqbn;
|
||||
const fqbn = this.boardsServiceClient.boardsConfig.selectedBoard?.fqbn;
|
||||
// Show all libraries, when no board is selected.
|
||||
// Otherwise, show libraries only for the selected board.
|
||||
libraries.push(...(await this.libraryService.list({ fqbn })));
|
||||
@@ -111,14 +108,10 @@ export class IncludeLibrary extends SketchContribution {
|
||||
}
|
||||
|
||||
for (const library of user) {
|
||||
this.toDispose.push(
|
||||
this.registerLibrary(library, userMenuPath)
|
||||
);
|
||||
this.toDispose.push(this.registerLibrary(library, userMenuPath));
|
||||
}
|
||||
for (const library of rest) {
|
||||
this.toDispose.push(
|
||||
this.registerLibrary(library, packageMenuPath)
|
||||
);
|
||||
this.toDispose.push(this.registerLibrary(library, packageMenuPath));
|
||||
}
|
||||
|
||||
this.mainMenuManager.update();
|
||||
@@ -169,18 +162,14 @@ export class IncludeLibrary extends SketchContribution {
|
||||
const editor = this.editorManager.currentEditor?.editor;
|
||||
if (editor instanceof MonacoEditor) {
|
||||
if (
|
||||
sketch.additionalFileUris.some(
|
||||
(uri) => uri === editor.uri.toString()
|
||||
)
|
||||
sketch.additionalFileUris.some((uri) => uri === editor.uri.toString())
|
||||
) {
|
||||
codeEditor = editor.getControl();
|
||||
}
|
||||
}
|
||||
|
||||
if (!codeEditor) {
|
||||
const widget = await this.editorManager.open(
|
||||
new URI(sketch.mainFileUri)
|
||||
);
|
||||
const widget = await this.editorManager.open(new URI(sketch.mainFileUri));
|
||||
if (widget.editor instanceof MonacoEditor) {
|
||||
codeEditor = widget.editor.getControl();
|
||||
}
|
||||
|
@@ -20,8 +20,7 @@ export class NewSketch extends SketchContribution {
|
||||
registry.registerCommand(NewSketch.Commands.NEW_SKETCH__TOOLBAR, {
|
||||
isVisible: (widget) =>
|
||||
ArduinoToolbar.is(widget) && widget.side === 'left',
|
||||
execute: () =>
|
||||
registry.executeCommand(NewSketch.Commands.NEW_SKETCH.id),
|
||||
execute: () => registry.executeCommand(NewSketch.Commands.NEW_SKETCH.id),
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -86,8 +86,7 @@ export class OpenSketch extends SketchContribution {
|
||||
this.toDispose
|
||||
);
|
||||
try {
|
||||
const containers =
|
||||
await this.examplesService.builtIns();
|
||||
const containers = await this.examplesService.builtIns();
|
||||
for (const container of containers) {
|
||||
this.builtInExamples.registerRecursively(
|
||||
container,
|
||||
@@ -96,10 +95,7 @@ export class OpenSketch extends SketchContribution {
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(
|
||||
'Error when collecting built-in examples.',
|
||||
e
|
||||
);
|
||||
console.error('Error when collecting built-in examples.', e);
|
||||
}
|
||||
const options = {
|
||||
menuPath: ArduinoMenus.OPEN_SKETCH__CONTEXT,
|
||||
@@ -180,9 +176,7 @@ export class OpenSketch extends SketchContribution {
|
||||
}
|
||||
if (Sketch.isSketchFile(sketchFileUri)) {
|
||||
const name = new URI(sketchFileUri).path.name;
|
||||
const nameWithExt = this.labelProvider.getName(
|
||||
new URI(sketchFileUri)
|
||||
);
|
||||
const nameWithExt = this.labelProvider.getName(new URI(sketchFileUri));
|
||||
const { response } = await remote.dialog.showMessageBox({
|
||||
title: 'Moving',
|
||||
type: 'question',
|
||||
@@ -191,9 +185,7 @@ export class OpenSketch extends SketchContribution {
|
||||
});
|
||||
if (response === 1) {
|
||||
// OK
|
||||
const newSketchUri = new URI(sketchFileUri).parent.resolve(
|
||||
name
|
||||
);
|
||||
const newSketchUri = new URI(sketchFileUri).parent.resolve(name);
|
||||
const exists = await this.fileService.exists(newSketchUri);
|
||||
if (exists) {
|
||||
await remote.dialog.showMessageBox({
|
||||
@@ -208,9 +200,7 @@ export class OpenSketch extends SketchContribution {
|
||||
new URI(sketchFileUri),
|
||||
new URI(newSketchUri.resolve(nameWithExt).toString())
|
||||
);
|
||||
return this.sketchService.getSketchFolder(
|
||||
newSketchUri.toString()
|
||||
);
|
||||
return this.sketchService.getSketchFolder(newSketchUri.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -66,10 +66,7 @@ export class SaveAsSketch extends SketchContribution {
|
||||
? sketchDirUri.resolve(
|
||||
sketchDirUri
|
||||
.resolve(
|
||||
`${sketch.name}_copy_${dateFormat(
|
||||
new Date(),
|
||||
'yyyymmddHHMMss'
|
||||
)}`
|
||||
`${sketch.name}_copy_${dateFormat(new Date(), 'yyyymmddHHMMss')}`
|
||||
)
|
||||
.toString()
|
||||
)
|
||||
|
@@ -43,10 +43,7 @@ export class Settings extends SketchContribution {
|
||||
label: 'Preferences...',
|
||||
order: '0',
|
||||
});
|
||||
registry.registerSubmenu(
|
||||
ArduinoMenus.FILE__ADVANCED_SUBMENU,
|
||||
'Advanced'
|
||||
);
|
||||
registry.registerSubmenu(ArduinoMenus.FILE__ADVANCED_SUBMENU, 'Advanced');
|
||||
}
|
||||
|
||||
registerKeybindings(registry: KeybindingRegistry): void {
|
||||
|
@@ -53,8 +53,7 @@ export class SketchControl extends SketchContribution {
|
||||
this.shell.getWidgets('main').indexOf(widget) !== -1,
|
||||
execute: async () => {
|
||||
this.toDisposeBeforeCreateNewContextMenu.dispose();
|
||||
const sketch =
|
||||
await this.sketchServiceClient.currentSketch();
|
||||
const sketch = await this.sketchServiceClient.currentSketch();
|
||||
if (!sketch) {
|
||||
return;
|
||||
}
|
||||
@@ -79,8 +78,7 @@ export class SketchControl extends SketchContribution {
|
||||
const parentsketchUri = this.editorManager.currentEditor
|
||||
?.getResourceUri()
|
||||
?.toString();
|
||||
const parentsketch =
|
||||
await this.sketchService.getSketchFolder(
|
||||
const parentsketch = await this.sketchService.getSketchFolder(
|
||||
parentsketchUri || ''
|
||||
);
|
||||
|
||||
@@ -117,9 +115,7 @@ export class SketchControl extends SketchContribution {
|
||||
);
|
||||
this.toDisposeBeforeCreateNewContextMenu.push(
|
||||
Disposable.create(() =>
|
||||
this.menuRegistry.unregisterMenuNode(
|
||||
renamePlaceholder.id
|
||||
)
|
||||
this.menuRegistry.unregisterMenuNode(renamePlaceholder.id)
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -156,9 +152,7 @@ export class SketchControl extends SketchContribution {
|
||||
);
|
||||
this.toDisposeBeforeCreateNewContextMenu.push(
|
||||
Disposable.create(() =>
|
||||
this.menuRegistry.unregisterMenuNode(
|
||||
deletePlaceholder.id
|
||||
)
|
||||
this.menuRegistry.unregisterMenuNode(deletePlaceholder.id)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@@ -115,13 +115,8 @@ export class UploadSketch extends SketchContribution {
|
||||
}
|
||||
try {
|
||||
const { boardsConfig } = this.boardsServiceClientImpl;
|
||||
const [
|
||||
fqbn,
|
||||
{ selectedProgrammer },
|
||||
verify,
|
||||
verbose,
|
||||
sourceOverride,
|
||||
] = await Promise.all([
|
||||
const [fqbn, { selectedProgrammer }, verify, verbose, sourceOverride] =
|
||||
await Promise.all([
|
||||
this.boardsDataStore.appendConfigToFqbn(
|
||||
boardsConfig.selectedBoard?.fqbn
|
||||
),
|
||||
|
@@ -107,9 +107,7 @@ export class VerifySketch extends SketchContribution {
|
||||
this.sourceOverride(),
|
||||
]);
|
||||
const verbose = this.preferences.get('arduino.compile.verbose');
|
||||
const compilerWarnings = this.preferences.get(
|
||||
'arduino.compile.warnings'
|
||||
);
|
||||
const compilerWarnings = this.preferences.get('arduino.compile.warnings');
|
||||
this.outputChannelManager.getChannel('Arduino').clear();
|
||||
await this.coreService.compile({
|
||||
sketchUri: sketch.uri,
|
||||
|
@@ -154,11 +154,7 @@ export class CreateApi {
|
||||
const sketch = await this.findSketchInCache(
|
||||
this.sketchCompareByPath(spath)
|
||||
);
|
||||
if (
|
||||
sketch &&
|
||||
sketch.secrets &&
|
||||
sketch.secrets.length > 0
|
||||
) {
|
||||
if (sketch && sketch.secrets && sketch.secrets.length > 0) {
|
||||
result.push(this.getSketchSecretStat(sketch));
|
||||
}
|
||||
});
|
||||
@@ -167,27 +163,24 @@ export class CreateApi {
|
||||
const sketch = await this.findSketchInCache(
|
||||
this.sketchCompareByPath(posixPath)
|
||||
);
|
||||
if (
|
||||
sketch &&
|
||||
sketch.secrets &&
|
||||
sketch.secrets.length > 0
|
||||
) {
|
||||
if (sketch && sketch.secrets && sketch.secrets.length > 0) {
|
||||
result.push(this.getSketchSecretStat(sketch));
|
||||
}
|
||||
}
|
||||
}
|
||||
const sketchesMap: Record<string, Create.Sketch> =
|
||||
sketches.reduce((prev, curr) => {
|
||||
const sketchesMap: Record<string, Create.Sketch> = sketches.reduce(
|
||||
(prev, curr) => {
|
||||
return { ...prev, [curr.path]: curr };
|
||||
}, {});
|
||||
},
|
||||
{}
|
||||
);
|
||||
|
||||
// add the sketch id and isPublic to the resource
|
||||
return result.map((resource) => {
|
||||
return {
|
||||
...resource,
|
||||
sketchId: sketchesMap[resource.path]?.id || '',
|
||||
isPublic:
|
||||
sketchesMap[resource.path]?.is_public || false,
|
||||
isPublic: sketchesMap[resource.path]?.is_public || false,
|
||||
};
|
||||
});
|
||||
})
|
||||
@@ -339,16 +332,13 @@ export class CreateApi {
|
||||
}
|
||||
const regexp = /(\S*)\s+([\S\s]*)/g;
|
||||
const tokens = regexp.exec(secret) || [];
|
||||
const name =
|
||||
tokens[1].length > 0 ? `SECRET_${tokens[1]}` : '';
|
||||
const name = tokens[1].length > 0 ? `SECRET_${tokens[1]}` : '';
|
||||
|
||||
let value = '';
|
||||
if (tokens[2].length > 0) {
|
||||
value = JSON.parse(
|
||||
JSON.stringify(
|
||||
tokens[2]
|
||||
.replace(/^['"]?/g, '')
|
||||
.replace(/['"]?$/g, '')
|
||||
tokens[2].replace(/^['"]?/g, '').replace(/['"]?$/g, '')
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -386,9 +376,7 @@ export class CreateApi {
|
||||
const headers = await this.headers();
|
||||
|
||||
let data: string =
|
||||
typeof content === 'string'
|
||||
? content
|
||||
: new TextDecoder().decode(content);
|
||||
typeof content === 'string' ? content : new TextDecoder().decode(content);
|
||||
data = await this.toggleSecretsInclude(posixPath, data, 'remove');
|
||||
|
||||
const payload = { data: btoa(data) };
|
||||
@@ -500,8 +488,7 @@ export class CreateApi {
|
||||
}
|
||||
|
||||
private domain(apiVersion = 'v2'): string {
|
||||
const endpoint =
|
||||
this.arduinoPreferences['arduino.cloud.sketchSyncEnpoint'];
|
||||
const endpoint = this.arduinoPreferences['arduino.cloud.sketchSyncEnpoint'];
|
||||
return `${endpoint}/${apiVersion}`;
|
||||
}
|
||||
|
||||
|
@@ -142,9 +142,7 @@ export class CreateFsProvider
|
||||
}
|
||||
default: {
|
||||
throw new FileSystemProviderError(
|
||||
`Unexpected file type '${
|
||||
stat.type
|
||||
}' for resource: ${uri.toString()}`,
|
||||
`Unexpected file type '${stat.type}' for resource: ${uri.toString()}`,
|
||||
FileSystemProviderErrorCode.Unknown
|
||||
);
|
||||
}
|
||||
|
@@ -12,9 +12,7 @@ export namespace CreateUri {
|
||||
typeof posixPathOrResource === 'string'
|
||||
? posixPathOrResource
|
||||
: toPosixPath(posixPathOrResource.path);
|
||||
return new URI(
|
||||
Uri.parse(posixPath).with({ scheme, authority: 'create' })
|
||||
);
|
||||
return new URI(Uri.parse(posixPath).with({ scheme, authority: 'create' }));
|
||||
}
|
||||
|
||||
export function is(uri: URI): boolean {
|
||||
|
@@ -17,9 +17,7 @@ export class EditorMode implements FrontendApplicationContribution {
|
||||
}
|
||||
|
||||
get compileForDebug(): boolean {
|
||||
const value = window.localStorage.getItem(
|
||||
EditorMode.COMPILE_FOR_DEBUG_KEY
|
||||
);
|
||||
const value = window.localStorage.getItem(EditorMode.COMPILE_FOR_DEBUG_KEY);
|
||||
return value === 'true';
|
||||
}
|
||||
|
||||
|
@@ -36,9 +36,7 @@ export class LibraryListWidget extends ListWidget<LibraryPackage> {
|
||||
protected init(): void {
|
||||
super.init();
|
||||
this.toDispose.pushAll([
|
||||
this.notificationCenter.onLibraryInstalled(() =>
|
||||
this.refresh(undefined)
|
||||
),
|
||||
this.notificationCenter.onLibraryInstalled(() => this.refresh(undefined)),
|
||||
this.notificationCenter.onLibraryUninstalled(() =>
|
||||
this.refresh(undefined)
|
||||
),
|
||||
@@ -62,9 +60,7 @@ export class LibraryListWidget extends ListWidget<LibraryPackage> {
|
||||
let installDependencies: boolean | undefined = undefined;
|
||||
if (dependencies.length) {
|
||||
const message = document.createElement('div');
|
||||
message.innerHTML = `The library <b>${
|
||||
item.name
|
||||
}:${version}</b> needs ${
|
||||
message.innerHTML = `The library <b>${item.name}:${version}</b> needs ${
|
||||
dependencies.length === 1
|
||||
? 'another dependency'
|
||||
: 'some other dependencies'
|
||||
@@ -145,9 +141,7 @@ class MessageBoxDialog extends AbstractDialog<MessageBoxDialog.Result> {
|
||||
|
||||
constructor(protected readonly options: MessageBoxDialog.Options) {
|
||||
super(options);
|
||||
this.contentNode.appendChild(
|
||||
this.createMessageNode(this.options.message)
|
||||
);
|
||||
this.contentNode.appendChild(this.createMessageNode(this.options.message));
|
||||
(options.buttons || ['OK']).forEach((text, index) => {
|
||||
const button = this.createButton(text);
|
||||
button.classList.add(index === 0 ? 'main' : 'secondary');
|
||||
|
@@ -26,9 +26,7 @@ export namespace LocalCacheUri {
|
||||
|
||||
@injectable()
|
||||
export class LocalCacheFsProvider
|
||||
implements
|
||||
FileServiceContribution,
|
||||
DelegatingFileSystemProvider.URIConverter
|
||||
implements FileServiceContribution, DelegatingFileSystemProvider.URIConverter
|
||||
{
|
||||
@inject(ConfigService)
|
||||
protected readonly configService: ConfigService;
|
||||
@@ -48,10 +46,7 @@ export class LocalCacheFsProvider
|
||||
(async () => {
|
||||
this.init(fileService);
|
||||
const provider = await this.createProvider(fileService);
|
||||
fileService.registerProvider(
|
||||
LocalCacheUri.scheme,
|
||||
provider
|
||||
);
|
||||
fileService.registerProvider(LocalCacheUri.scheme, provider);
|
||||
})()
|
||||
);
|
||||
}
|
||||
@@ -135,15 +130,13 @@ export class LocalCacheFsProvider
|
||||
}
|
||||
const toDispose = new DisposableCollection();
|
||||
toDispose.push(
|
||||
this.authenticationService.onSessionDidChange(
|
||||
async (session) => {
|
||||
this.authenticationService.onSessionDidChange(async (session) => {
|
||||
if (session) {
|
||||
await this.ensureExists(session, fileService);
|
||||
toDispose.dispose();
|
||||
resolve(session);
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@@ -88,9 +88,7 @@ export class MonitorConnection {
|
||||
}
|
||||
case MonitorError.ErrorCodes.DEVICE_BUSY: {
|
||||
this.messageService.warn(
|
||||
`Connection failed. Serial port is busy: ${Port.toString(
|
||||
port
|
||||
)}.`,
|
||||
`Connection failed. Serial port is busy: ${Port.toString(port)}.`,
|
||||
options
|
||||
);
|
||||
shouldReconnect = this.autoConnect;
|
||||
@@ -141,9 +139,7 @@ export class MonitorConnection {
|
||||
this.messageService.warn(
|
||||
`Reconnecting ${Board.toString(board, {
|
||||
useFqbn: false,
|
||||
})} to ${Port.toString(
|
||||
port
|
||||
)} in ${attempts} seconds...`,
|
||||
})} to ${Port.toString(port)} in ${attempts} seconds...`,
|
||||
{ timeout }
|
||||
);
|
||||
this.reconnectTimeout = window.setTimeout(
|
||||
@@ -169,12 +165,10 @@ export class MonitorConnection {
|
||||
if (
|
||||
attached.boards.some(
|
||||
(board) =>
|
||||
!!board.port &&
|
||||
BoardsConfig.Config.sameAs(boardsConfig, board)
|
||||
!!board.port && BoardsConfig.Config.sameAs(boardsConfig, board)
|
||||
)
|
||||
) {
|
||||
const { selectedBoard: board, selectedPort: port } =
|
||||
boardsConfig;
|
||||
const { selectedBoard: board, selectedPort: port } = boardsConfig;
|
||||
const { baudRate } = this.monitorModel;
|
||||
this.disconnect().then(() =>
|
||||
this.connect({ board, port, baudRate })
|
||||
@@ -211,9 +205,7 @@ export class MonitorConnection {
|
||||
if (!oldValue && value) {
|
||||
// We have to make sure the previous boards config has been restored.
|
||||
// Otherwise, we might start the auto-connection without configured boards.
|
||||
this.applicationState
|
||||
.reachedState('started_contributions')
|
||||
.then(() => {
|
||||
this.applicationState.reachedState('started_contributions').then(() => {
|
||||
const { boardsConfig } = this.boardsServiceProvider;
|
||||
this.handleBoardConfigChange(boardsConfig);
|
||||
});
|
||||
@@ -325,9 +317,7 @@ export class MonitorConnection {
|
||||
// The connected board might be unknown. See: https://github.com/arduino/arduino-pro-ide/issues/127#issuecomment-563251881
|
||||
this.boardsService.getAvailablePorts().then((ports) => {
|
||||
if (
|
||||
ports.some((port) =>
|
||||
Port.equals(port, boardsConfig.selectedPort)
|
||||
)
|
||||
ports.some((port) => Port.equals(port, boardsConfig.selectedPort))
|
||||
) {
|
||||
new Promise<void>((resolve) => {
|
||||
// First, disconnect if connected.
|
||||
@@ -338,8 +328,7 @@ export class MonitorConnection {
|
||||
resolve();
|
||||
}).then(() => {
|
||||
// Then (re-)connect.
|
||||
const { selectedBoard: board, selectedPort: port } =
|
||||
boardsConfig;
|
||||
const { selectedBoard: board, selectedPort: port } = boardsConfig;
|
||||
const { baudRate } = this.monitorModel;
|
||||
this.connect({ board, port, baudRate });
|
||||
});
|
||||
|
@@ -70,9 +70,7 @@ export class MonitorWidget extends ReactWidget {
|
||||
protected init(): void {
|
||||
this.update();
|
||||
this.toDispose.push(
|
||||
this.monitorConnection.onConnectionChanged(() =>
|
||||
this.clearConsole()
|
||||
)
|
||||
this.monitorConnection.onConnectionChanged(() => this.clearConsole())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -145,9 +143,7 @@ export class MonitorWidget extends ReactWidget {
|
||||
];
|
||||
}
|
||||
|
||||
protected get baudRates(): OptionsType<
|
||||
SelectOption<MonitorConfig.BaudRate>
|
||||
> {
|
||||
protected get baudRates(): OptionsType<SelectOption<MonitorConfig.BaudRate>> {
|
||||
const baudRates: Array<MonitorConfig.BaudRate> = [
|
||||
300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200,
|
||||
];
|
||||
@@ -160,13 +156,11 @@ export class MonitorWidget extends ReactWidget {
|
||||
protected render(): React.ReactNode {
|
||||
const { baudRates, lineEndings } = this;
|
||||
const lineEnding =
|
||||
lineEndings.find(
|
||||
(item) => item.value === this.monitorModel.lineEnding
|
||||
) || lineEndings[1]; // Defaults to `\n`.
|
||||
lineEndings.find((item) => item.value === this.monitorModel.lineEnding) ||
|
||||
lineEndings[1]; // Defaults to `\n`.
|
||||
const baudRate =
|
||||
baudRates.find(
|
||||
(item) => item.value === this.monitorModel.baudRate
|
||||
) || baudRates[4]; // Defaults to `9600`.
|
||||
baudRates.find((item) => item.value === this.monitorModel.baudRate) ||
|
||||
baudRates[4]; // Defaults to `9600`.
|
||||
return (
|
||||
<div className="serial-monitor">
|
||||
<div className="head">
|
||||
@@ -254,9 +248,7 @@ export class SerialMonitorSendInput extends React.Component<
|
||||
<input
|
||||
ref={this.setRef}
|
||||
type="text"
|
||||
className={`theia-input ${
|
||||
this.props.monitorConfig ? '' : 'warning'
|
||||
}`}
|
||||
className={`theia-input ${this.props.monitorConfig ? '' : 'warning'}`}
|
||||
placeholder={this.placeholder}
|
||||
value={this.state.text}
|
||||
onChange={this.onChange}
|
||||
|
@@ -16,8 +16,7 @@ export class ResponseServiceImpl implements ResponseService {
|
||||
@inject(OutputChannelManager)
|
||||
protected outputChannelManager: OutputChannelManager;
|
||||
|
||||
protected readonly progressDidChangeEmitter =
|
||||
new Emitter<ProgressMessage>();
|
||||
protected readonly progressDidChangeEmitter = new Emitter<ProgressMessage>();
|
||||
readonly onProgressDidChange = this.progressDidChangeEmitter.event;
|
||||
|
||||
appendToOutput(message: OutputMessage): void {
|
||||
|
@@ -123,16 +123,10 @@ export class SettingsService {
|
||||
strings: false,
|
||||
}
|
||||
),
|
||||
this.preferenceService.get<boolean>(
|
||||
'arduino.window.autoScale',
|
||||
true
|
||||
),
|
||||
this.preferenceService.get<boolean>('arduino.window.autoScale', true),
|
||||
this.preferenceService.get<number>('arduino.window.zoomLevel', 0),
|
||||
// this.preferenceService.get<string>('arduino.ide.autoUpdate', true),
|
||||
this.preferenceService.get<boolean>(
|
||||
'arduino.compile.verbose',
|
||||
true
|
||||
),
|
||||
this.preferenceService.get<boolean>('arduino.compile.verbose', true),
|
||||
this.preferenceService.get<any>('arduino.compile.warnings', 'None'),
|
||||
this.preferenceService.get<boolean>('arduino.upload.verbose', true),
|
||||
this.preferenceService.get<boolean>('arduino.upload.verify', true),
|
||||
@@ -144,9 +138,7 @@ export class SettingsService {
|
||||
this.configService.getConfiguration(),
|
||||
]);
|
||||
const { additionalUrls, sketchDirUri, network } = cliConfig;
|
||||
const sketchbookPath = await this.fileService.fsPath(
|
||||
new URI(sketchDirUri)
|
||||
);
|
||||
const sketchbookPath = await this.fileService.fsPath(new URI(sketchDirUri));
|
||||
return {
|
||||
editorFontSize,
|
||||
themeId,
|
||||
@@ -192,9 +184,7 @@ export class SettingsService {
|
||||
): Promise<string | true> {
|
||||
try {
|
||||
const { sketchbookPath, editorFontSize, themeId } = await settings;
|
||||
const sketchbookDir = await this.fileSystemExt.getUri(
|
||||
sketchbookPath
|
||||
);
|
||||
const sketchbookDir = await this.fileSystemExt.getUri(sketchbookPath);
|
||||
if (!(await this.fileService.exists(new URI(sketchbookDir)))) {
|
||||
return `Invalid sketchbook location: ${sketchbookPath}`;
|
||||
}
|
||||
@@ -399,9 +389,7 @@ export class SettingsComponent extends React.Component<
|
||||
<div className="flex-line">Editor font size:</div>
|
||||
<div className="flex-line">Interface scale:</div>
|
||||
<div className="flex-line">Theme:</div>
|
||||
<div className="flex-line">
|
||||
Show verbose output during:
|
||||
</div>
|
||||
<div className="flex-line">Show verbose output during:</div>
|
||||
<div className="flex-line">Compiler warnings:</div>
|
||||
</div>
|
||||
<div className="column">
|
||||
@@ -442,10 +430,8 @@ export class SettingsComponent extends React.Component<
|
||||
value={
|
||||
ThemeService.get()
|
||||
.getThemes()
|
||||
.find(
|
||||
({ id }) =>
|
||||
id === this.state.themeId
|
||||
)?.label || 'Unknown'
|
||||
.find(({ id }) => id === this.state.themeId)?.label ||
|
||||
'Unknown'
|
||||
}
|
||||
onChange={this.themeDidChange}
|
||||
>
|
||||
@@ -630,9 +616,7 @@ export class SettingsComponent extends React.Component<
|
||||
type="number"
|
||||
pattern="[0-9]"
|
||||
value={
|
||||
this.state.network === 'none'
|
||||
? ''
|
||||
: this.state.network.port
|
||||
this.state.network === 'none' ? '' : this.state.network.port
|
||||
}
|
||||
onKeyDown={this.numbersOnlyKeyDown}
|
||||
onChange={this.portDidChange}
|
||||
@@ -669,9 +653,7 @@ export class SettingsComponent extends React.Component<
|
||||
);
|
||||
}
|
||||
|
||||
private isControlKey(
|
||||
event: React.KeyboardEvent<HTMLInputElement>
|
||||
): boolean {
|
||||
private isControlKey(event: React.KeyboardEvent<HTMLInputElement>): boolean {
|
||||
return (
|
||||
!!event.key &&
|
||||
['tab', 'delete', 'backspace', 'arrowleft', 'arrowright'].some(
|
||||
@@ -739,9 +721,7 @@ export class SettingsComponent extends React.Component<
|
||||
event: React.ChangeEvent<HTMLInputElement>
|
||||
) => {
|
||||
this.setState({
|
||||
additionalUrls: event.target.value
|
||||
.split(',')
|
||||
.map((url) => url.trim()),
|
||||
additionalUrls: event.target.value.split(',').map((url) => url.trim()),
|
||||
});
|
||||
};
|
||||
|
||||
@@ -811,9 +791,7 @@ export class SettingsComponent extends React.Component<
|
||||
});
|
||||
};
|
||||
|
||||
protected themeDidChange = (
|
||||
event: React.ChangeEvent<HTMLSelectElement>
|
||||
) => {
|
||||
protected themeDidChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
const { selectedIndex } = event.target.options;
|
||||
const theme = ThemeService.get().getThemes()[selectedIndex];
|
||||
if (theme) {
|
||||
@@ -852,9 +830,7 @@ export class SettingsComponent extends React.Component<
|
||||
}
|
||||
};
|
||||
|
||||
protected noProxyDidChange = (
|
||||
event: React.ChangeEvent<HTMLInputElement>
|
||||
) => {
|
||||
protected noProxyDidChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.checked) {
|
||||
this.setState({ network: 'none' });
|
||||
} else {
|
||||
@@ -1070,8 +1046,7 @@ export class AdditionalUrlsDialog extends AbstractDialog<string[]> {
|
||||
|
||||
const anchor = document.createElement('div');
|
||||
anchor.classList.add('link');
|
||||
anchor.textContent =
|
||||
'Click for a list of unofficial board support URLs';
|
||||
anchor.textContent = 'Click for a list of unofficial board support URLs';
|
||||
anchor.style.marginTop = '5px';
|
||||
anchor.style.cursor = 'pointer';
|
||||
this.addEventListener(anchor, 'click', () =>
|
||||
|
@@ -74,8 +74,7 @@ export class ApplicationShell extends TheiaApplicationShell {
|
||||
|
||||
async saveAll(): Promise<void> {
|
||||
if (
|
||||
this.connectionStatusService.currentStatus ===
|
||||
ConnectionStatus.OFFLINE
|
||||
this.connectionStatusService.currentStatus === ConnectionStatus.OFFLINE
|
||||
) {
|
||||
this.messageService.error(
|
||||
'Could not save the sketch. Please copy your unsaved work into your favorite text editor, and restart the IDE.'
|
||||
|
@@ -1,10 +1,12 @@
|
||||
import { injectable } from 'inversify';
|
||||
import { MenuModelRegistry } from '@theia/core/lib/common/menu';
|
||||
import { CommonFrontendContribution as TheiaCommonFrontendContribution, CommonCommands } from '@theia/core/lib/browser/common-frontend-contribution';
|
||||
import {
|
||||
CommonFrontendContribution as TheiaCommonFrontendContribution,
|
||||
CommonCommands,
|
||||
} from '@theia/core/lib/browser/common-frontend-contribution';
|
||||
|
||||
@injectable()
|
||||
export class CommonFrontendContribution extends TheiaCommonFrontendContribution {
|
||||
|
||||
registerMenus(registry: MenuModelRegistry): void {
|
||||
super.registerMenus(registry);
|
||||
for (const command of [
|
||||
@@ -25,10 +27,9 @@ export class CommonFrontendContribution extends TheiaCommonFrontendContribution
|
||||
CommonCommands.CLOSE_OTHER_TABS,
|
||||
CommonCommands.CLOSE_ALL_TABS,
|
||||
CommonCommands.COLLAPSE_PANEL,
|
||||
CommonCommands.SAVE_WITHOUT_FORMATTING // Patched for https://github.com/eclipse-theia/theia/pull/8877
|
||||
CommonCommands.SAVE_WITHOUT_FORMATTING, // Patched for https://github.com/eclipse-theia/theia/pull/8877
|
||||
]) {
|
||||
registry.unregisterMenuAction(command);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -70,9 +70,7 @@ export class ApplicationConnectionStatusContribution extends TheiaApplicationCon
|
||||
priority: 5000,
|
||||
});
|
||||
this.toDisposeOnOnline.push(
|
||||
Disposable.create(() =>
|
||||
this.statusBar.removeElement('connection-status')
|
||||
)
|
||||
Disposable.create(() => this.statusBar.removeElement('connection-status'))
|
||||
);
|
||||
document.body.classList.add('theia-mod-offline');
|
||||
this.toDisposeOnOnline.push(
|
||||
|
@@ -26,9 +26,7 @@ export class FrontendApplication extends TheiaFrontendApplication {
|
||||
for (const root of roots) {
|
||||
const exists = await this.fileService.exists(root.resource);
|
||||
if (exists) {
|
||||
this.sketchesService.markAsRecentlyOpened(
|
||||
root.resource.toString()
|
||||
); // no await, will get the notification later and rebuild the menu
|
||||
this.sketchesService.markAsRecentlyOpened(root.resource.toString()); // no await, will get the notification later and rebuild the menu
|
||||
await this.commandService.executeCommand(
|
||||
ArduinoCommands.OPEN_SKETCH_FILES.id,
|
||||
root.resource
|
||||
|
@@ -15,15 +15,10 @@ export class ShellLayoutRestorer extends TheiaShellLayoutRestorer {
|
||||
this.storageKey,
|
||||
serializedLayoutData
|
||||
);
|
||||
this.logger.info(
|
||||
'<<< The layout has been successfully stored.'
|
||||
);
|
||||
this.logger.info('<<< The layout has been successfully stored.');
|
||||
} catch (error) {
|
||||
await this.storageService.setData(this.storageKey, undefined);
|
||||
this.logger.error(
|
||||
'Error during serialization of layout data',
|
||||
error
|
||||
);
|
||||
this.logger.error('Error during serialization of layout data', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -23,19 +23,14 @@ export class TabBarDecoratorService extends TheiaTabBarDecoratorService {
|
||||
.getConfiguration()
|
||||
.then(({ dataDirUri }) => (this.dataDirUri = new URI(dataDirUri)))
|
||||
.catch((err) =>
|
||||
this.logger.error(
|
||||
`Failed to determine the data directory: ${err}`
|
||||
)
|
||||
this.logger.error(`Failed to determine the data directory: ${err}`)
|
||||
);
|
||||
}
|
||||
|
||||
getDecorations(title: Title<Widget>): WidgetDecoration.Data[] {
|
||||
if (title.owner instanceof EditorWidget) {
|
||||
const editor = title.owner.editor;
|
||||
if (
|
||||
this.dataDirUri &&
|
||||
this.dataDirUri.isEqualOrParent(editor.uri)
|
||||
) {
|
||||
if (this.dataDirUri && this.dataDirUri.isEqualOrParent(editor.uri)) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
@@ -41,9 +41,7 @@ export class TabBarToolbar extends TheiaTabBarToolbar {
|
||||
id={`${item.id}--container`}
|
||||
key={item.id}
|
||||
className={`${TabBarToolbar.Styles.TAB_BAR_TOOLBAR_ITEM}${
|
||||
command && this.commandIsEnabled(command.id)
|
||||
? ' enabled'
|
||||
: ''
|
||||
command && this.commandIsEnabled(command.id) ? ' enabled' : ''
|
||||
}`}
|
||||
onMouseDown={this.onMouseDownEvent}
|
||||
onMouseUp={this.onMouseUpEvent}
|
||||
|
@@ -48,16 +48,13 @@ export class DebugConfigurationManager extends TheiaDebugConfigurationManager {
|
||||
// /var/folders/k3/d2fkvv1j16v3_rz93k7f74180000gn/T/arduino-ide2-a0337d47f86b24a51df3dbcf2cc17925/launch.json
|
||||
// /private/var/folders/k3/d2fkvv1j16v3_rz93k7f74180000gn/T/arduino-ide2-A0337D47F86B24A51DF3DBCF2CC17925/launch.json
|
||||
const tempFolderName = (
|
||||
tempContent instanceof URI
|
||||
? tempContent
|
||||
: tempContent.uri.parent
|
||||
tempContent instanceof URI ? tempContent : tempContent.uri.parent
|
||||
).path.base.toLowerCase();
|
||||
this.fileService.onDidFilesChange((event) => {
|
||||
for (const { resource } of event.changes) {
|
||||
if (
|
||||
resource.path.base === 'launch.json' &&
|
||||
resource.parent.path.base.toLowerCase() ===
|
||||
tempFolderName
|
||||
resource.parent.path.base.toLowerCase() === tempFolderName
|
||||
) {
|
||||
this.getTempLaunchJsonContent().then((config) => {
|
||||
if (config && !(config instanceof URI)) {
|
||||
@@ -85,11 +82,8 @@ export class DebugConfigurationManager extends TheiaDebugConfigurationManager {
|
||||
continue;
|
||||
}
|
||||
const configurations: DebugConfiguration[] =
|
||||
tempContent instanceof URI
|
||||
? []
|
||||
: tempContent.configurations;
|
||||
const uri =
|
||||
tempContent instanceof URI ? undefined : tempContent.uri;
|
||||
tempContent instanceof URI ? [] : tempContent.configurations;
|
||||
const uri = tempContent instanceof URI ? undefined : tempContent.uri;
|
||||
const model = new DebugConfigurationModel(
|
||||
key,
|
||||
this.preferences,
|
||||
@@ -112,9 +106,7 @@ export class DebugConfigurationManager extends TheiaDebugConfigurationManager {
|
||||
}, 500);
|
||||
|
||||
protected async getTempLaunchJsonContent(): Promise<
|
||||
| (TheiaDebugConfigurationModel.JsonContent & { uri: URI })
|
||||
| URI
|
||||
| undefined
|
||||
(TheiaDebugConfigurationModel.JsonContent & { uri: URI }) | URI | undefined
|
||||
> {
|
||||
const sketch = await this.sketchesServiceClient.currentSketch();
|
||||
if (!sketch) {
|
||||
@@ -126,9 +118,7 @@ export class DebugConfigurationManager extends TheiaDebugConfigurationManager {
|
||||
try {
|
||||
const uri = tempFolderUri.resolve('launch.json');
|
||||
const { value } = await this.fileService.read(uri);
|
||||
const configurations = DebugConfigurationModel.parse(
|
||||
JSON.parse(value)
|
||||
);
|
||||
const configurations = DebugConfigurationModel.parse(JSON.parse(value));
|
||||
return { uri, configurations };
|
||||
} catch (err) {
|
||||
if (
|
||||
|
@@ -62,9 +62,7 @@ export class DebugEditorModel extends TheiaDebugEditorModel {
|
||||
const model = codeEditor.getModel()!;
|
||||
const overrides = {
|
||||
resource: model.uri,
|
||||
overrideIdentifier: (
|
||||
model as any
|
||||
).getLanguageIdentifier().language,
|
||||
overrideIdentifier: (model as any).getLanguageIdentifier().language,
|
||||
};
|
||||
const { enabled, delay, sticky } =
|
||||
this.configurationService._configuration.getValue(
|
||||
@@ -86,8 +84,7 @@ export class DebugEditorModel extends TheiaDebugEditorModel {
|
||||
|
||||
private isCurrentEditorFrame(uri: URI): boolean {
|
||||
return (
|
||||
this.sessions.currentFrame?.source?.uri.toString() ===
|
||||
uri.toString()
|
||||
this.sessions.currentFrame?.source?.uri.toString() === uri.toString()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -98,9 +95,10 @@ export class DebugEditorModel extends TheiaDebugEditorModel {
|
||||
this.toDisposeOnRenderFrames.dispose();
|
||||
|
||||
this.toggleExceptionWidget();
|
||||
const [newFrameDecorations, inlineValueDecorations] = await Promise.all(
|
||||
[this.createFrameDecorations(), this.createInlineValueDecorations()]
|
||||
);
|
||||
const [newFrameDecorations, inlineValueDecorations] = await Promise.all([
|
||||
this.createFrameDecorations(),
|
||||
this.createInlineValueDecorations(),
|
||||
]);
|
||||
const codeEditor = this.editor.getControl();
|
||||
codeEditor.removeDecorations(INLINE_VALUE_DECORATION_KEY);
|
||||
codeEditor.setDecorations(
|
||||
|
@@ -45,10 +45,7 @@ export class DebugHoverWidget extends TheiaDebugHoverWidget {
|
||||
this.hide();
|
||||
return;
|
||||
}
|
||||
if (
|
||||
this.options &&
|
||||
this.options.selection.equalsRange(options.selection)
|
||||
) {
|
||||
if (this.options && this.options.selection.equalsRange(options.selection)) {
|
||||
return;
|
||||
}
|
||||
if (!this.isAttached) {
|
||||
@@ -73,9 +70,9 @@ export class DebugHoverWidget extends TheiaDebugHoverWidget {
|
||||
})
|
||||
);
|
||||
}
|
||||
const expression = await (
|
||||
this.hoverSource as DebugHoverSource
|
||||
).evaluate2(matchingExpression);
|
||||
const expression = await (this.hoverSource as DebugHoverSource).evaluate2(
|
||||
matchingExpression
|
||||
);
|
||||
if (!expression || !expression.value) {
|
||||
toFocus.dispose();
|
||||
this.hide();
|
||||
|
@@ -6,13 +6,8 @@ import { DebugSessionManager as TheiaDebugSessionManager } from '@theia/debug/li
|
||||
|
||||
@injectable()
|
||||
export class DebugSessionManager extends TheiaDebugSessionManager {
|
||||
async start(
|
||||
options: DebugSessionOptions
|
||||
): Promise<DebugSession | undefined> {
|
||||
return this.progressService.withProgress(
|
||||
'Start...',
|
||||
'debug',
|
||||
async () => {
|
||||
async start(options: DebugSessionOptions): Promise<DebugSession | undefined> {
|
||||
return this.progressService.withProgress('Start...', 'debug', async () => {
|
||||
try {
|
||||
// Only save when dirty. To avoid saving temporary sketches.
|
||||
// This is a quick fix for not saving the editor when there are no dirty editors.
|
||||
@@ -53,7 +48,6 @@ export class DebugSessionManager extends TheiaDebugSessionManager {
|
||||
console.error('Error starting the debug session', e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -9,10 +9,8 @@ export class EditorCommandContribution extends TheiaEditorCommandContribution {
|
||||
this.editorPreferences.onPreferenceChanged(
|
||||
({ preferenceName, newValue, oldValue }) => {
|
||||
if (preferenceName === 'editor.autoSave') {
|
||||
const autoSaveWasOnBeforeChange =
|
||||
!oldValue || oldValue === 'on';
|
||||
const autoSaveIsOnAfterChange =
|
||||
!newValue || newValue === 'on';
|
||||
const autoSaveWasOnBeforeChange = !oldValue || oldValue === 'on';
|
||||
const autoSaveIsOnAfterChange = !newValue || newValue === 'on';
|
||||
if (!autoSaveWasOnBeforeChange && autoSaveIsOnAfterChange) {
|
||||
this.shell.saveAll();
|
||||
}
|
||||
|
@@ -30,9 +30,7 @@ export class EditorWidgetFactory extends TheiaEditorWidgetFactory {
|
||||
if (sketch && Sketch.isInSketch(uri, sketch)) {
|
||||
const isTemp = await this.sketchesService.isTemp(sketch);
|
||||
if (isTemp) {
|
||||
widget.title.caption = `Unsaved – ${this.labelProvider.getName(
|
||||
uri
|
||||
)}`;
|
||||
widget.title.caption = `Unsaved – ${this.labelProvider.getName(uri)}`;
|
||||
}
|
||||
}
|
||||
return widget;
|
||||
|
@@ -23,9 +23,7 @@ export class ProblemManager extends TheiaProblemManager {
|
||||
.getConfiguration()
|
||||
.then(({ dataDirUri }) => (this.dataDirUri = new URI(dataDirUri)))
|
||||
.catch((err) =>
|
||||
this.logger.error(
|
||||
`Failed to determine the data directory: ${err}`
|
||||
)
|
||||
this.logger.error(`Failed to determine the data directory: ${err}`)
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -15,9 +15,7 @@ export class NotificationCenterComponent extends TheiaNotificationCenterComponen
|
||||
}`}
|
||||
>
|
||||
<div className="theia-notification-center-header">
|
||||
<div className="theia-notification-center-header-title">
|
||||
{title}
|
||||
</div>
|
||||
<div className="theia-notification-center-header-title">{title}</div>
|
||||
<div className="theia-notification-center-header-actions">
|
||||
<ul className="theia-notification-actions">
|
||||
<li
|
||||
|
@@ -3,15 +3,8 @@ import { NotificationComponent as TheiaNotificationComponent } from '@theia/mess
|
||||
|
||||
export class NotificationComponent extends TheiaNotificationComponent {
|
||||
render(): React.ReactNode {
|
||||
const {
|
||||
messageId,
|
||||
message,
|
||||
type,
|
||||
collapsed,
|
||||
expandable,
|
||||
source,
|
||||
actions,
|
||||
} = this.props.notification;
|
||||
const { messageId, message, type, collapsed, expandable, source, actions } =
|
||||
this.props.notification;
|
||||
return (
|
||||
<div key={messageId} className="theia-notification-list-item">
|
||||
<div
|
||||
@@ -32,9 +25,7 @@ export class NotificationComponent extends TheiaNotificationComponent {
|
||||
<ul className="theia-notification-actions">
|
||||
{expandable && (
|
||||
<li
|
||||
className={
|
||||
collapsed ? 'expand' : 'collapse'
|
||||
}
|
||||
className={collapsed ? 'expand' : 'collapse'}
|
||||
title={collapsed ? 'Expand' : 'Collapse'}
|
||||
data-message-id={messageId}
|
||||
onClick={this.onToggleExpansion}
|
||||
|
@@ -24,16 +24,12 @@ export class NotificationManager extends TheiaNotificationManager {
|
||||
notification.message =
|
||||
originalMessage.text && update.message
|
||||
? `${originalMessage.text}: ${update.message}`
|
||||
: originalMessage.text ||
|
||||
update?.message ||
|
||||
notification.message;
|
||||
: originalMessage.text || update?.message || notification.message;
|
||||
|
||||
// Unlike in Theia, we allow resetting the progress monitor to NaN to enforce unknown progress.
|
||||
const candidate = this.toPlainProgress(update);
|
||||
notification.progress =
|
||||
typeof candidate === 'number'
|
||||
? candidate
|
||||
: notification.progress;
|
||||
typeof candidate === 'number' ? candidate : notification.progress;
|
||||
}
|
||||
this.fireUpdatedEvent();
|
||||
}
|
||||
|
@@ -34,9 +34,7 @@ export class MonacoEditorProvider extends TheiaMonacoEditorProvider {
|
||||
return editor;
|
||||
}
|
||||
|
||||
private installCustomReferencesController(
|
||||
editor: MonacoEditor
|
||||
): Disposable {
|
||||
private installCustomReferencesController(editor: MonacoEditor): Disposable {
|
||||
const control = editor.getControl();
|
||||
const referencesController =
|
||||
control._contributions['editor.contrib.referencesController'];
|
||||
@@ -66,9 +64,7 @@ export class MonacoEditorProvider extends TheiaMonacoEditorProvider {
|
||||
._preview as monaco.editor.ICodeEditor;
|
||||
if (preview) {
|
||||
toDisposeBeforeToggleWidget.push(
|
||||
preview.onDidChangeModel(() =>
|
||||
this.updateReadOnlyState(preview)
|
||||
)
|
||||
preview.onDidChangeModel(() => this.updateReadOnlyState(preview))
|
||||
);
|
||||
this.updateReadOnlyState(preview);
|
||||
}
|
||||
|
@@ -13,9 +13,7 @@ export class MonacoTextModelService extends TheiaMonacoTextModelService {
|
||||
@inject(SketchesServiceClientImpl)
|
||||
protected readonly sketchesServiceClient: SketchesServiceClientImpl;
|
||||
|
||||
protected async createModel(
|
||||
resource: Resource
|
||||
): Promise<MonacoEditorModel> {
|
||||
protected async createModel(resource: Resource): Promise<MonacoEditorModel> {
|
||||
const factory = this.factories
|
||||
.getContributions()
|
||||
.find(({ scheme }) => resource.uri.scheme === scheme);
|
||||
|
@@ -23,9 +23,7 @@ export class OutputChannelManager extends TheiaOutputChannelManager {
|
||||
let resource = this.resources.get(name);
|
||||
if (!resource) {
|
||||
const uri = OutputUri.create(name);
|
||||
const editorModelRef = new Deferred<
|
||||
IReference<MonacoEditorModel>
|
||||
>();
|
||||
const editorModelRef = new Deferred<IReference<MonacoEditorModel>>();
|
||||
resource = this.createResource({ uri, editorModelRef });
|
||||
this.resources.set(name, resource);
|
||||
this.textModelService
|
||||
@@ -35,10 +33,7 @@ export class OutputChannelManager extends TheiaOutputChannelManager {
|
||||
|
||||
const channel = new OutputChannel(resource, this.preferences);
|
||||
this.channels.set(name, channel);
|
||||
this.toDisposeOnChannelDeletion.set(
|
||||
name,
|
||||
this.registerListeners(channel)
|
||||
);
|
||||
this.toDisposeOnChannelDeletion.set(name, this.registerListeners(channel));
|
||||
this.channelAddedEmitter.fire(channel);
|
||||
if (!this.selectedChannel) {
|
||||
this.selectedChannel = channel;
|
||||
|
@@ -15,15 +15,11 @@ export class SearchInWorkspaceFrontendContribution extends TheiaSearchInWorkspac
|
||||
|
||||
registerMenus(registry: MenuModelRegistry): void {
|
||||
super.registerMenus(registry);
|
||||
registry.unregisterMenuAction(
|
||||
SearchInWorkspaceCommands.OPEN_SIW_WIDGET
|
||||
);
|
||||
registry.unregisterMenuAction(SearchInWorkspaceCommands.OPEN_SIW_WIDGET);
|
||||
}
|
||||
|
||||
registerKeybindings(keybindings: KeybindingRegistry): void {
|
||||
super.registerKeybindings(keybindings);
|
||||
keybindings.unregisterKeybinding(
|
||||
SearchInWorkspaceCommands.OPEN_SIW_WIDGET
|
||||
);
|
||||
keybindings.unregisterKeybinding(SearchInWorkspaceCommands.OPEN_SIW_WIDGET);
|
||||
}
|
||||
}
|
||||
|
@@ -35,9 +35,7 @@ export class SearchInWorkspaceResultTreeWidget extends TheiaSearchInWorkspaceRes
|
||||
(this._replaceTerm.length - this.searchTerm.length) *
|
||||
leftPositionedNodes.length;
|
||||
const start = lines[l.line - 1].substr(0, l.character - 1 + diff);
|
||||
const end = lines[l.line - 1].substr(
|
||||
l.character - 1 + diff + l.length
|
||||
);
|
||||
const end = lines[l.line - 1].substr(l.character - 1 + diff + l.length);
|
||||
lines[l.line - 1] = start + this._replaceTerm + end;
|
||||
});
|
||||
|
||||
|
@@ -22,27 +22,18 @@ export class SearchInWorkspaceWidget extends TheiaSearchInWorkspaceWidget {
|
||||
id={kind + '-glob-field'}
|
||||
onKeyUp={(e) => {
|
||||
if (e.target) {
|
||||
const targetValue =
|
||||
(e.target as HTMLInputElement).value || '';
|
||||
const targetValue = (e.target as HTMLInputElement).value || '';
|
||||
let shouldSearch =
|
||||
Key.ENTER.keyCode ===
|
||||
KeyCode.createKeyCode(e.nativeEvent).key
|
||||
?.keyCode;
|
||||
const currentOptions = (
|
||||
this.searchInWorkspaceOptions[kind] || []
|
||||
)
|
||||
KeyCode.createKeyCode(e.nativeEvent).key?.keyCode;
|
||||
const currentOptions = (this.searchInWorkspaceOptions[kind] || [])
|
||||
.slice()
|
||||
.map((s) => s.trim())
|
||||
.sort();
|
||||
const candidateOptions = this.splitOnComma(
|
||||
targetValue
|
||||
)
|
||||
const candidateOptions = this.splitOnComma(targetValue)
|
||||
.map((s) => s.trim())
|
||||
.sort();
|
||||
const sameAs = (
|
||||
left: string[],
|
||||
right: string[]
|
||||
) => {
|
||||
const sameAs = (left: string[], right: string[]) => {
|
||||
if (left.length !== right.length) {
|
||||
return false;
|
||||
}
|
||||
|
@@ -2,8 +2,14 @@ import { inject, injectable } from 'inversify';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import { open } from '@theia/core/lib/browser/opener-service';
|
||||
import { FileStat } from '@theia/filesystem/lib/common/files';
|
||||
import { CommandRegistry, CommandService } from '@theia/core/lib/common/command';
|
||||
import { WorkspaceCommandContribution as TheiaWorkspaceCommandContribution, WorkspaceCommands } from '@theia/workspace/lib/browser/workspace-commands';
|
||||
import {
|
||||
CommandRegistry,
|
||||
CommandService,
|
||||
} from '@theia/core/lib/common/command';
|
||||
import {
|
||||
WorkspaceCommandContribution as TheiaWorkspaceCommandContribution,
|
||||
WorkspaceCommands,
|
||||
} from '@theia/workspace/lib/browser/workspace-commands';
|
||||
import { Sketch, SketchesService } from '../../../common/protocol';
|
||||
import { WorkspaceInputDialog } from './workspace-input-dialog';
|
||||
import { SketchesServiceClientImpl } from '../../../common/protocol/sketches-service-client-impl';
|
||||
@@ -12,7 +18,6 @@ import { SingleTextInputDialog } from '@theia/core/lib/browser';
|
||||
|
||||
@injectable()
|
||||
export class WorkspaceCommandContribution extends TheiaWorkspaceCommandContribution {
|
||||
|
||||
@inject(SketchesServiceClientImpl)
|
||||
protected readonly sketchesServiceClient: SketchesServiceClientImpl;
|
||||
|
||||
@@ -25,13 +30,19 @@ export class WorkspaceCommandContribution extends TheiaWorkspaceCommandContribut
|
||||
registerCommands(registry: CommandRegistry): void {
|
||||
super.registerCommands(registry);
|
||||
registry.unregisterCommand(WorkspaceCommands.NEW_FILE);
|
||||
registry.registerCommand(WorkspaceCommands.NEW_FILE, this.newWorkspaceRootUriAwareCommandHandler({
|
||||
execute: uri => this.newFile(uri)
|
||||
}));
|
||||
registry.registerCommand(
|
||||
WorkspaceCommands.NEW_FILE,
|
||||
this.newWorkspaceRootUriAwareCommandHandler({
|
||||
execute: (uri) => this.newFile(uri),
|
||||
})
|
||||
);
|
||||
registry.unregisterCommand(WorkspaceCommands.FILE_RENAME);
|
||||
registry.registerCommand(WorkspaceCommands.FILE_RENAME, this.newUriAwareCommandHandler({
|
||||
execute: uri => this.renameFile(uri)
|
||||
}));
|
||||
registry.registerCommand(
|
||||
WorkspaceCommands.FILE_RENAME,
|
||||
this.newUriAwareCommandHandler({
|
||||
execute: (uri) => this.renameFile(uri),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
protected async newFile(uri: URI | undefined): Promise<void> {
|
||||
@@ -44,11 +55,14 @@ export class WorkspaceCommandContribution extends TheiaWorkspaceCommandContribut
|
||||
}
|
||||
|
||||
const parentUri = parent.resource;
|
||||
const dialog = new WorkspaceInputDialog({
|
||||
const dialog = new WorkspaceInputDialog(
|
||||
{
|
||||
title: 'Name for new file',
|
||||
parentUri,
|
||||
validate: name => this.validateFileName(name, parent, true)
|
||||
}, this.labelProvider);
|
||||
validate: (name) => this.validateFileName(name, parent, true),
|
||||
},
|
||||
this.labelProvider
|
||||
);
|
||||
|
||||
const name = await dialog.open();
|
||||
const nameWithExt = this.maybeAppendInoExt(name);
|
||||
@@ -60,12 +74,20 @@ export class WorkspaceCommandContribution extends TheiaWorkspaceCommandContribut
|
||||
}
|
||||
}
|
||||
|
||||
protected async validateFileName(name: string, parent: FileStat, recursive = false): Promise<string> {
|
||||
protected async validateFileName(
|
||||
name: string,
|
||||
parent: FileStat,
|
||||
recursive = false
|
||||
): Promise<string> {
|
||||
// In the Java IDE the followings are the rules:
|
||||
// - `name` without an extension should default to `name.ino`.
|
||||
// - `name` with a single trailing `.` also defaults to `name.ino`.
|
||||
const nameWithExt = this.maybeAppendInoExt(name);
|
||||
const errorMessage = await super.validateFileName(nameWithExt, parent, recursive);
|
||||
const errorMessage = await super.validateFileName(
|
||||
nameWithExt,
|
||||
parent,
|
||||
recursive
|
||||
);
|
||||
if (errorMessage) {
|
||||
return errorMessage;
|
||||
}
|
||||
@@ -85,10 +107,10 @@ export class WorkspaceCommandContribution extends TheiaWorkspaceCommandContribut
|
||||
}
|
||||
if (name.trim().length) {
|
||||
if (name.indexOf('.') === -1) {
|
||||
return `${name}.ino`
|
||||
return `${name}.ino`;
|
||||
}
|
||||
if (name.lastIndexOf('.') === name.length - 1) {
|
||||
return `${name.slice(0, -1)}.ino`
|
||||
return `${name.slice(0, -1)}.ino`;
|
||||
}
|
||||
}
|
||||
return name;
|
||||
@@ -104,7 +126,9 @@ export class WorkspaceCommandContribution extends TheiaWorkspaceCommandContribut
|
||||
}
|
||||
|
||||
// file belongs to another sketch, do not allow rename
|
||||
const parentsketch = await this.sketchService.getSketchFolder(uri.toString());
|
||||
const parentsketch = await this.sketchService.getSketchFolder(
|
||||
uri.toString()
|
||||
);
|
||||
if (parentsketch && parentsketch.uri !== sketch.uri) {
|
||||
return;
|
||||
}
|
||||
@@ -113,9 +137,12 @@ export class WorkspaceCommandContribution extends TheiaWorkspaceCommandContribut
|
||||
const options = {
|
||||
execOnlyIfTemp: false,
|
||||
openAfterMove: true,
|
||||
wipeOriginal: true
|
||||
wipeOriginal: true,
|
||||
};
|
||||
await this.commandService.executeCommand(SaveAsSketch.Commands.SAVE_AS_SKETCH.id, options);
|
||||
await this.commandService.executeCommand(
|
||||
SaveAsSketch.Commands.SAVE_AS_SKETCH.id,
|
||||
options
|
||||
);
|
||||
return;
|
||||
}
|
||||
const parent = await this.getParent(uri);
|
||||
@@ -128,14 +155,14 @@ export class WorkspaceCommandContribution extends TheiaWorkspaceCommandContribut
|
||||
initialValue,
|
||||
initialSelectionRange: {
|
||||
start: 0,
|
||||
end: uri.path.name.length
|
||||
end: uri.path.name.length,
|
||||
},
|
||||
validate: (name, mode) => {
|
||||
if (initialValue === name && mode === 'preview') {
|
||||
return false;
|
||||
}
|
||||
return this.validateFileName(name, parent, false);
|
||||
}
|
||||
},
|
||||
});
|
||||
const newName = await dialog.open();
|
||||
const newNameWithExt = this.maybeAppendInoExt(newName);
|
||||
@@ -145,5 +172,4 @@ export class WorkspaceCommandContribution extends TheiaWorkspaceCommandContribut
|
||||
this.fileService.move(oldUri, newUri);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -87,9 +87,7 @@ export class WorkspaceService extends TheiaWorkspaceService {
|
||||
this.appStateService
|
||||
.reachedState('ready')
|
||||
.then(() => this.application.shell.update());
|
||||
this.logger.fatal(
|
||||
`Failed to determine the sketch directory: ${err}`
|
||||
);
|
||||
this.logger.fatal(`Failed to determine the sketch directory: ${err}`);
|
||||
this.messageService.error(
|
||||
'There was an error creating the sketch directory. ' +
|
||||
'See the log for more details. ' +
|
||||
|
@@ -49,9 +49,7 @@ export class ArduinoToolbarComponent extends React.Component<
|
||||
const command = this.props.commands.getCommand(item.command);
|
||||
const cls = `${ARDUINO_TOOLBAR_ITEM_CLASS} ${
|
||||
TabBarToolbar.Styles.TAB_BAR_TOOLBAR_ITEM
|
||||
} ${
|
||||
command && this.props.commandIsEnabled(command.id) ? 'enabled' : ''
|
||||
} ${
|
||||
} ${command && this.props.commandIsEnabled(command.id) ? 'enabled' : ''} ${
|
||||
command && this.props.commandIsToggled(command.id) ? 'toggled' : ''
|
||||
}`;
|
||||
return (
|
||||
@@ -62,9 +60,7 @@ export class ArduinoToolbarComponent extends React.Component<
|
||||
id={item.id}
|
||||
className={className}
|
||||
onClick={this.props.executeCommand}
|
||||
onMouseOver={() =>
|
||||
this.setState({ tooltip: item.tooltip || '' })
|
||||
}
|
||||
onMouseOver={() => this.setState({ tooltip: item.tooltip || '' })}
|
||||
onMouseOut={() => this.setState({ tooltip: '' })}
|
||||
title={item.tooltip}
|
||||
>
|
||||
@@ -77,19 +73,14 @@ export class ArduinoToolbarComponent extends React.Component<
|
||||
|
||||
render(): React.ReactNode {
|
||||
const tooltip = (
|
||||
<div
|
||||
key="arduino-toolbar-tooltip"
|
||||
className={'arduino-toolbar-tooltip'}
|
||||
>
|
||||
<div key="arduino-toolbar-tooltip" className={'arduino-toolbar-tooltip'}>
|
||||
{this.state.tooltip}
|
||||
</div>
|
||||
);
|
||||
const items = [
|
||||
<React.Fragment key={this.props.side + '-arduino-toolbar-tooltip'}>
|
||||
{[...this.props.items].map((item) =>
|
||||
TabBarToolbarItem.is(item)
|
||||
? this.renderItem(item)
|
||||
: item.render()
|
||||
TabBarToolbarItem.is(item) ? this.renderItem(item) : item.render()
|
||||
)}
|
||||
</React.Fragment>,
|
||||
];
|
||||
|
@@ -48,9 +48,7 @@ export class ArduinoSelect<T> extends Select<T> {
|
||||
primary50: 'var(--theia-list-activeSelectionBackground)',
|
||||
},
|
||||
});
|
||||
const DropdownIndicator = () => (
|
||||
<span className="fa fa-caret-down caret" />
|
||||
);
|
||||
const DropdownIndicator = () => <span className="fa fa-caret-down caret" />;
|
||||
return (
|
||||
<Select
|
||||
{...this.props}
|
||||
|
@@ -40,18 +40,13 @@ export class CloudSketchbookCompositeWidget extends BaseWidget {
|
||||
Widget.attach(this.cloudSketchbookTreeWidget, this.compositeNode);
|
||||
ReactDOM.render(
|
||||
<UserStatus
|
||||
model={
|
||||
this.cloudSketchbookTreeWidget
|
||||
.model as CloudSketchbookTreeModel
|
||||
}
|
||||
model={this.cloudSketchbookTreeWidget.model as CloudSketchbookTreeModel}
|
||||
authenticationService={this.authenticationService}
|
||||
/>,
|
||||
this.cloudUserStatusNode
|
||||
);
|
||||
this.toDisposeOnDetach.push(
|
||||
Disposable.create(() =>
|
||||
Widget.detach(this.cloudSketchbookTreeWidget)
|
||||
)
|
||||
Disposable.create(() => Widget.detach(this.cloudSketchbookTreeWidget))
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -55,9 +55,7 @@ export namespace CloudSketchbookCommands {
|
||||
export namespace Arg {
|
||||
export function is(arg: Partial<Arg> | undefined): arg is Arg {
|
||||
return (
|
||||
!!arg &&
|
||||
!!arg.node &&
|
||||
arg.model instanceof CloudSketchbookTreeModel
|
||||
!!arg && !!arg.node && arg.model instanceof CloudSketchbookTreeModel
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -130,8 +128,7 @@ export class CloudSketchbookContribution extends Contribution {
|
||||
@inject(MainMenuManager)
|
||||
protected readonly mainMenuManager: MainMenuManager;
|
||||
|
||||
protected readonly toDisposeBeforeNewContextMenu =
|
||||
new DisposableCollection();
|
||||
protected readonly toDisposeBeforeNewContextMenu = new DisposableCollection();
|
||||
|
||||
registerMenus(menus: MenuModelRegistry): void {
|
||||
menus.registerMenuAction(ArduinoMenus.FILE__ADVANCED_SUBMENU, {
|
||||
@@ -142,9 +139,7 @@ export class CloudSketchbookContribution extends Contribution {
|
||||
}
|
||||
|
||||
registerCommands(registry: CommandRegistry): void {
|
||||
registry.registerCommand(
|
||||
CloudSketchbookCommands.TOGGLE_CLOUD_SKETCHBOOK,
|
||||
{
|
||||
registry.registerCommand(CloudSketchbookCommands.TOGGLE_CLOUD_SKETCHBOOK, {
|
||||
execute: () => {
|
||||
this.preferenceService.set(
|
||||
'arduino.cloud.enabled',
|
||||
@@ -154,8 +149,7 @@ export class CloudSketchbookContribution extends Contribution {
|
||||
},
|
||||
isEnabled: () => true,
|
||||
isVisible: () => true,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
registry.registerCommand(CloudSketchbookCommands.PULL_SKETCH, {
|
||||
execute: (arg) => arg.model.sketchbookTree().pull(arg),
|
||||
@@ -194,9 +188,7 @@ export class CloudSketchbookContribution extends Contribution {
|
||||
CloudSketchbookTree.CloudSketchDirNode.is(arg.node),
|
||||
});
|
||||
|
||||
registry.registerCommand(
|
||||
CloudSketchbookCommands.OPEN_SKETCH_SHARE_DIALOG,
|
||||
{
|
||||
registry.registerCommand(CloudSketchbookCommands.OPEN_SKETCH_SHARE_DIALOG, {
|
||||
execute: (arg) => {
|
||||
new ShareSketchDialog({
|
||||
node: arg.node,
|
||||
@@ -210,8 +202,7 @@ export class CloudSketchbookContribution extends Contribution {
|
||||
isVisible: (arg) =>
|
||||
CloudSketchbookCommands.Arg.is(arg) &&
|
||||
CloudSketchbookTree.CloudSketchDirNode.is(arg.node),
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
registry.registerCommand(
|
||||
CloudSketchbookCommands.OPEN_SKETCHBOOKSYNC_CONTEXT_MENU,
|
||||
@@ -235,10 +226,8 @@ export class CloudSketchbookContribution extends Contribution {
|
||||
this.menuRegistry.registerMenuAction(
|
||||
SKETCHBOOKSYNC__CONTEXT__MAIN_GROUP,
|
||||
{
|
||||
commandId:
|
||||
CloudSketchbookCommands.OPEN_IN_CLOUD_EDITOR.id,
|
||||
label: CloudSketchbookCommands.OPEN_IN_CLOUD_EDITOR
|
||||
.label,
|
||||
commandId: CloudSketchbookCommands.OPEN_IN_CLOUD_EDITOR.id,
|
||||
label: CloudSketchbookCommands.OPEN_IN_CLOUD_EDITOR.label,
|
||||
order: '0',
|
||||
}
|
||||
);
|
||||
@@ -253,11 +242,8 @@ export class CloudSketchbookContribution extends Contribution {
|
||||
this.menuRegistry.registerMenuAction(
|
||||
SKETCHBOOKSYNC__CONTEXT__MAIN_GROUP,
|
||||
{
|
||||
commandId:
|
||||
CloudSketchbookCommands.OPEN_SKETCH_SHARE_DIALOG
|
||||
.id,
|
||||
label: CloudSketchbookCommands
|
||||
.OPEN_SKETCH_SHARE_DIALOG.label,
|
||||
commandId: CloudSketchbookCommands.OPEN_SKETCH_SHARE_DIALOG.id,
|
||||
label: CloudSketchbookCommands.OPEN_SKETCH_SHARE_DIALOG.label,
|
||||
order: '1',
|
||||
}
|
||||
);
|
||||
@@ -269,24 +255,20 @@ export class CloudSketchbookContribution extends Contribution {
|
||||
)
|
||||
);
|
||||
|
||||
const currentSketch =
|
||||
await this.sketchServiceClient.currentSketch();
|
||||
const currentSketch = await this.sketchServiceClient.currentSketch();
|
||||
|
||||
const localUri =
|
||||
await arg.model.cloudSketchbookTree.localUri(arg.node);
|
||||
const localUri = await arg.model.cloudSketchbookTree.localUri(
|
||||
arg.node
|
||||
);
|
||||
let underlying = null;
|
||||
if (arg.node && localUri) {
|
||||
underlying =
|
||||
await this.fileService.toUnderlyingResource(
|
||||
localUri
|
||||
);
|
||||
underlying = await this.fileService.toUnderlyingResource(localUri);
|
||||
}
|
||||
|
||||
// disable the "open sketch" command for the current sketch and for those not in sync
|
||||
if (
|
||||
!underlying ||
|
||||
(currentSketch &&
|
||||
currentSketch.uri === underlying.toString())
|
||||
(currentSketch && currentSketch.uri === underlying.toString())
|
||||
) {
|
||||
const placeholder = new PlaceholderMenuNode(
|
||||
SKETCHBOOKSYNC__CONTEXT__MAIN_GROUP,
|
||||
@@ -298,9 +280,7 @@ export class CloudSketchbookContribution extends Contribution {
|
||||
);
|
||||
this.toDisposeBeforeNewContextMenu.push(
|
||||
Disposable.create(() =>
|
||||
this.menuRegistry.unregisterMenuNode(
|
||||
placeholder.id
|
||||
)
|
||||
this.menuRegistry.unregisterMenuNode(placeholder.id)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
@@ -308,8 +288,7 @@ export class CloudSketchbookContribution extends Contribution {
|
||||
this.menuRegistry.registerMenuAction(
|
||||
SKETCHBOOKSYNC__CONTEXT__MAIN_GROUP,
|
||||
{
|
||||
commandId:
|
||||
SketchbookCommands.OPEN_NEW_WINDOW.id,
|
||||
commandId: SketchbookCommands.OPEN_NEW_WINDOW.id,
|
||||
label: SketchbookCommands.OPEN_NEW_WINDOW.label,
|
||||
}
|
||||
);
|
||||
@@ -326,9 +305,7 @@ export class CloudSketchbookContribution extends Contribution {
|
||||
menuPath: SKETCHBOOKSYNC__CONTEXT,
|
||||
anchor: {
|
||||
x: container.getBoundingClientRect().left,
|
||||
y:
|
||||
container.getBoundingClientRect().top +
|
||||
container.offsetHeight,
|
||||
y: container.getBoundingClientRect().top + container.offsetHeight,
|
||||
},
|
||||
args: arg,
|
||||
};
|
||||
@@ -345,18 +322,13 @@ export class CloudSketchbookContribution extends Contribution {
|
||||
return;
|
||||
}
|
||||
|
||||
this.menuRegistry.registerMenuAction(
|
||||
CLOUD_USER__CONTEXT__MAIN_GROUP,
|
||||
{
|
||||
this.menuRegistry.registerMenuAction(CLOUD_USER__CONTEXT__MAIN_GROUP, {
|
||||
commandId: CloudUserCommands.LOGOUT.id,
|
||||
label: CloudUserCommands.LOGOUT.label,
|
||||
}
|
||||
);
|
||||
});
|
||||
this.toDisposeBeforeNewContextMenu.push(
|
||||
Disposable.create(() =>
|
||||
this.menuRegistry.unregisterMenuAction(
|
||||
CloudUserCommands.LOGOUT
|
||||
)
|
||||
this.menuRegistry.unregisterMenuAction(CloudUserCommands.LOGOUT)
|
||||
)
|
||||
);
|
||||
|
||||
|
@@ -81,9 +81,7 @@ export class CloudSketchbookTreeModel extends SketchbookTreeModel {
|
||||
protected init(): void {
|
||||
super.init();
|
||||
this.toDispose.push(
|
||||
this.authenticationService.onSessionDidChange(() =>
|
||||
this.updateRoot()
|
||||
)
|
||||
this.authenticationService.onSessionDidChange(() => this.updateRoot())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -93,10 +91,7 @@ export class CloudSketchbookTreeModel extends SketchbookTreeModel {
|
||||
this.tree.root = undefined;
|
||||
return;
|
||||
}
|
||||
this.createApi.init(
|
||||
this.authenticationService,
|
||||
this.arduinoPreferences
|
||||
);
|
||||
this.createApi.init(this.authenticationService, this.arduinoPreferences);
|
||||
|
||||
const resources = await this.createApi.readDirectory(posix.sep, {
|
||||
recursive: true,
|
||||
@@ -116,9 +111,7 @@ export class CloudSketchbookTreeModel extends SketchbookTreeModel {
|
||||
fileStat.children
|
||||
?.filter(
|
||||
(child) =>
|
||||
!Object.keys(cache).includes(
|
||||
path + posix.sep + child.name
|
||||
)
|
||||
!Object.keys(cache).includes(path + posix.sep + child.name)
|
||||
)
|
||||
.forEach((child) => {
|
||||
const localChild: Create.Resource = {
|
||||
|
@@ -51,9 +51,7 @@ export class CloudSketchbookTreeWidget extends SketchbookTreeWidget {
|
||||
</div>
|
||||
<button
|
||||
className="theia-button"
|
||||
onClick={() =>
|
||||
shell.openExternal('https://create.arduino.cc/editor')
|
||||
}
|
||||
onClick={() => shell.openExternal('https://create.arduino.cc/editor')}
|
||||
>
|
||||
GO TO CLOUD
|
||||
</button>
|
||||
@@ -88,10 +86,7 @@ export class CloudSketchbookTreeWidget extends SketchbookTreeWidget {
|
||||
return classNames;
|
||||
}
|
||||
|
||||
protected renderInlineCommands(
|
||||
node: any,
|
||||
props: NodeProps
|
||||
): React.ReactNode {
|
||||
protected renderInlineCommands(node: any, props: NodeProps): React.ReactNode {
|
||||
if (
|
||||
CloudSketchbookTree.CloudSketchDirNode.is(node) &&
|
||||
node.commands &&
|
||||
@@ -110,9 +105,7 @@ export class CloudSketchbookTreeWidget extends SketchbookTreeWidget {
|
||||
<div className="cloud-sketchbook-welcome center">
|
||||
<div className="center item">
|
||||
<div>
|
||||
<p className="sign-in-title">
|
||||
Sign in to Arduino Cloud
|
||||
</p>
|
||||
<p className="sign-in-title">Sign in to Arduino Cloud</p>
|
||||
<p className="sign-in-desc">
|
||||
Sync and edit your Arduino Cloud Sketches
|
||||
</p>
|
||||
@@ -121,9 +114,7 @@ export class CloudSketchbookTreeWidget extends SketchbookTreeWidget {
|
||||
<button
|
||||
className="theia-button sign-in-cta"
|
||||
onClick={() =>
|
||||
this.commandRegistry.executeCommand(
|
||||
CloudUserCommands.LOGIN.id
|
||||
)
|
||||
this.commandRegistry.executeCommand(CloudUserCommands.LOGIN.id)
|
||||
}
|
||||
>
|
||||
SIGN IN
|
||||
@@ -154,9 +145,7 @@ export class CloudSketchbookTreeWidget extends SketchbookTreeWidget {
|
||||
// overwrite the uri using the local-cache
|
||||
const localUri = await this.cloudSketchbookTree.localUri(node);
|
||||
if (node && localUri) {
|
||||
const underlying = await this.fileService.toUnderlyingResource(
|
||||
localUri
|
||||
);
|
||||
const underlying = await this.fileService.toUnderlyingResource(localUri);
|
||||
uri = underlying;
|
||||
}
|
||||
|
||||
@@ -174,9 +163,7 @@ export class CloudSketchbookTreeWidget extends SketchbookTreeWidget {
|
||||
// if the localURI does not exists, ignore the double click, so that the sketch is not opened
|
||||
const localUri = await this.cloudSketchbookTree.localUri(node);
|
||||
if (node && localUri) {
|
||||
const underlying = await this.fileService.toUnderlyingResource(
|
||||
localUri
|
||||
);
|
||||
const underlying = await this.fileService.toUnderlyingResource(localUri);
|
||||
uri = underlying;
|
||||
super.handleDblClickEvent({ ...node, uri }, event);
|
||||
}
|
||||
|
@@ -60,8 +60,7 @@ export class CloudSketchbookTree extends SketchbookTree {
|
||||
node: CloudSketchbookTree.CloudSketchDirNode
|
||||
): Promise<boolean> {
|
||||
const warn =
|
||||
node.isPublic &&
|
||||
this.arduinoPreferences['arduino.cloud.pushpublic.warn'];
|
||||
node.isPublic && this.arduinoPreferences['arduino.cloud.pushpublic.warn'];
|
||||
|
||||
if (warn) {
|
||||
const ok = await new DoNotAskAgainConfirmDialog({
|
||||
@@ -123,28 +122,22 @@ export class CloudSketchbookTree extends SketchbookTree {
|
||||
// check if the sketch dir already exist
|
||||
if (node.synced) {
|
||||
const filesToPull = (
|
||||
await this.createApi.readDirectory(
|
||||
node.uri.path.toString(),
|
||||
{
|
||||
await this.createApi.readDirectory(node.uri.path.toString(), {
|
||||
secrets: true,
|
||||
}
|
||||
)
|
||||
})
|
||||
).filter((file: any) => !REMOTE_ONLY_FILES.includes(file.name));
|
||||
|
||||
await Promise.all(
|
||||
filesToPull.map((file: any) => {
|
||||
const uri = CreateUri.toUri(file);
|
||||
this.fileService.copy(
|
||||
uri,
|
||||
LocalCacheUri.root.resolve(uri.path),
|
||||
{ overwrite: true }
|
||||
);
|
||||
this.fileService.copy(uri, LocalCacheUri.root.resolve(uri.path), {
|
||||
overwrite: true,
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
// open the pulled files in the current workspace
|
||||
const currentSketch =
|
||||
await this.sketchServiceClient.currentSketch();
|
||||
const currentSketch = await this.sketchServiceClient.currentSketch();
|
||||
|
||||
if (
|
||||
currentSketch &&
|
||||
@@ -155,8 +148,7 @@ export class CloudSketchbookTree extends SketchbookTree {
|
||||
const localUri = LocalCacheUri.root.resolve(
|
||||
CreateUri.toUri(file).path
|
||||
);
|
||||
const underlying =
|
||||
await this.fileService.toUnderlyingResource(
|
||||
const underlying = await this.fileService.toUnderlyingResource(
|
||||
localUri
|
||||
);
|
||||
|
||||
@@ -238,15 +230,9 @@ export class CloudSketchbookTree extends SketchbookTree {
|
||||
if (localUri) {
|
||||
node.synced = true;
|
||||
if (
|
||||
node.commands?.indexOf(
|
||||
CloudSketchbookCommands.PUSH_SKETCH
|
||||
) === -1
|
||||
node.commands?.indexOf(CloudSketchbookCommands.PUSH_SKETCH) === -1
|
||||
) {
|
||||
node.commands.splice(
|
||||
1,
|
||||
0,
|
||||
CloudSketchbookCommands.PUSH_SKETCH
|
||||
);
|
||||
node.commands.splice(1, 0, CloudSketchbookCommands.PUSH_SKETCH);
|
||||
}
|
||||
// remove italic from synced nodes
|
||||
if (
|
||||
@@ -261,8 +247,7 @@ export class CloudSketchbookTree extends SketchbookTree {
|
||||
}
|
||||
|
||||
private async runWithState<T>(
|
||||
node: CloudSketchbookTree.CloudSketchDirNode &
|
||||
Partial<DecoratedTreeNode>,
|
||||
node: CloudSketchbookTree.CloudSketchDirNode & Partial<DecoratedTreeNode>,
|
||||
state: CloudSketchbookTree.CloudSketchDirNode.State,
|
||||
task: (node: CloudSketchbookTree.CloudSketchDirNode) => MaybePromise<T>
|
||||
): Promise<T> {
|
||||
@@ -282,8 +267,7 @@ export class CloudSketchbookTree extends SketchbookTree {
|
||||
delete node.state;
|
||||
// TODO: find a better way to attach and detach decorators. Do we need a proper `TreeDecorator` instead?
|
||||
const index = node.decorationData?.tailDecorations?.findIndex(
|
||||
(candidate) =>
|
||||
JSON.stringify(decoration) === JSON.stringify(candidate)
|
||||
(candidate) => JSON.stringify(decoration) === JSON.stringify(candidate)
|
||||
);
|
||||
if (typeof index === 'number' && index !== -1) {
|
||||
node.decorationData?.tailDecorations?.splice(index, 1);
|
||||
@@ -326,9 +310,7 @@ export class CloudSketchbookTree extends SketchbookTree {
|
||||
const localUri = await this.localUri(child);
|
||||
let underlying = null;
|
||||
if (localUri) {
|
||||
underlying = await this.fileService.toUnderlyingResource(
|
||||
localUri
|
||||
);
|
||||
underlying = await this.fileService.toUnderlyingResource(localUri);
|
||||
Object.assign(child, { underlying });
|
||||
}
|
||||
|
||||
@@ -346,9 +328,7 @@ export class CloudSketchbookTree extends SketchbookTree {
|
||||
this.mergeDecoration(child, this.notInSyncDecoration);
|
||||
}
|
||||
|
||||
commands.push(
|
||||
CloudSketchbookCommands.OPEN_SKETCHBOOKSYNC_CONTEXT_MENU
|
||||
);
|
||||
commands.push(CloudSketchbookCommands.OPEN_SKETCHBOOKSYNC_CONTEXT_MENU);
|
||||
|
||||
Object.assign(child, { commands });
|
||||
if (!this.showAllFiles) {
|
||||
@@ -365,10 +345,7 @@ export class CloudSketchbookTree extends SketchbookTree {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (
|
||||
CloudSketchbookTree.SketchDirNode.is(parent) &&
|
||||
!this.showAllFiles
|
||||
) {
|
||||
if (CloudSketchbookTree.SketchDirNode.is(parent) && !this.showAllFiles) {
|
||||
return [];
|
||||
}
|
||||
return children;
|
||||
@@ -514,8 +491,7 @@ export namespace CloudSketchbookTree {
|
||||
type: resource.type,
|
||||
...(!!depth && {
|
||||
children: CreateCache.childrenOf(resource, cache)?.map(
|
||||
(childResource) =>
|
||||
toFileStat(childResource, cache, depth - 1)
|
||||
(childResource) => toFileStat(childResource, cache, depth - 1)
|
||||
),
|
||||
}),
|
||||
};
|
||||
|
@@ -57,10 +57,7 @@ export class ComponentListItem<
|
||||
export namespace ComponentListItem {
|
||||
export interface Props<T extends ArduinoComponent> {
|
||||
readonly item: T;
|
||||
readonly install: (
|
||||
item: T,
|
||||
version?: Installable.Version
|
||||
) => Promise<void>;
|
||||
readonly install: (item: T, version?: Installable.Version) => Promise<void>;
|
||||
readonly uninstall: (item: T) => Promise<void>;
|
||||
readonly itemRenderer: ListItemRenderer<T>;
|
||||
}
|
||||
|
@@ -46,10 +46,7 @@ export namespace ComponentList {
|
||||
readonly itemLabel: (item: T) => string;
|
||||
readonly itemDeprecated: (item: T) => boolean;
|
||||
readonly itemRenderer: ListItemRenderer<T>;
|
||||
readonly install: (
|
||||
item: T,
|
||||
version?: Installable.Version
|
||||
) => Promise<void>;
|
||||
readonly install: (item: T, version?: Installable.Version) => Promise<void>;
|
||||
readonly uninstall: (item: T) => Promise<void>;
|
||||
readonly resolveContainer: (element: HTMLElement) => void;
|
||||
}
|
||||
|
@@ -30,9 +30,7 @@ export class FilterableListContainer<
|
||||
componentDidMount(): void {
|
||||
this.search = debounce(this.search, 500);
|
||||
this.handleFilterTextChange('');
|
||||
this.props.filterTextChangeEvent(
|
||||
this.handleFilterTextChange.bind(this)
|
||||
);
|
||||
this.props.filterTextChangeEvent(this.handleFilterTextChange.bind(this));
|
||||
}
|
||||
|
||||
componentDidUpdate(): void {
|
||||
|
@@ -66,9 +66,7 @@ export class ListItemRenderer<T extends ArduinoComponent> {
|
||||
</button>
|
||||
);
|
||||
|
||||
const onSelectChange = (
|
||||
event: React.ChangeEvent<HTMLSelectElement>
|
||||
) => {
|
||||
const onSelectChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
const version = event.target.value;
|
||||
if (version) {
|
||||
onVersionChange(version);
|
||||
@@ -89,9 +87,7 @@ export class ListItemRenderer<T extends ArduinoComponent> {
|
||||
onChange={onSelectChange}
|
||||
>
|
||||
{item.availableVersions
|
||||
.filter(
|
||||
(version) => version !== item.installedVersion
|
||||
) // Filter the version that is currently installed.
|
||||
.filter((version) => version !== item.installedVersion) // Filter the version that is currently installed.
|
||||
.map((version) => (
|
||||
<option value={version} key={version}>
|
||||
{version}
|
||||
|
@@ -63,15 +63,9 @@ export abstract class ListWidget<
|
||||
protected init(): void {
|
||||
this.update();
|
||||
this.toDispose.pushAll([
|
||||
this.notificationCenter.onIndexUpdated(() =>
|
||||
this.refresh(undefined)
|
||||
),
|
||||
this.notificationCenter.onDaemonStarted(() =>
|
||||
this.refresh(undefined)
|
||||
),
|
||||
this.notificationCenter.onDaemonStopped(() =>
|
||||
this.refresh(undefined)
|
||||
),
|
||||
this.notificationCenter.onIndexUpdated(() => this.refresh(undefined)),
|
||||
this.notificationCenter.onDaemonStarted(() => this.refresh(undefined)),
|
||||
this.notificationCenter.onDaemonStopped(() => this.refresh(undefined)),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
import { Command } from '@theia/core/lib/common/command';
|
||||
|
||||
export namespace SketchbookCommands {
|
||||
|
||||
export const OPEN_NEW_WINDOW: Command = {
|
||||
id: 'arduino-sketchbook--open-sketch-new-window',
|
||||
label: 'Open Sketch in New Window',
|
||||
@@ -15,7 +14,7 @@ export namespace SketchbookCommands {
|
||||
export const OPEN_SKETCHBOOK_CONTEXT_MENU: Command = {
|
||||
id: 'arduino-sketchbook--open-sketch-context-menu',
|
||||
label: 'Contextual menu',
|
||||
iconClass: 'sketchbook-tree__opts'
|
||||
iconClass: 'sketchbook-tree__opts',
|
||||
};
|
||||
|
||||
export const SKETCHBOOK_HIDE_FILES: Command = {
|
||||
@@ -27,7 +26,4 @@ export namespace SketchbookCommands {
|
||||
id: 'arduino-sketchbook--show-files',
|
||||
label: 'Contextual menu',
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@@ -1,10 +1,19 @@
|
||||
import { interfaces, Container } from 'inversify';
|
||||
import { createTreeContainer, Tree, TreeImpl, TreeModel, TreeModelImpl, TreeWidget } from '@theia/core/lib/browser/tree';
|
||||
import {
|
||||
createTreeContainer,
|
||||
Tree,
|
||||
TreeImpl,
|
||||
TreeModel,
|
||||
TreeModelImpl,
|
||||
TreeWidget,
|
||||
} from '@theia/core/lib/browser/tree';
|
||||
import { SketchbookTree } from './sketchbook-tree';
|
||||
import { SketchbookTreeModel } from './sketchbook-tree-model';
|
||||
import { SketchbookTreeWidget } from './sketchbook-tree-widget';
|
||||
|
||||
export function createSketchbookTreeContainer(parent: interfaces.Container): Container {
|
||||
export function createSketchbookTreeContainer(
|
||||
parent: interfaces.Container
|
||||
): Container {
|
||||
const child = createTreeContainer(parent);
|
||||
|
||||
child.unbind(TreeImpl);
|
||||
@@ -21,6 +30,8 @@ export function createSketchbookTreeContainer(parent: interfaces.Container): Con
|
||||
return child;
|
||||
}
|
||||
|
||||
export function createSketchbookTreeWidget(parent: interfaces.Container): SketchbookTreeWidget {
|
||||
export function createSketchbookTreeWidget(
|
||||
parent: interfaces.Container
|
||||
): SketchbookTreeWidget {
|
||||
return createSketchbookTreeContainer(parent).get(SketchbookTreeWidget);
|
||||
}
|
||||
|
@@ -2,7 +2,12 @@ import * as React from 'react';
|
||||
import { inject, injectable, postConstruct } from 'inversify';
|
||||
import { TreeNode } from '@theia/core/lib/browser/tree/tree';
|
||||
import { CommandRegistry } from '@theia/core/lib/common/command';
|
||||
import { NodeProps, TreeProps, TREE_NODE_SEGMENT_CLASS, TREE_NODE_TAIL_CLASS } from '@theia/core/lib/browser/tree/tree-widget';
|
||||
import {
|
||||
NodeProps,
|
||||
TreeProps,
|
||||
TREE_NODE_SEGMENT_CLASS,
|
||||
TREE_NODE_TAIL_CLASS,
|
||||
} from '@theia/core/lib/browser/tree/tree-widget';
|
||||
import { EditorManager } from '@theia/editor/lib/browser/editor-manager';
|
||||
import { FileTreeWidget } from '@theia/filesystem/lib/browser';
|
||||
import { ContextMenuRenderer } from '@theia/core/lib/browser/context-menu-renderer';
|
||||
@@ -15,7 +20,6 @@ import { Sketch } from '../../contributions/contribution';
|
||||
|
||||
@injectable()
|
||||
export class SketchbookTreeWidget extends FileTreeWidget {
|
||||
|
||||
@inject(CommandRegistry)
|
||||
protected readonly commandRegistry: CommandRegistry;
|
||||
|
||||
@@ -30,7 +34,8 @@ export class SketchbookTreeWidget extends FileTreeWidget {
|
||||
constructor(
|
||||
@inject(TreeProps) readonly props: TreeProps,
|
||||
@inject(SketchbookTreeModel) readonly model: SketchbookTreeModel,
|
||||
@inject(ContextMenuRenderer) readonly contextMenuRenderer: ContextMenuRenderer,
|
||||
@inject(ContextMenuRenderer)
|
||||
readonly contextMenuRenderer: ContextMenuRenderer,
|
||||
@inject(EditorManager) readonly editorManager: EditorManager
|
||||
) {
|
||||
super(props, model, contextMenuRenderer);
|
||||
@@ -43,15 +48,17 @@ export class SketchbookTreeWidget extends FileTreeWidget {
|
||||
@postConstruct()
|
||||
protected async init(): Promise<void> {
|
||||
super.init();
|
||||
this.toDispose.push(this.arduinoPreferences.onPreferenceChanged(({ preferenceName }) => {
|
||||
this.toDispose.push(
|
||||
this.arduinoPreferences.onPreferenceChanged(({ preferenceName }) => {
|
||||
if (preferenceName === 'arduino.sketchbook.showAllFiles') {
|
||||
this.updateModel();
|
||||
}
|
||||
}));
|
||||
})
|
||||
);
|
||||
this.updateModel();
|
||||
// cache the current open sketch uri
|
||||
const currentSketch = await this.sketchServiceClient.currentSketch();
|
||||
this.currentSketchUri = currentSketch && currentSketch.uri || '';
|
||||
this.currentSketchUri = (currentSketch && currentSketch.uri) || '';
|
||||
}
|
||||
|
||||
async updateModel(): Promise<void> {
|
||||
@@ -61,7 +68,10 @@ export class SketchbookTreeWidget extends FileTreeWidget {
|
||||
protected createNodeClassNames(node: TreeNode, props: NodeProps): string[] {
|
||||
const classNames = super.createNodeClassNames(node, props);
|
||||
|
||||
if (SketchbookTree.SketchDirNode.is(node) && this.currentSketchUri === node?.uri.toString()) {
|
||||
if (
|
||||
SketchbookTree.SketchDirNode.is(node) &&
|
||||
this.currentSketchUri === node?.uri.toString()
|
||||
) {
|
||||
classNames.push('active-sketch');
|
||||
}
|
||||
|
||||
@@ -70,7 +80,7 @@ export class SketchbookTreeWidget extends FileTreeWidget {
|
||||
|
||||
protected renderIcon(node: TreeNode, props: NodeProps): React.ReactNode {
|
||||
if (SketchbookTree.SketchDirNode.is(node) || Sketch.isSketchFile(node.id)) {
|
||||
return <div className='sketch-folder-icon file-icon'></div>;
|
||||
return <div className="sketch-folder-icon file-icon"></div>;
|
||||
}
|
||||
const icon = this.toNodeIcon(node);
|
||||
if (icon) {
|
||||
@@ -79,11 +89,16 @@ export class SketchbookTreeWidget extends FileTreeWidget {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
protected renderTailDecorations(node: TreeNode, props: NodeProps): React.ReactNode {
|
||||
return <React.Fragment>
|
||||
protected renderTailDecorations(
|
||||
node: TreeNode,
|
||||
props: NodeProps
|
||||
): React.ReactNode {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{super.renderTailDecorations(node, props)}
|
||||
{this.renderInlineCommands(node, props)}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
protected hoveredNodeId: string | undefined;
|
||||
@@ -92,44 +107,76 @@ export class SketchbookTreeWidget extends FileTreeWidget {
|
||||
this.update();
|
||||
}
|
||||
|
||||
protected createNodeAttributes(node: TreeNode, props: NodeProps): React.Attributes & React.HTMLAttributes<HTMLElement> {
|
||||
protected createNodeAttributes(
|
||||
node: TreeNode,
|
||||
props: NodeProps
|
||||
): React.Attributes & React.HTMLAttributes<HTMLElement> {
|
||||
return {
|
||||
...super.createNodeAttributes(node, props),
|
||||
draggable: false,
|
||||
onMouseOver: () => this.setHoverNodeId(node.id),
|
||||
onMouseOut: () => this.setHoverNodeId(undefined)
|
||||
onMouseOut: () => this.setHoverNodeId(undefined),
|
||||
};
|
||||
}
|
||||
|
||||
protected renderInlineCommands(node: TreeNode, props: NodeProps): React.ReactNode {
|
||||
if (SketchbookTree.SketchDirNode.is(node) && (node.commands && node.id === this.hoveredNodeId || this.currentSketchUri === node?.uri.toString())) {
|
||||
return Array.from(new Set(node.commands)).map(command => this.renderInlineCommand(command.id, node));
|
||||
protected renderInlineCommands(
|
||||
node: TreeNode,
|
||||
props: NodeProps
|
||||
): React.ReactNode {
|
||||
if (
|
||||
SketchbookTree.SketchDirNode.is(node) &&
|
||||
((node.commands && node.id === this.hoveredNodeId) ||
|
||||
this.currentSketchUri === node?.uri.toString())
|
||||
) {
|
||||
return Array.from(new Set(node.commands)).map((command) =>
|
||||
this.renderInlineCommand(command.id, node)
|
||||
);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
protected renderInlineCommand(commandId: string, node: SketchbookTree.SketchDirNode): React.ReactNode {
|
||||
protected renderInlineCommand(
|
||||
commandId: string,
|
||||
node: SketchbookTree.SketchDirNode
|
||||
): React.ReactNode {
|
||||
const command = this.commandRegistry.getCommand(commandId);
|
||||
const icon = command?.iconClass;
|
||||
const args = { model: this.model, node: node };
|
||||
if (command && icon && this.commandRegistry.isEnabled(commandId, args) && this.commandRegistry.isVisible(commandId, args)) {
|
||||
const className = [TREE_NODE_SEGMENT_CLASS, TREE_NODE_TAIL_CLASS, icon, 'theia-tree-view-inline-action'].join(' ');
|
||||
return <div
|
||||
if (
|
||||
command &&
|
||||
icon &&
|
||||
this.commandRegistry.isEnabled(commandId, args) &&
|
||||
this.commandRegistry.isVisible(commandId, args)
|
||||
) {
|
||||
const className = [
|
||||
TREE_NODE_SEGMENT_CLASS,
|
||||
TREE_NODE_TAIL_CLASS,
|
||||
icon,
|
||||
'theia-tree-view-inline-action',
|
||||
].join(' ');
|
||||
return (
|
||||
<div
|
||||
key={`${commandId}--${node.id}`}
|
||||
className={className}
|
||||
title={command?.label || command.id}
|
||||
onClick={event => {
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.commandRegistry.executeCommand(commandId, Object.assign(args, { event: event.nativeEvent }));
|
||||
this.commandRegistry.executeCommand(
|
||||
commandId,
|
||||
Object.assign(args, { event: event.nativeEvent })
|
||||
);
|
||||
}}
|
||||
/>;
|
||||
/>
|
||||
);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
protected handleClickEvent(node: TreeNode | undefined, event: React.MouseEvent<HTMLElement>): void {
|
||||
|
||||
protected handleClickEvent(
|
||||
node: TreeNode | undefined,
|
||||
event: React.MouseEvent<HTMLElement>
|
||||
): void {
|
||||
if (node) {
|
||||
if (!!this.props.multiSelect) {
|
||||
const shiftMask = this.hasShiftMask(event);
|
||||
@@ -150,11 +197,9 @@ export class SketchbookTreeWidget extends FileTreeWidget {
|
||||
}
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected doToggle(event: React.MouseEvent<HTMLElement>): void {
|
||||
|
||||
const nodeId = event.currentTarget.getAttribute('data-node-id');
|
||||
if (nodeId) {
|
||||
const node = this.model.getNode(nodeId);
|
||||
@@ -164,5 +209,4 @@ export class SketchbookTreeWidget extends FileTreeWidget {
|
||||
}
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -2,14 +2,17 @@ import { inject, injectable } from 'inversify';
|
||||
import { LabelProvider } from '@theia/core/lib/browser/label-provider';
|
||||
import { Command } from '@theia/core/lib/common/command';
|
||||
import { TreeNode, CompositeTreeNode } from '@theia/core/lib/browser/tree';
|
||||
import { DirNode, FileStatNode, FileTree } from '@theia/filesystem/lib/browser/file-tree';
|
||||
import {
|
||||
DirNode,
|
||||
FileStatNode,
|
||||
FileTree,
|
||||
} from '@theia/filesystem/lib/browser/file-tree';
|
||||
import { SketchesService } from '../../../common/protocol';
|
||||
import { FileStat } from '@theia/filesystem/lib/common/files';
|
||||
import { SketchbookCommands } from './sketchbook-commands';
|
||||
|
||||
@injectable()
|
||||
export class SketchbookTree extends FileTree {
|
||||
|
||||
@inject(LabelProvider)
|
||||
protected readonly labelProvider: LabelProvider;
|
||||
|
||||
@@ -17,7 +20,6 @@ export class SketchbookTree extends FileTree {
|
||||
protected readonly sketchesService: SketchesService;
|
||||
|
||||
async resolveChildren(parent: CompositeTreeNode): Promise<TreeNode[]> {
|
||||
|
||||
if (!FileStatNode.is(parent)) {
|
||||
return super.resolveChildren(parent);
|
||||
}
|
||||
@@ -28,15 +30,28 @@ export class SketchbookTree extends FileTree {
|
||||
if (!SketchbookTree.RootNode.is(root)) {
|
||||
return [];
|
||||
}
|
||||
const children = (await Promise.all((await super.resolveChildren(parent)).map(node => this.maybeDecorateNode(node, root.showAllFiles)))).filter(node => {
|
||||
const children = (
|
||||
await Promise.all(
|
||||
(
|
||||
await super.resolveChildren(parent)
|
||||
).map((node) => this.maybeDecorateNode(node, root.showAllFiles))
|
||||
)
|
||||
).filter((node) => {
|
||||
// filter out hidden nodes
|
||||
if (DirNode.is(node) || FileStatNode.is(node)) {
|
||||
return node.fileStat.name.indexOf('.') !== 0
|
||||
return node.fileStat.name.indexOf('.') !== 0;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if (SketchbookTree.RootNode.is(parent)) {
|
||||
return children.filter(DirNode.is).filter(node => ['libraries', 'hardware'].indexOf(this.labelProvider.getName(node)) === -1);
|
||||
return children
|
||||
.filter(DirNode.is)
|
||||
.filter(
|
||||
(node) =>
|
||||
['libraries', 'hardware'].indexOf(
|
||||
this.labelProvider.getName(node)
|
||||
) === -1
|
||||
);
|
||||
}
|
||||
if (SketchbookTree.SketchDirNode.is(parent)) {
|
||||
return children.filter(FileStatNode.is);
|
||||
@@ -44,11 +59,19 @@ export class SketchbookTree extends FileTree {
|
||||
return children;
|
||||
}
|
||||
|
||||
protected async maybeDecorateNode(node: TreeNode, showAllFiles: boolean): Promise<TreeNode> {
|
||||
protected async maybeDecorateNode(
|
||||
node: TreeNode,
|
||||
showAllFiles: boolean
|
||||
): Promise<TreeNode> {
|
||||
if (DirNode.is(node)) {
|
||||
const sketch = await this.sketchesService.maybeLoadSketch(node.uri.toString());
|
||||
const sketch = await this.sketchesService.maybeLoadSketch(
|
||||
node.uri.toString()
|
||||
);
|
||||
if (sketch) {
|
||||
Object.assign(node, { type: 'sketch', commands: [SketchbookCommands.OPEN_SKETCHBOOK_CONTEXT_MENU] });
|
||||
Object.assign(node, {
|
||||
type: 'sketch',
|
||||
commands: [SketchbookCommands.OPEN_SKETCHBOOK_CONTEXT_MENU],
|
||||
});
|
||||
if (!showAllFiles) {
|
||||
delete (node as any).expanded;
|
||||
}
|
||||
@@ -57,24 +80,26 @@ export class SketchbookTree extends FileTree {
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export namespace SketchbookTree {
|
||||
|
||||
export interface RootNode extends DirNode {
|
||||
readonly showAllFiles: boolean;
|
||||
}
|
||||
export namespace RootNode {
|
||||
|
||||
export function is(node: TreeNode & Partial<RootNode>): node is RootNode {
|
||||
return typeof node.showAllFiles === 'boolean';
|
||||
}
|
||||
|
||||
export function create(fileStat: FileStat, showAllFiles: boolean): RootNode {
|
||||
return Object.assign(DirNode.createRoot(fileStat), { showAllFiles, visible: false });
|
||||
export function create(
|
||||
fileStat: FileStat,
|
||||
showAllFiles: boolean
|
||||
): RootNode {
|
||||
return Object.assign(DirNode.createRoot(fileStat), {
|
||||
showAllFiles,
|
||||
visible: false,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export interface SketchDirNode extends DirNode {
|
||||
@@ -82,11 +107,10 @@ export namespace SketchbookTree {
|
||||
readonly commands?: Command[];
|
||||
}
|
||||
export namespace SketchDirNode {
|
||||
|
||||
export function is(node: TreeNode & Partial<SketchDirNode> | undefined): node is SketchDirNode {
|
||||
export function is(
|
||||
node: (TreeNode & Partial<SketchDirNode>) | undefined
|
||||
): node is SketchDirNode {
|
||||
return !!node && node.type === 'sketch' && DirNode.is(node);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -12,19 +12,30 @@ import { PlaceholderMenuNode } from '../../menu/arduino-menus';
|
||||
import { SketchbookTree } from './sketchbook-tree';
|
||||
import { SketchbookCommands } from './sketchbook-commands';
|
||||
import { WorkspaceService } from '../../theia/workspace/workspace-service';
|
||||
import { ContextMenuRenderer, RenderContextMenuOptions } from '@theia/core/lib/browser';
|
||||
import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable';
|
||||
import {
|
||||
ContextMenuRenderer,
|
||||
RenderContextMenuOptions,
|
||||
} from '@theia/core/lib/browser';
|
||||
import {
|
||||
Disposable,
|
||||
DisposableCollection,
|
||||
} from '@theia/core/lib/common/disposable';
|
||||
import { SketchesServiceClientImpl } from '../../../common/protocol/sketches-service-client-impl';
|
||||
import { FileService } from '@theia/filesystem/lib/browser/file-service';
|
||||
|
||||
export const SKETCHBOOK__CONTEXT = ['arduino-sketchbook--context'];
|
||||
|
||||
// `Open Folder`, `Open in New Window`
|
||||
export const SKETCHBOOK__CONTEXT__MAIN_GROUP = [...SKETCHBOOK__CONTEXT, '0_main'];
|
||||
export const SKETCHBOOK__CONTEXT__MAIN_GROUP = [
|
||||
...SKETCHBOOK__CONTEXT,
|
||||
'0_main',
|
||||
];
|
||||
|
||||
@injectable()
|
||||
export class SketchbookWidgetContribution extends AbstractViewContribution<SketchbookWidget> implements FrontendApplicationContribution {
|
||||
|
||||
export class SketchbookWidgetContribution
|
||||
extends AbstractViewContribution<SketchbookWidget>
|
||||
implements FrontendApplicationContribution
|
||||
{
|
||||
@inject(ArduinoPreferences)
|
||||
protected readonly arduinoPreferences: ArduinoPreferences;
|
||||
|
||||
@@ -57,10 +68,10 @@ export class SketchbookWidgetContribution extends AbstractViewContribution<Sketc
|
||||
widgetName: 'Sketchbook',
|
||||
defaultWidgetOptions: {
|
||||
area: 'left',
|
||||
rank: 1
|
||||
rank: 1,
|
||||
},
|
||||
toggleCommandId: 'arduino-sketchbook-widget:toggle',
|
||||
toggleKeybinding: 'CtrlCmd+Shift+B'
|
||||
toggleKeybinding: 'CtrlCmd+Shift+B',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -80,26 +91,33 @@ export class SketchbookWidgetContribution extends AbstractViewContribution<Sketc
|
||||
super.registerCommands(registry);
|
||||
|
||||
registry.registerCommand(SketchbookCommands.OPEN_NEW_WINDOW, {
|
||||
execute: async arg => {
|
||||
const underlying = await this.fileService.toUnderlyingResource(arg.node.uri);
|
||||
return this.workspaceService.open(underlying)
|
||||
execute: async (arg) => {
|
||||
const underlying = await this.fileService.toUnderlyingResource(
|
||||
arg.node.uri
|
||||
);
|
||||
return this.workspaceService.open(underlying);
|
||||
},
|
||||
isEnabled: arg => !!arg && 'node' in arg && SketchbookTree.SketchDirNode.is(arg.node),
|
||||
isVisible: arg => !!arg && 'node' in arg && SketchbookTree.SketchDirNode.is(arg.node)
|
||||
isEnabled: (arg) =>
|
||||
!!arg && 'node' in arg && SketchbookTree.SketchDirNode.is(arg.node),
|
||||
isVisible: (arg) =>
|
||||
!!arg && 'node' in arg && SketchbookTree.SketchDirNode.is(arg.node),
|
||||
});
|
||||
|
||||
registry.registerCommand(SketchbookCommands.REVEAL_IN_FINDER, {
|
||||
execute: (arg) => {
|
||||
shell.openPath(arg.node.id);
|
||||
},
|
||||
isEnabled: (arg) => !!arg && 'node' in arg && SketchbookTree.SketchDirNode.is(arg.node),
|
||||
isVisible: (arg) => !!arg && 'node' in arg && SketchbookTree.SketchDirNode.is(arg.node),
|
||||
isEnabled: (arg) =>
|
||||
!!arg && 'node' in arg && SketchbookTree.SketchDirNode.is(arg.node),
|
||||
isVisible: (arg) =>
|
||||
!!arg && 'node' in arg && SketchbookTree.SketchDirNode.is(arg.node),
|
||||
});
|
||||
|
||||
|
||||
registry.registerCommand(SketchbookCommands.OPEN_SKETCHBOOK_CONTEXT_MENU, {
|
||||
isEnabled: (arg) => !!arg && 'node' in arg && SketchbookTree.SketchDirNode.is(arg.node),
|
||||
isVisible: (arg) => !!arg && 'node' in arg && SketchbookTree.SketchDirNode.is(arg.node),
|
||||
isEnabled: (arg) =>
|
||||
!!arg && 'node' in arg && SketchbookTree.SketchDirNode.is(arg.node),
|
||||
isVisible: (arg) =>
|
||||
!!arg && 'node' in arg && SketchbookTree.SketchDirNode.is(arg.node),
|
||||
execute: async (arg) => {
|
||||
// cleanup previous context menu entries
|
||||
this.toDisposeBeforeNewContextMenu.dispose();
|
||||
@@ -112,28 +130,46 @@ export class SketchbookWidgetContribution extends AbstractViewContribution<Sketc
|
||||
// otherwise make the command clickable
|
||||
const currentSketch = await this.sketchServiceClient.currentSketch();
|
||||
if (currentSketch && currentSketch.uri === arg.node.uri.toString()) {
|
||||
const placeholder = new PlaceholderMenuNode(SKETCHBOOK__CONTEXT__MAIN_GROUP, SketchbookCommands.OPEN_NEW_WINDOW.label!);
|
||||
this.menuRegistry.registerMenuNode(SKETCHBOOK__CONTEXT__MAIN_GROUP, placeholder);
|
||||
this.toDisposeBeforeNewContextMenu.push(Disposable.create(() => this.menuRegistry.unregisterMenuNode(placeholder.id)));
|
||||
const placeholder = new PlaceholderMenuNode(
|
||||
SKETCHBOOK__CONTEXT__MAIN_GROUP,
|
||||
SketchbookCommands.OPEN_NEW_WINDOW.label!
|
||||
);
|
||||
this.menuRegistry.registerMenuNode(
|
||||
SKETCHBOOK__CONTEXT__MAIN_GROUP,
|
||||
placeholder
|
||||
);
|
||||
this.toDisposeBeforeNewContextMenu.push(
|
||||
Disposable.create(() =>
|
||||
this.menuRegistry.unregisterMenuNode(placeholder.id)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
this.menuRegistry.registerMenuAction(SKETCHBOOK__CONTEXT__MAIN_GROUP, {
|
||||
this.menuRegistry.registerMenuAction(
|
||||
SKETCHBOOK__CONTEXT__MAIN_GROUP,
|
||||
{
|
||||
commandId: SketchbookCommands.OPEN_NEW_WINDOW.id,
|
||||
label: SketchbookCommands.OPEN_NEW_WINDOW.label,
|
||||
});
|
||||
this.toDisposeBeforeNewContextMenu.push(Disposable.create(() => this.menuRegistry.unregisterMenuAction(SketchbookCommands.OPEN_NEW_WINDOW)));
|
||||
}
|
||||
|
||||
);
|
||||
this.toDisposeBeforeNewContextMenu.push(
|
||||
Disposable.create(() =>
|
||||
this.menuRegistry.unregisterMenuAction(
|
||||
SketchbookCommands.OPEN_NEW_WINDOW
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const options: RenderContextMenuOptions = {
|
||||
menuPath: SKETCHBOOK__CONTEXT,
|
||||
anchor: {
|
||||
x: container.getBoundingClientRect().left,
|
||||
y: container.getBoundingClientRect().top + container.offsetHeight
|
||||
y: container.getBoundingClientRect().top + container.offsetHeight,
|
||||
},
|
||||
args: arg
|
||||
}
|
||||
args: arg,
|
||||
};
|
||||
this.contextMenuRenderer.render(options);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -148,9 +184,7 @@ export class SketchbookWidgetContribution extends AbstractViewContribution<Sketc
|
||||
registry.registerMenuAction(SKETCHBOOK__CONTEXT__MAIN_GROUP, {
|
||||
commandId: SketchbookCommands.REVEAL_IN_FINDER.id,
|
||||
label: SketchbookCommands.REVEAL_IN_FINDER.label,
|
||||
order: '0'
|
||||
order: '0',
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -9,7 +9,6 @@ import { SketchbookTreeWidget } from './sketchbook-tree-widget';
|
||||
|
||||
@injectable()
|
||||
export class SketchbookWidget extends BaseWidget {
|
||||
|
||||
@inject(SketchbookTreeWidget)
|
||||
protected readonly localSketchbookTreeWidget: SketchbookTreeWidget;
|
||||
|
||||
@@ -34,7 +33,9 @@ export class SketchbookWidget extends BaseWidget {
|
||||
protected onAfterAttach(message: Message): void {
|
||||
super.onAfterAttach(message);
|
||||
Widget.attach(this.sketchbookTreesContainer, this.node);
|
||||
this.toDisposeOnDetach.push(Disposable.create(() => Widget.detach(this.sketchbookTreesContainer)));
|
||||
this.toDisposeOnDetach.push(
|
||||
Disposable.create(() => Widget.detach(this.sketchbookTreesContainer))
|
||||
);
|
||||
}
|
||||
|
||||
protected onActivateRequest(message: Message): void {
|
||||
@@ -50,7 +51,10 @@ export class SketchbookWidget extends BaseWidget {
|
||||
|
||||
protected onResize(message: Widget.ResizeMessage): void {
|
||||
super.onResize(message);
|
||||
MessageLoop.sendMessage(this.sketchbookTreesContainer, Widget.ResizeMessage.UnknownSize);
|
||||
MessageLoop.sendMessage(
|
||||
this.sketchbookTreesContainer,
|
||||
Widget.ResizeMessage.UnknownSize
|
||||
);
|
||||
for (const widget of toArray(this.sketchbookTreesContainer.widgets())) {
|
||||
MessageLoop.sendMessage(widget, Widget.ResizeMessage.UnknownSize);
|
||||
}
|
||||
@@ -62,16 +66,17 @@ export class SketchbookWidget extends BaseWidget {
|
||||
}
|
||||
|
||||
protected createTreesContainer(): DockPanel {
|
||||
const panel = new NoopDragOverDockPanel({ spacing: 0, mode: 'single-document' });
|
||||
const panel = new NoopDragOverDockPanel({
|
||||
spacing: 0,
|
||||
mode: 'single-document',
|
||||
});
|
||||
panel.addClass('sketchbook-trees-container');
|
||||
panel.node.tabIndex = -1;
|
||||
return panel;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class NoopDragOverDockPanel extends DockPanel {
|
||||
|
||||
constructor(options?: DockPanel.IOptions) {
|
||||
super(options);
|
||||
NoopDragOverDockPanel.prototype['_evtDragOver'] = (event: IDragEvent) => {
|
||||
@@ -80,6 +85,4 @@ export class NoopDragOverDockPanel extends DockPanel {
|
||||
event.dropAction = 'none';
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@@ -80,10 +80,9 @@ export namespace AttachedBoardsChangeEvent {
|
||||
for (const port of detached.ports) {
|
||||
if (!visitedDetachedPorts.find((p) => Port.sameAs(port, p))) {
|
||||
rows.push(
|
||||
` - Port is no longer available on ${Port.toString(
|
||||
port,
|
||||
{ useLabel: true }
|
||||
)}`
|
||||
` - Port is no longer available on ${Port.toString(port, {
|
||||
useLabel: true,
|
||||
})}`
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -108,8 +107,7 @@ export namespace AttachedBoardsChangeEvent {
|
||||
sameAs: (left: T, right: T) => boolean
|
||||
) => {
|
||||
return lefts.filter(
|
||||
(left) =>
|
||||
rights.findIndex((right) => sameAs(left, right)) === -1
|
||||
(left) => rights.findIndex((right) => sameAs(left, right)) === -1
|
||||
);
|
||||
};
|
||||
const { boards: newBoards } = event.newState;
|
||||
@@ -118,8 +116,7 @@ export namespace AttachedBoardsChangeEvent {
|
||||
const { ports: oldPorts } = event.oldState;
|
||||
const boardSameAs = (left: Board, right: Board) =>
|
||||
Board.sameAs(left, right);
|
||||
const portSameAs = (left: Port, right: Port) =>
|
||||
Port.sameAs(left, right);
|
||||
const portSameAs = (left: Port, right: Port) => Port.sameAs(left, right);
|
||||
return {
|
||||
detached: {
|
||||
boards: diff(oldBoards, newBoards, boardSameAs),
|
||||
@@ -149,12 +146,8 @@ export interface BoardsService
|
||||
*/
|
||||
getAvailablePorts(): Promise<Port[]>;
|
||||
getState(): Promise<AvailablePorts>;
|
||||
getBoardDetails(options: {
|
||||
fqbn: string;
|
||||
}): Promise<BoardDetails | undefined>;
|
||||
getBoardPackage(options: {
|
||||
id: string;
|
||||
}): Promise<BoardsPackage | undefined>;
|
||||
getBoardDetails(options: { fqbn: string }): Promise<BoardDetails | undefined>;
|
||||
getBoardPackage(options: { id: string }): Promise<BoardsPackage | undefined>;
|
||||
getContainerBoardPackage(options: {
|
||||
fqbn: string;
|
||||
}): Promise<BoardsPackage | undefined>;
|
||||
@@ -502,8 +495,7 @@ export namespace Board {
|
||||
return left.fqbn === other.fqbn;
|
||||
}
|
||||
return (
|
||||
left.name.replace('/Genuino', '') ===
|
||||
other.name.replace('/Genuino', '')
|
||||
left.name.replace('/Genuino', '') === other.name.replace('/Genuino', '')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -553,15 +545,10 @@ export namespace Board {
|
||||
if (!!selectedBoard) {
|
||||
if (Board.equals(board, selectedBoard)) {
|
||||
if ('packageName' in selectedBoard) {
|
||||
return (
|
||||
board.packageName ===
|
||||
(selectedBoard as any).packageName
|
||||
);
|
||||
return board.packageName === (selectedBoard as any).packageName;
|
||||
}
|
||||
if ('packageId' in selectedBoard) {
|
||||
return (
|
||||
board.packageId === (selectedBoard as any).packageId
|
||||
);
|
||||
return board.packageId === (selectedBoard as any).packageId;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@@ -36,9 +36,7 @@ export namespace Network {
|
||||
}
|
||||
try {
|
||||
// Patter: PROTOCOL://USER:PASS@HOSTNAME:PORT/
|
||||
const { protocol, hostname, password, username, port } = new URL(
|
||||
raw
|
||||
);
|
||||
const { protocol, hostname, password, username, port } = new URL(raw);
|
||||
return {
|
||||
protocol,
|
||||
hostname,
|
||||
|
@@ -94,10 +94,7 @@ export namespace LibraryPackage {
|
||||
);
|
||||
}
|
||||
|
||||
export function equals(
|
||||
left: LibraryPackage,
|
||||
right: LibraryPackage
|
||||
): boolean {
|
||||
export function equals(left: LibraryPackage, right: LibraryPackage): boolean {
|
||||
return left.name === right.name && left.author === right.author;
|
||||
}
|
||||
|
||||
|
@@ -62,44 +62,26 @@ export class SketchesServiceClientImpl
|
||||
if (Sketch.isSketchFile(resource)) {
|
||||
if (type === FileChangeType.ADDED) {
|
||||
try {
|
||||
const toAdd =
|
||||
await this.sketchService.loadSketch(
|
||||
const toAdd = await this.sketchService.loadSketch(
|
||||
resource.parent.toString()
|
||||
);
|
||||
if (
|
||||
!this.sketches.has(
|
||||
toAdd.uri
|
||||
)
|
||||
) {
|
||||
if (!this.sketches.has(toAdd.uri)) {
|
||||
console.log(
|
||||
`New sketch '${toAdd.name}' was crated in sketchbook '${sketchDirUri}'.`
|
||||
);
|
||||
this.sketches.set(
|
||||
toAdd.uri,
|
||||
toAdd
|
||||
);
|
||||
this.fireSoon(
|
||||
toAdd,
|
||||
'created'
|
||||
);
|
||||
this.sketches.set(toAdd.uri, toAdd);
|
||||
this.fireSoon(toAdd, 'created');
|
||||
}
|
||||
} catch {}
|
||||
} else if (
|
||||
type === FileChangeType.DELETED
|
||||
) {
|
||||
const uri =
|
||||
resource.parent.toString();
|
||||
const toDelete =
|
||||
this.sketches.get(uri);
|
||||
} else if (type === FileChangeType.DELETED) {
|
||||
const uri = resource.parent.toString();
|
||||
const toDelete = this.sketches.get(uri);
|
||||
if (toDelete) {
|
||||
console.log(
|
||||
`Sketch '${toDelete.name}' was removed from sketchbook '${sketchbookUri}'.`
|
||||
);
|
||||
this.sketches.delete(uri);
|
||||
this.fireSoon(
|
||||
toDelete,
|
||||
'removed'
|
||||
);
|
||||
this.fireSoon(toDelete, 'removed');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -113,18 +113,14 @@ export namespace Sketch {
|
||||
'.md',
|
||||
'.adoc',
|
||||
];
|
||||
export const ALL = Array.from(
|
||||
new Set([...MAIN, ...SOURCE, ...ADDITIONAL])
|
||||
);
|
||||
export const ALL = Array.from(new Set([...MAIN, ...SOURCE, ...ADDITIONAL]));
|
||||
}
|
||||
export function isInSketch(uri: string | URI, sketch: Sketch): boolean {
|
||||
const { mainFileUri, otherSketchFileUris, additionalFileUris } = sketch;
|
||||
return (
|
||||
[
|
||||
mainFileUri,
|
||||
...otherSketchFileUris,
|
||||
...additionalFileUris,
|
||||
].indexOf(uri.toString()) !== -1
|
||||
[mainFileUri, ...otherSketchFileUris, ...additionalFileUris].indexOf(
|
||||
uri.toString()
|
||||
) !== -1
|
||||
);
|
||||
}
|
||||
export function isSketchFile(arg: string | URI): boolean {
|
||||
|
@@ -28,8 +28,7 @@ export class ElectronWindowService extends TheiaElectronWindowService {
|
||||
|
||||
protected shouldUnload(): boolean {
|
||||
const offline =
|
||||
this.connectionStatusService.currentStatus ===
|
||||
ConnectionStatus.OFFLINE;
|
||||
this.connectionStatusService.currentStatus === ConnectionStatus.OFFLINE;
|
||||
const detail = offline
|
||||
? 'Could not save the sketch. Please copy your unsaved work into your favorite text editor, and restart the IDE.'
|
||||
: 'Any unsaved changes will not be saved.';
|
||||
|
@@ -25,9 +25,7 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory {
|
||||
if (isOSX) {
|
||||
template.unshift(this.createOSXMenu());
|
||||
}
|
||||
const menu = remote.Menu.buildFromTemplate(
|
||||
this.escapeAmpersand(template)
|
||||
);
|
||||
const menu = remote.Menu.buildFromTemplate(this.escapeAmpersand(template));
|
||||
this._menu = menu;
|
||||
return menu;
|
||||
}
|
||||
|
@@ -51,12 +51,8 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
|
||||
);
|
||||
const splashHeight = 450;
|
||||
const splashWidth = 600;
|
||||
const splashY = Math.floor(
|
||||
bounds.y + (bounds.height - splashHeight) / 2
|
||||
);
|
||||
const splashX = Math.floor(
|
||||
bounds.x + (bounds.width - splashWidth) / 2
|
||||
);
|
||||
const splashY = Math.floor(bounds.y + (bounds.height - splashHeight) / 2);
|
||||
const splashX = Math.floor(bounds.x + (bounds.width - splashWidth) / 2);
|
||||
const splashScreenOpts: BrowserWindowConstructorOptions = {
|
||||
height: splashHeight,
|
||||
width: splashWidth,
|
||||
@@ -118,8 +114,7 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
|
||||
// We cannot use the `process.cwd()` as the application project path (the location of the `package.json` in other words)
|
||||
// in a bundled electron application because it depends on the way we start it. For instance, on OS X, these are a differences:
|
||||
// https://github.com/eclipse-theia/theia/issues/3297#issuecomment-439172274
|
||||
process.env.THEIA_APP_PROJECT_PATH =
|
||||
this.globals.THEIA_APP_PROJECT_PATH;
|
||||
process.env.THEIA_APP_PROJECT_PATH = this.globals.THEIA_APP_PROJECT_PATH;
|
||||
// Set the electron version for both the dev and the production mode. (https://github.com/eclipse-theia/theia/issues/3254)
|
||||
// Otherwise, the forked backend processes will not know that they're serving the electron frontend.
|
||||
process.env.THEIA_ELECTRON_VERSION = process.versions.electron;
|
||||
|
@@ -12,8 +12,7 @@ export class ElectronMainWindowServiceImpl extends TheiaElectronMainWindowServic
|
||||
if (!external) {
|
||||
const sanitizedUrl = this.sanitize(url);
|
||||
const existing = this.app.windows.find(
|
||||
(window) =>
|
||||
this.sanitize(window.webContents.getURL()) === sanitizedUrl
|
||||
(window) => this.sanitize(window.webContents.getURL()) === sanitizedUrl
|
||||
);
|
||||
if (existing) {
|
||||
existing.focus();
|
||||
|
@@ -113,10 +113,7 @@ export class ArduinoDaemonImpl
|
||||
if (this._execPath) {
|
||||
return this._execPath;
|
||||
}
|
||||
this._execPath = await getExecPath(
|
||||
'arduino-cli',
|
||||
this.onError.bind(this)
|
||||
);
|
||||
this._execPath = await getExecPath('arduino-cli', this.onError.bind(this));
|
||||
return this._execPath;
|
||||
}
|
||||
|
||||
|
@@ -234,14 +234,11 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
new JsonRpcConnectionHandler<NotificationServiceClient>(
|
||||
NotificationServicePath,
|
||||
(client) => {
|
||||
const server =
|
||||
context.container.get<NotificationServiceServer>(
|
||||
const server = context.container.get<NotificationServiceServer>(
|
||||
NotificationServiceServer
|
||||
);
|
||||
server.setClient(client);
|
||||
client.onDidCloseConnection(() =>
|
||||
server.disposeClient(client)
|
||||
);
|
||||
client.onDidCloseConnection(() => server.disposeClient(client));
|
||||
return server;
|
||||
}
|
||||
)
|
||||
@@ -297,14 +294,11 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
new JsonRpcConnectionHandler<AuthenticationServiceClient>(
|
||||
AuthenticationServicePath,
|
||||
(client) => {
|
||||
const server =
|
||||
context.container.get<AuthenticationServiceImpl>(
|
||||
const server = context.container.get<AuthenticationServiceImpl>(
|
||||
AuthenticationServiceImpl
|
||||
);
|
||||
server.setClient(client);
|
||||
client.onDidCloseConnection(() =>
|
||||
server.disposeClient(client)
|
||||
);
|
||||
client.onDidCloseConnection(() => server.disposeClient(client));
|
||||
return server;
|
||||
}
|
||||
)
|
||||
|
@@ -50,9 +50,7 @@ export class ArduinoAuthenticationProvider implements AuthenticationProvider {
|
||||
}
|
||||
|
||||
private get sessions(): Promise<AuthenticationSession[]> {
|
||||
return Promise.resolve(
|
||||
this._tokens.map((token) => IToken2Session(token))
|
||||
);
|
||||
return Promise.resolve(this._tokens.map((token) => IToken2Session(token)));
|
||||
}
|
||||
|
||||
public getSessions(): Promise<AuthenticationSession[]> {
|
||||
@@ -171,10 +169,7 @@ export class ArduinoAuthenticationProvider implements AuthenticationProvider {
|
||||
const { url } = req;
|
||||
if (url && url.startsWith('/callback?code=')) {
|
||||
const code = url.slice('/callback?code='.length);
|
||||
const token = await this.exchangeCodeForToken(
|
||||
code,
|
||||
pkp.verifier
|
||||
);
|
||||
const token = await this.exchangeCodeForToken(code, pkp.verifier);
|
||||
resolve(token2IToken(token));
|
||||
}
|
||||
|
||||
@@ -326,9 +321,7 @@ export class ArduinoAuthenticationProvider implements AuthenticationProvider {
|
||||
setTimeout(
|
||||
async () => {
|
||||
try {
|
||||
const refreshedToken = await this.refreshToken(
|
||||
token
|
||||
);
|
||||
const refreshedToken = await this.refreshToken(token);
|
||||
this.addToken(refreshedToken);
|
||||
} catch (e) {
|
||||
await this.removeSession(token.sessionId);
|
||||
|
@@ -35,9 +35,7 @@ export class AuthenticationServiceImpl
|
||||
)
|
||||
);
|
||||
removed?.forEach(() =>
|
||||
this.clients.forEach((client) =>
|
||||
client.notifySessionDidChange()
|
||||
)
|
||||
this.clients.forEach((client) => client.notifySessionDidChange())
|
||||
);
|
||||
}),
|
||||
Disposable.create(() =>
|
||||
|
@@ -98,8 +98,6 @@ export function generateProofKeyPair() {
|
||||
const seed = btoa(decode(buffer));
|
||||
|
||||
const verifier = urlEncode(seed);
|
||||
const challenge = urlEncode(
|
||||
btoa(decode(sha256().update(verifier).digest()))
|
||||
);
|
||||
const challenge = urlEncode(btoa(decode(sha256().update(verifier).digest())));
|
||||
return { verifier, challenge };
|
||||
}
|
||||
|
@@ -69,18 +69,14 @@ export class BoardDiscovery extends CoreClientAware {
|
||||
}
|
||||
|
||||
if (eventType === 'unknown') {
|
||||
throw new Error(
|
||||
`Unexpected event type: '${resp.getEventType()}'`
|
||||
);
|
||||
throw new Error(`Unexpected event type: '${resp.getEventType()}'`);
|
||||
}
|
||||
|
||||
const oldState = deepClone(this._state);
|
||||
const newState = deepClone(this._state);
|
||||
|
||||
const address = detectedPort.getAddress();
|
||||
const protocol = Port.Protocol.toProtocol(
|
||||
detectedPort.getProtocol()
|
||||
);
|
||||
const protocol = Port.Protocol.toProtocol(detectedPort.getProtocol());
|
||||
// const label = detectedPort.getProtocolLabel();
|
||||
const port = { address, protocol };
|
||||
const boards: Board[] = [];
|
||||
@@ -106,9 +102,7 @@ export class BoardDiscovery extends CoreClientAware {
|
||||
newState[port.address] = [port, boards];
|
||||
} else if (eventType === 'remove') {
|
||||
if (newState[port.address] === undefined) {
|
||||
console.warn(
|
||||
`Port '${port.address}' was not available. Skipping`
|
||||
);
|
||||
console.warn(`Port '${port.address}' was not available. Skipping`);
|
||||
return;
|
||||
}
|
||||
delete newState[port.address];
|
||||
|
@@ -87,10 +87,8 @@ export class BoardsServiceImpl
|
||||
if (err) {
|
||||
// Required cores are not installed manually: https://github.com/arduino/arduino-cli/issues/954
|
||||
if (
|
||||
(err.message.indexOf('missing platform release') !==
|
||||
-1 &&
|
||||
err.message.indexOf('referenced by board') !==
|
||||
-1) ||
|
||||
(err.message.indexOf('missing platform release') !== -1 &&
|
||||
err.message.indexOf('referenced by board') !== -1) ||
|
||||
// Platform is not installed.
|
||||
(err.message.indexOf('platform') !== -1 &&
|
||||
err.message.indexOf('not installed') !== -1)
|
||||
@@ -147,16 +145,13 @@ export class BoardsServiceImpl
|
||||
const listResp =
|
||||
await new Promise<ListProgrammersAvailableForUploadResponse>(
|
||||
(resolve, reject) =>
|
||||
client.listProgrammersAvailableForUpload(
|
||||
listReq,
|
||||
(err, resp) => {
|
||||
client.listProgrammersAvailableForUpload(listReq, (err, resp) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
resolve(resp);
|
||||
}
|
||||
)
|
||||
})
|
||||
);
|
||||
|
||||
const programmers = listResp.getProgrammersList().map(
|
||||
@@ -223,8 +218,7 @@ export class BoardsServiceImpl
|
||||
const req = new BoardSearchRequest();
|
||||
req.setSearchArgs(query || '');
|
||||
req.setInstance(instance);
|
||||
const boards = await new Promise<BoardWithPackage[]>(
|
||||
(resolve, reject) => {
|
||||
const boards = await new Promise<BoardWithPackage[]>((resolve, reject) => {
|
||||
client.boardSearch(req, (error, resp) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
@@ -244,8 +238,7 @@ export class BoardsServiceImpl
|
||||
}
|
||||
resolve(boards);
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
return boards;
|
||||
}
|
||||
|
||||
@@ -268,8 +261,7 @@ export class BoardsServiceImpl
|
||||
req.setSearchArgs(options.query || '');
|
||||
req.setAllVersions(true);
|
||||
req.setInstance(instance);
|
||||
const resp = await new Promise<PlatformSearchResponse>(
|
||||
(resolve, reject) =>
|
||||
const resp = await new Promise<PlatformSearchResponse>((resolve, reject) =>
|
||||
client.platformSearch(req, (err, resp) =>
|
||||
(!!err ? reject : resolve)(!!err ? err : resp)
|
||||
)
|
||||
@@ -298,9 +290,7 @@ export class BoardsServiceImpl
|
||||
installedVersion,
|
||||
boards: platform
|
||||
.getBoardsList()
|
||||
.map(
|
||||
(b) => <Board>{ name: b.getName(), fqbn: b.getFqbn() }
|
||||
),
|
||||
.map((b) => <Board>{ name: b.getName(), fqbn: b.getFqbn() }),
|
||||
moreInfoLink: platform.getWebsite(),
|
||||
};
|
||||
};
|
||||
@@ -323,8 +313,7 @@ export class BoardsServiceImpl
|
||||
// XXX: we cannot rely on `platform.getInstalled()`, it is always an empty string.
|
||||
const leftInstalled = !!installedPlatforms.find(
|
||||
(ip) =>
|
||||
ip.getId() === left.getId() &&
|
||||
ip.getInstalled() === left.getLatest()
|
||||
ip.getId() === left.getId() && ip.getInstalled() === left.getLatest()
|
||||
);
|
||||
const rightInstalled = !!installedPlatforms.find(
|
||||
(ip) =>
|
||||
@@ -352,9 +341,7 @@ export class BoardsServiceImpl
|
||||
const pkg = packages.get(id);
|
||||
if (pkg) {
|
||||
pkg.availableVersions.push(platform.getLatest());
|
||||
pkg.availableVersions
|
||||
.sort(Installable.Version.COMPARATOR)
|
||||
.reverse();
|
||||
pkg.availableVersions.sort(Installable.Version.COMPARATOR).reverse();
|
||||
} else {
|
||||
packages.set(id, toPackage(platform));
|
||||
}
|
||||
|
@@ -12,12 +12,8 @@ export namespace BoardManager {
|
||||
): boolean {
|
||||
const leftOrDefault = left || {};
|
||||
const rightOrDefault = right || {};
|
||||
const leftUrls = Array.from(
|
||||
new Set(leftOrDefault.additional_urls || [])
|
||||
);
|
||||
const rightUrls = Array.from(
|
||||
new Set(rightOrDefault.additional_urls || [])
|
||||
);
|
||||
const leftUrls = Array.from(new Set(leftOrDefault.additional_urls || []));
|
||||
const rightUrls = Array.from(new Set(rightOrDefault.additional_urls || []));
|
||||
if (leftUrls.length !== rightUrls.length) {
|
||||
return false;
|
||||
}
|
||||
@@ -143,9 +139,7 @@ export namespace DefaultCliConfig {
|
||||
config: RecursivePartial<DefaultCliConfig> | undefined
|
||||
): config is DefaultCliConfig {
|
||||
return (
|
||||
!!config &&
|
||||
Directories.is(config.directories) &&
|
||||
Daemon.is(config.daemon)
|
||||
!!config && Directories.is(config.directories) && Daemon.is(config.daemon)
|
||||
);
|
||||
}
|
||||
export function sameAs(
|
||||
|
@@ -163,8 +163,7 @@ export class ConfigServiceImpl
|
||||
|
||||
protected async getFallbackCliConfig(): Promise<DefaultCliConfig> {
|
||||
const cliPath = await this.daemon.getExecPath();
|
||||
const throwawayDirPath = await new Promise<string>(
|
||||
(resolve, reject) => {
|
||||
const throwawayDirPath = await new Promise<string>((resolve, reject) => {
|
||||
track.mkdir({}, (err, dirPath) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
@@ -172,8 +171,7 @@ export class ConfigServiceImpl
|
||||
}
|
||||
resolve(dirPath);
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
await spawnCommand(`"${cliPath}"`, [
|
||||
'config',
|
||||
'init',
|
||||
@@ -219,10 +217,7 @@ export class ConfigServiceImpl
|
||||
const { directories } = cliConfig;
|
||||
const { data, user, downloads } = directories;
|
||||
const additionalUrls: Array<string> = [];
|
||||
if (
|
||||
cliConfig.board_manager &&
|
||||
cliConfig.board_manager.additional_urls
|
||||
) {
|
||||
if (cliConfig.board_manager && cliConfig.board_manager.additional_urls) {
|
||||
additionalUrls.push(
|
||||
...Array.from(new Set(cliConfig.board_manager.additional_urls))
|
||||
);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user