Make tab width 2 spaces (#445)

This commit is contained in:
Francesco Stasi
2021-07-09 10:14:42 +02:00
committed by GitHub
parent 40a73af82b
commit e10f0f1683
205 changed files with 19676 additions and 20141 deletions

View File

@@ -1,13 +1,6 @@
{
"singleQuote": true,
"tabWidth": 4,
"tabWidth": 2,
"useTabs": false,
"overrides": [
{
"files": "*.{json,yml}",
"options": {
"tabWidth": 2
}
}
]
"printWidth": 80
}

View File

@@ -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.',
}
);
}
}

View File

@@ -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(

View File

@@ -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({

View File

@@ -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())
);
}
});

View File

@@ -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>
);

View File

@@ -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;
}

View File

@@ -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)
),
]);
}

View File

@@ -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;
}

View File

@@ -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),
]);
}

View File

@@ -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' });
};
}

View File

@@ -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`;

View File

@@ -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) {

View File

@@ -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);
}
}
}

View File

@@ -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'),
]);

View File

@@ -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;
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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') }

View File

@@ -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');
}

View File

@@ -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);
}
}

View File

@@ -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();
}

View File

@@ -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),
});
}

View File

@@ -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());
}
}
}

View File

@@ -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()
)

View File

@@ -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 {

View File

@@ -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)
)
);
}

View File

@@ -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
),

View File

@@ -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,

View File

@@ -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}`;
}

View File

@@ -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
);
}

View File

@@ -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 {

View File

@@ -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';
}

View File

@@ -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');

View File

@@ -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);
}
}
)
})
);
});
}

View File

@@ -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 });
});

View File

@@ -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}

View File

@@ -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 {

View File

@@ -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', () =>

View File

@@ -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.'

View File

@@ -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);
}
}
}

View File

@@ -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(

View File

@@ -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

View File

@@ -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);
}
}
}

View File

@@ -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 [];
}
}

View File

@@ -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}

View File

@@ -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 (

View File

@@ -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(

View File

@@ -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();

View File

@@ -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;
}
}
);
});
}
}

View File

@@ -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();
}

View File

@@ -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;

View File

@@ -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}`)
);
}

View File

@@ -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

View File

@@ -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}

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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;
});

View File

@@ -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;
}

View File

@@ -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);
}
}
}

View File

@@ -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. ' +

View File

@@ -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>,
];

View File

@@ -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}

View File

@@ -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))
);
}

View File

@@ -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)
)
);

View File

@@ -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 = {

View File

@@ -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);
}

View File

@@ -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)
),
}),
};

View File

@@ -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>;
}

View File

@@ -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;
}

View File

@@ -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 {

View File

@@ -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}

View File

@@ -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)),
]);
}

View File

@@ -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',
};
}

View File

@@ -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);
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}
}

View File

@@ -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',
});
}
}

View File

@@ -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';
};
}
}

View File

@@ -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;
}

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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');
}
}
}

View File

@@ -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 {

View File

@@ -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.';

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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;
}
)

View File

@@ -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);

View File

@@ -35,9 +35,7 @@ export class AuthenticationServiceImpl
)
);
removed?.forEach(() =>
this.clients.forEach((client) =>
client.notifySessionDidChange()
)
this.clients.forEach((client) => client.notifySessionDidChange())
);
}),
Disposable.create(() =>

View File

@@ -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 };
}

View File

@@ -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];

View File

@@ -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));
}

View File

@@ -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(

View File

@@ -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