From f5a1ae4225b24be27c0a4920a19f96af4fa0cfa9 Mon Sep 17 00:00:00 2001 From: Alberto Iannaccone Date: Wed, 22 Jun 2022 12:51:29 +0200 Subject: [PATCH 01/13] add commands to open sketchbook widgets add commands to show sketchbook widgets --- .../browser/arduino-ide-frontend-module.ts | 1 + .../cloud-sketchbook-widget.ts | 53 +++++++++++++++++-- .../widgets/sketchbook/sketchbook-commands.ts | 12 +++++ .../sketchbook-widget-contribution.ts | 14 +++-- .../widgets/sketchbook/sketchbook-widget.tsx | 16 +++++- 5 files changed, 87 insertions(+), 9 deletions(-) diff --git a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts index 5a0b5221b..08c9de2c9 100644 --- a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts +++ b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts @@ -832,6 +832,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(CloudSketchbookWidget).toSelf(); rebind(SketchbookWidget).toService(CloudSketchbookWidget); + bind(CommandContribution).toService(CloudSketchbookWidget); bind(CloudSketchbookTreeWidget).toDynamicValue(({ container }) => createCloudSketchbookTreeWidget(container) ); diff --git a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts index 22239a227..53cfeaef6 100644 --- a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts +++ b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts @@ -1,16 +1,36 @@ -import { inject, injectable, postConstruct } from '@theia/core/shared/inversify'; +import { + inject, + injectable, + postConstruct, +} from '@theia/core/shared/inversify'; import { CloudSketchbookCompositeWidget } from './cloud-sketchbook-composite-widget'; import { SketchbookWidget } from '../sketchbook/sketchbook-widget'; import { ArduinoPreferences } from '../../arduino-preferences'; +import { Command, CommandContribution, CommandRegistry } from '@theia/core'; +import { ApplicationShell } from '@theia/core/lib/browser'; + +export const SHOW_CLOUD_SKETCHBOOK_WIDGET = Command.toLocalizedCommand( + { + id: 'arduino-sketchbook--show-cloud-sketchbook-widget', + label: 'Show Cloud Sketchbook Widget', + }, + 'arduino/sketch/showCloudSketchbookWidget' +); @injectable() -export class CloudSketchbookWidget extends SketchbookWidget { +export class CloudSketchbookWidget + extends SketchbookWidget + implements CommandContribution +{ @inject(CloudSketchbookCompositeWidget) - protected readonly widget: CloudSketchbookCompositeWidget; + protected readonly cloudSketchbookCompositeWidget: CloudSketchbookCompositeWidget; @inject(ArduinoPreferences) protected readonly arduinoPreferences: ArduinoPreferences; + @inject(ApplicationShell) + protected readonly shell: ApplicationShell; + @postConstruct() protected override init(): void { super.init(); @@ -27,7 +47,9 @@ export class CloudSketchbookWidget extends SketchbookWidget { checkCloudEnabled() { if (this.arduinoPreferences['arduino.cloud.enabled']) { - this.sketchbookTreesContainer.activateWidget(this.widget); + this.sketchbookTreesContainer.activateWidget( + this.cloudSketchbookCompositeWidget + ); } else { this.sketchbookTreesContainer.activateWidget( this.localSketchbookTreeWidget @@ -45,7 +67,9 @@ export class CloudSketchbookWidget extends SketchbookWidget { } protected override onAfterAttach(msg: any): void { - this.sketchbookTreesContainer.addWidget(this.widget); + this.sketchbookTreesContainer.addWidget( + this.cloudSketchbookCompositeWidget + ); this.setDocumentMode(); this.arduinoPreferences.onPreferenceChanged((event) => { if (event.preferenceName === 'arduino.cloud.enabled') { @@ -54,4 +78,23 @@ export class CloudSketchbookWidget extends SketchbookWidget { }); super.onAfterAttach(msg); } + + registerCommands(registry: CommandRegistry): void { + this.sketchbookTreesContainer.addWidget( + this.cloudSketchbookCompositeWidget + ); + registry.registerCommand(SHOW_CLOUD_SKETCHBOOK_WIDGET, { + execute: this.showCloudSketchbookWidget.bind(this), + }); + } + + showCloudSketchbookWidget(): void { + if (this.arduinoPreferences['arduino.cloud.enabled']) { + this.shell.activateWidget(this.id).then((widget) => { + if (widget instanceof CloudSketchbookWidget) { + widget.activateTreeWidget(this.cloudSketchbookCompositeWidget.id); + } + }); + } + } } diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-commands.ts b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-commands.ts index f8e360650..c1f8bbd59 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-commands.ts +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-commands.ts @@ -1,6 +1,18 @@ import { Command } from '@theia/core/lib/common/command'; export namespace SketchbookCommands { + export const TOGGLE_SKETCHBOOK_WIDGET: Command = { + id: 'arduino-sketchbook-widget:toggle', + }; + + export const SHOW_SKETCHBOOK_WIDGET = Command.toLocalizedCommand( + { + id: 'arduino-sketchbook--show-sketchbook-widget', + label: 'Show Sketchbook Widget', + }, + 'arduino/sketch/showSketchbookWidget' + ); + export const OPEN_NEW_WINDOW = Command.toLocalizedCommand( { id: 'arduino-sketchbook--open-sketch-new-window', diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts index 16b66a26a..a2a711e94 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts @@ -77,7 +77,7 @@ export class SketchbookWidgetContribution area: 'left', rank: 1, }, - toggleCommandId: 'arduino-sketchbook-widget:toggle', + toggleCommandId: SketchbookCommands.TOGGLE_SKETCHBOOK_WIDGET.id, toggleKeybinding: 'CtrlCmd+Shift+B', }); } @@ -100,7 +100,9 @@ export class SketchbookWidgetContribution override registerCommands(registry: CommandRegistry): void { super.registerCommands(registry); - + registry.registerCommand(SketchbookCommands.SHOW_SKETCHBOOK_WIDGET, { + execute: () => this.showSketchbookWidget(), + }); registry.registerCommand(SketchbookCommands.OPEN_NEW_WINDOW, { execute: async (arg) => { return this.workspaceService.open(arg.node.uri); @@ -197,7 +199,7 @@ export class SketchbookWidgetContribution // unregister main menu action registry.unregisterMenuAction({ - commandId: 'arduino-sketchbook-widget:toggle', + commandId: SketchbookCommands.TOGGLE_SKETCHBOOK_WIDGET.id, }); registry.registerMenuAction(SKETCHBOOK__CONTEXT__MAIN_GROUP, { @@ -230,4 +232,10 @@ export class SketchbookWidgetContribution protected onCurrentWidgetChangedHandler(): void { this.selectWidgetFileNode(this.shell.currentWidget); } + + protected async showSketchbookWidget(): Promise { + const widget = await this.widget; + await this.shell.activateWidget(widget.id); + widget.activateTreeWidget(widget.getTreeWidget().id); + } } diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx index f0a427de7..a263b163e 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx @@ -1,4 +1,8 @@ -import { inject, injectable, postConstruct } from '@theia/core/shared/inversify'; +import { + inject, + injectable, + postConstruct, +} from '@theia/core/shared/inversify'; import { toArray } from '@theia/core/shared/@phosphor/algorithm'; import { IDragEvent } from '@theia/core/shared/@phosphor/dragdrop'; import { DockPanel, Widget } from '@theia/core/shared/@phosphor/widgets'; @@ -45,6 +49,16 @@ export class SketchbookWidget extends BaseWidget { return this.localSketchbookTreeWidget; } + activateTreeWidget(treeWidgetId: string): boolean { + for (const widget of toArray(this.sketchbookTreesContainer.widgets())) { + if (widget.id === treeWidgetId) { + this.sketchbookTreesContainer.activateWidget(widget); + return true; + } + } + return false; + } + protected override onActivateRequest(message: Message): void { super.onActivateRequest(message); From 7d17dd5012f9febde21b059749f049adfe6cf8c0 Mon Sep 17 00:00:00 2001 From: Alberto Iannaccone Date: Wed, 22 Jun 2022 18:24:51 +0200 Subject: [PATCH 02/13] enable sending commands via query params --- .../theia/workspace/workspace-service.ts | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts b/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts index e49da551b..145e97436 100644 --- a/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts +++ b/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts @@ -9,7 +9,10 @@ import { FrontendApplication } from '@theia/core/lib/browser/frontend-applicatio import { FocusTracker, Widget } from '@theia/core/lib/browser'; import { DEFAULT_WINDOW_HASH } from '@theia/core/lib/common/window'; import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state'; -import { WorkspaceService as TheiaWorkspaceService } from '@theia/workspace/lib/browser/workspace-service'; +import { + WorkspaceInput, + WorkspaceService as TheiaWorkspaceService, +} from '@theia/workspace/lib/browser/workspace-service'; import { ConfigService } from '../../../common/protocol/config-service'; import { SketchesService, @@ -17,6 +20,11 @@ import { } from '../../../common/protocol/sketches-service'; import { BoardsServiceProvider } from '../../boards/boards-service-provider'; import { BoardsConfig } from '../../boards/boards-config'; +import { Command } from '@theia/core'; + +interface WorkspaceOptions extends WorkspaceInput { + commands: Command[]; +} @injectable() export class WorkspaceService extends TheiaWorkspaceService { @@ -42,6 +50,7 @@ export class WorkspaceService extends TheiaWorkspaceService { protected readonly boardsServiceProvider: BoardsServiceProvider; private version?: string; + private optionsToAppendToURI?: WorkspaceOptions; async onStart(application: FrontendApplication): Promise { const info = await this.applicationServer.getApplicationInfo(); @@ -82,6 +91,11 @@ export class WorkspaceService extends TheiaWorkspaceService { } } + override open(uri: URI, options?: WorkspaceOptions): void { + this.optionsToAppendToURI = options; + super.doOpen(uri); + } + protected override openNewWindow(workspacePath: string): void { const { boardsConfig } = this.boardsServiceProvider; const url = BoardsConfig.Config.setConfig( @@ -89,6 +103,13 @@ export class WorkspaceService extends TheiaWorkspaceService { new URL(window.location.href) ); // Set the current boards config for the new browser window. url.hash = workspacePath; + if (this.optionsToAppendToURI) { + url.searchParams.set( + 'commands', + encodeURIComponent(JSON.stringify(this.optionsToAppendToURI?.commands)) + ); + this.optionsToAppendToURI = undefined; + } this.windowService.openNewWindow(url.toString()); } From e1ef5e26f0e6a4c288f60ae65eae2832bf200a60 Mon Sep 17 00:00:00 2001 From: Alberto Iannaccone Date: Wed, 22 Jun 2022 18:32:53 +0200 Subject: [PATCH 03/13] opening sketch in new window will open sketchbook --- .../browser/contributions/sketch-control.ts | 2 +- .../cloud-sketchbook-contributions.ts | 13 +++- .../cloud-sketchbook-widget.ts | 26 ++++---- .../sketchbook-widget-contribution.ts | 64 +++++++++++++++++-- 4 files changed, 84 insertions(+), 21 deletions(-) diff --git a/arduino-ide-extension/src/browser/contributions/sketch-control.ts b/arduino-ide-extension/src/browser/contributions/sketch-control.ts index ea376fea1..1d2d77801 100644 --- a/arduino-ide-extension/src/browser/contributions/sketch-control.ts +++ b/arduino-ide-extension/src/browser/contributions/sketch-control.ts @@ -250,7 +250,7 @@ export class SketchControl extends SketchContribution { }); } - protected isCloudSketch(uri: string): boolean { + isCloudSketch(uri: string): boolean { try { const cloudCacheLocation = this.localCacheFsProvider.from(new URI(uri)); diff --git a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-contributions.ts b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-contributions.ts index 85e703554..13a840b7f 100644 --- a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-contributions.ts +++ b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-contributions.ts @@ -23,7 +23,10 @@ import { } from '@theia/core/lib/browser/preferences/preference-service'; import { ArduinoMenus, PlaceholderMenuNode } from '../../menu/arduino-menus'; import { SketchbookCommands } from '../sketchbook/sketchbook-commands'; -import { CurrentSketch, SketchesServiceClientImpl } from '../../../common/protocol/sketches-service-client-impl'; +import { + CurrentSketch, + SketchesServiceClientImpl, +} from '../../../common/protocol/sketches-service-client-impl'; import { Contribution } from '../../contributions/contribution'; import { ArduinoPreferences } from '../../arduino-preferences'; import { MainMenuManager } from '../../../common/main-menu-manager'; @@ -61,6 +64,14 @@ export namespace CloudSketchbookCommands { } } + export const SHOW_CLOUD_SKETCHBOOK_WIDGET = Command.toLocalizedCommand( + { + id: 'arduino-cloud-sketchbook--show-cloud-sketchbook-widget', + label: 'Show Cloud Sketchbook Widget', + }, + 'arduino/sketch/showCloudSketchbookWidget' + ); + export const TOGGLE_CLOUD_SKETCHBOOK = Command.toLocalizedCommand( { id: 'arduino-cloud-sketchbook--disable', diff --git a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts index 53cfeaef6..d27d02414 100644 --- a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts +++ b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts @@ -6,16 +6,10 @@ import { import { CloudSketchbookCompositeWidget } from './cloud-sketchbook-composite-widget'; import { SketchbookWidget } from '../sketchbook/sketchbook-widget'; import { ArduinoPreferences } from '../../arduino-preferences'; -import { Command, CommandContribution, CommandRegistry } from '@theia/core'; +import { CommandContribution, CommandRegistry } from '@theia/core'; import { ApplicationShell } from '@theia/core/lib/browser'; - -export const SHOW_CLOUD_SKETCHBOOK_WIDGET = Command.toLocalizedCommand( - { - id: 'arduino-sketchbook--show-cloud-sketchbook-widget', - label: 'Show Cloud Sketchbook Widget', - }, - 'arduino/sketch/showCloudSketchbookWidget' -); +import { CloudSketchbookCommands } from './cloud-sketchbook-contributions'; +import { EditorManager } from '@theia/editor/lib/browser'; @injectable() export class CloudSketchbookWidget @@ -31,6 +25,9 @@ export class CloudSketchbookWidget @inject(ApplicationShell) protected readonly shell: ApplicationShell; + @inject(EditorManager) + protected readonly editorManager: EditorManager; + @postConstruct() protected override init(): void { super.init(); @@ -83,9 +80,12 @@ export class CloudSketchbookWidget this.sketchbookTreesContainer.addWidget( this.cloudSketchbookCompositeWidget ); - registry.registerCommand(SHOW_CLOUD_SKETCHBOOK_WIDGET, { - execute: this.showCloudSketchbookWidget.bind(this), - }); + registry.registerCommand( + CloudSketchbookCommands.SHOW_CLOUD_SKETCHBOOK_WIDGET, + { + execute: () => this.showCloudSketchbookWidget(), + } + ); } showCloudSketchbookWidget(): void { @@ -94,6 +94,8 @@ export class CloudSketchbookWidget if (widget instanceof CloudSketchbookWidget) { widget.activateTreeWidget(this.cloudSketchbookCompositeWidget.id); } + if (this.editorManager.currentEditor) + this.shell.activateWidget(this.editorManager.currentEditor.id); }); } } diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts index a2a711e94..5519c17ea 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts @@ -1,6 +1,6 @@ import * as remote from '@theia/core/electron-shared/@electron/remote'; import { inject, injectable } from '@theia/core/shared/inversify'; -import { CommandRegistry } from '@theia/core/lib/common/command'; +import { Command, CommandRegistry } from '@theia/core/lib/common/command'; import { MenuModelRegistry } from '@theia/core/lib/common/menu'; import { PreferenceService } from '@theia/core/lib/browser/preferences/preference-service'; import { AbstractViewContribution } from '@theia/core/lib/browser/shell/view-contribution'; @@ -29,6 +29,10 @@ import { } from '../../../common/protocol/sketches-service-client-impl'; import { FileService } from '@theia/filesystem/lib/browser/file-service'; import { URI } from '../../contributions/contribution'; +import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state'; +import { EditorManager } from '@theia/editor/lib/browser'; +import { SketchControl } from '../../contributions/sketch-control'; +import { CloudSketchbookCommands } from '../cloud-sketchbook/cloud-sketchbook-contributions'; export const SKETCHBOOK__CONTEXT = ['arduino-sketchbook--context']; @@ -67,6 +71,18 @@ export class SketchbookWidgetContribution @inject(FileService) protected readonly fileService: FileService; + @inject(CommandRegistry) + protected readonly commandRegistry: CommandRegistry; + + @inject(FrontendApplicationStateService) + private readonly app: FrontendApplicationStateService; + + @inject(EditorManager) + protected readonly editorManager: EditorManager; + + @inject(SketchControl) + protected readonly sketchControl: SketchControl; + protected readonly toDisposeBeforeNewContextMenu = new DisposableCollection(); constructor() { @@ -92,6 +108,12 @@ export class SketchbookWidgetContribution this.mainMenuManager.update(); } }); + + this.app.reachedState('ready').then(() => this.onReady()); + } + + onReady(): void { + this.runEncodedCommands(); } async initializeLayout(): Promise { @@ -104,9 +126,7 @@ export class SketchbookWidgetContribution execute: () => this.showSketchbookWidget(), }); registry.registerCommand(SketchbookCommands.OPEN_NEW_WINDOW, { - execute: async (arg) => { - return this.workspaceService.open(arg.node.uri); - }, + execute: (arg) => this.openSketchInNewWindow(arg), isEnabled: (arg) => !!arg && 'node' in arg && SketchbookTree.SketchDirNode.is(arg.node), isVisible: (arg) => @@ -194,6 +214,15 @@ export class SketchbookWidgetContribution }); } + openSketchInNewWindow(arg: any): any { + const openSketchbookCommand = this.sketchControl.isCloudSketch(arg.node.uri) + ? CloudSketchbookCommands.SHOW_CLOUD_SKETCHBOOK_WIDGET + : SketchbookCommands.SHOW_SKETCHBOOK_WIDGET; + return this.workspaceService.open(arg.node.uri, { + commands: [openSketchbookCommand], + }); + } + override registerMenus(registry: MenuModelRegistry): void { super.registerMenus(registry); @@ -234,8 +263,29 @@ export class SketchbookWidgetContribution } protected async showSketchbookWidget(): Promise { - const widget = await this.widget; - await this.shell.activateWidget(widget.id); - widget.activateTreeWidget(widget.getTreeWidget().id); + this.widget + .then((widget) => this.shell.activateWidget(widget.id)) + .then((widget) => { + if (widget instanceof SketchbookWidget) { + widget.activateTreeWidget(widget.getTreeWidget().id); + if (this.editorManager.currentEditor) + this.shell.activateWidget(this.editorManager.currentEditor.id); + } + }); + } + + protected runEncodedCommands(): void { + const params = new URLSearchParams(window.location.search); + const encoded = params.get('commands'); + if (!encoded) return; + + const commands = JSON.parse(decodeURIComponent(encoded)); + + if (commands && Array.isArray(commands)) { + commands.forEach((c: Command) => { + if (this.commandRegistry.commandIds.includes(c.id)) + this.commandRegistry.executeCommand(c.id); + }); + } } } From a6d762a758920aa93a31b820abe67dc8d78f7a6f Mon Sep 17 00:00:00 2001 From: Alberto Iannaccone Date: Thu, 23 Jun 2022 12:28:50 +0200 Subject: [PATCH 04/13] requested changes --- .../cloud-sketchbook/cloud-sketchbook-widget.ts | 17 +++++++++++------ .../sketchbook-widget-contribution.ts | 12 +++++------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts index d27d02414..5d1f20c87 100644 --- a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts +++ b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts @@ -10,6 +10,7 @@ import { CommandContribution, CommandRegistry } from '@theia/core'; import { ApplicationShell } from '@theia/core/lib/browser'; import { CloudSketchbookCommands } from './cloud-sketchbook-contributions'; import { EditorManager } from '@theia/editor/lib/browser'; +import { SketchbookWidgetContribution } from '../sketchbook/sketchbook-widget-contribution'; @injectable() export class CloudSketchbookWidget @@ -17,16 +18,19 @@ export class CloudSketchbookWidget implements CommandContribution { @inject(CloudSketchbookCompositeWidget) - protected readonly cloudSketchbookCompositeWidget: CloudSketchbookCompositeWidget; + private readonly cloudSketchbookCompositeWidget: CloudSketchbookCompositeWidget; @inject(ArduinoPreferences) - protected readonly arduinoPreferences: ArduinoPreferences; + private readonly arduinoPreferences: ArduinoPreferences; @inject(ApplicationShell) - protected readonly shell: ApplicationShell; + private readonly shell: ApplicationShell; + + @inject(SketchbookWidgetContribution) + private readonly sketchbookWidgetContribution: SketchbookWidgetContribution; @inject(EditorManager) - protected readonly editorManager: EditorManager; + private readonly editorManager: EditorManager; @postConstruct() protected override init(): void { @@ -94,8 +98,9 @@ export class CloudSketchbookWidget if (widget instanceof CloudSketchbookWidget) { widget.activateTreeWidget(this.cloudSketchbookCompositeWidget.id); } - if (this.editorManager.currentEditor) - this.shell.activateWidget(this.editorManager.currentEditor.id); + this.sketchbookWidgetContribution.selectWidgetFileNode( + this.editorManager.currentEditor + ); }); } } diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts index 5519c17ea..a6eb309bb 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts @@ -123,7 +123,7 @@ export class SketchbookWidgetContribution override registerCommands(registry: CommandRegistry): void { super.registerCommands(registry); registry.registerCommand(SketchbookCommands.SHOW_SKETCHBOOK_WIDGET, { - execute: () => this.showSketchbookWidget(), + execute: () => this.showLocalSketchbookWidget(), }); registry.registerCommand(SketchbookCommands.OPEN_NEW_WINDOW, { execute: (arg) => this.openSketchInNewWindow(arg), @@ -262,14 +262,13 @@ export class SketchbookWidgetContribution this.selectWidgetFileNode(this.shell.currentWidget); } - protected async showSketchbookWidget(): Promise { + protected async showLocalSketchbookWidget(): Promise { this.widget .then((widget) => this.shell.activateWidget(widget.id)) .then((widget) => { if (widget instanceof SketchbookWidget) { widget.activateTreeWidget(widget.getTreeWidget().id); - if (this.editorManager.currentEditor) - this.shell.activateWidget(this.editorManager.currentEditor.id); + this.selectWidgetFileNode(this.editorManager.currentEditor); } }); } @@ -281,10 +280,9 @@ export class SketchbookWidgetContribution const commands = JSON.parse(decodeURIComponent(encoded)); - if (commands && Array.isArray(commands)) { + if (Array.isArray(commands)) { commands.forEach((c: Command) => { - if (this.commandRegistry.commandIds.includes(c.id)) - this.commandRegistry.executeCommand(c.id); + this.commandRegistry.executeCommand(c.id); }); } } From 1b06314092d455afbd37ce14137bc989b9649366 Mon Sep 17 00:00:00 2001 From: Alberto Iannaccone Date: Thu, 23 Jun 2022 16:09:14 +0200 Subject: [PATCH 05/13] add specific method WorkspaceService to open sketch with commands --- .../theia/workspace/workspace-service.ts | 58 ++++++++++++++++--- .../sketchbook-widget-contribution.ts | 2 +- 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts b/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts index 145e97436..25fce9df7 100644 --- a/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts +++ b/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts @@ -50,7 +50,6 @@ export class WorkspaceService extends TheiaWorkspaceService { protected readonly boardsServiceProvider: BoardsServiceProvider; private version?: string; - private optionsToAppendToURI?: WorkspaceOptions; async onStart(application: FrontendApplication): Promise { const info = await this.applicationServer.getApplicationInfo(); @@ -91,25 +90,68 @@ export class WorkspaceService extends TheiaWorkspaceService { } } - override open(uri: URI, options?: WorkspaceOptions): void { - this.optionsToAppendToURI = options; - super.doOpen(uri); + /* + This method mostly duplicates super.doOpen and super.openWindow because they didn't let pass any custom + option to openNewWindow + */ + async openWithCommands(uri: URI, options?: WorkspaceOptions): Promise { + const stat = await this.toFileStat(uri); + if (stat) { + if (!stat.isDirectory && !this.isWorkspaceFile(stat)) { + const message = `Not a valid workspace: ${uri.path.toString()}`; + this.messageService.error(message); + throw new Error(message); + } + // The same window has to be preserved too (instead of opening a new one), if the workspace root is not yet available and we are setting it for the first time. + // Option passed as parameter has the highest priority (for api developers), then the preference, then the default. + await this.roots; + const { preserveWindow } = { + preserveWindow: + this.preferences['workspace.preserveWindow'] || !this.opened, + ...options, + }; + await this.server.setMostRecentlyUsedWorkspace(uri.toString()); + if (preserveWindow) { + this._workspace = stat; + } + + const workspacePath = stat.resource.path.toString(); + + if (this.shouldPreserveWindow(options)) { + this.reloadWindow(); + } else { + try { + this.openNewWindow(workspacePath, options); + return; + } catch (error) { + // Fall back to reloading the current window in case the browser has blocked the new window + this._workspace = stat; + this.logger.error(error.toString()).then(() => this.reloadWindow()); + } + } + } + throw new Error( + 'Invalid workspace root URI. Expected an existing directory or workspace file.' + ); } - protected override openNewWindow(workspacePath: string): void { + protected override openNewWindow( + workspacePath: string, + options?: WorkspaceOptions + ): void { const { boardsConfig } = this.boardsServiceProvider; const url = BoardsConfig.Config.setConfig( boardsConfig, new URL(window.location.href) ); // Set the current boards config for the new browser window. url.hash = workspacePath; - if (this.optionsToAppendToURI) { + if (options?.commands) { url.searchParams.set( 'commands', - encodeURIComponent(JSON.stringify(this.optionsToAppendToURI?.commands)) + encodeURIComponent(JSON.stringify(options.commands)) ); - this.optionsToAppendToURI = undefined; } + this.windowService.openNewWindow(url.toString()); } diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts index a6eb309bb..4eba51d4a 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts @@ -218,7 +218,7 @@ export class SketchbookWidgetContribution const openSketchbookCommand = this.sketchControl.isCloudSketch(arg.node.uri) ? CloudSketchbookCommands.SHOW_CLOUD_SKETCHBOOK_WIDGET : SketchbookCommands.SHOW_SKETCHBOOK_WIDGET; - return this.workspaceService.open(arg.node.uri, { + return this.workspaceService.openWithCommands(arg.node.uri, { commands: [openSketchbookCommand], }); } From 9630eb202f1c6f5686445dc22611d5200e129e7f Mon Sep 17 00:00:00 2001 From: Alberto Iannaccone Date: Thu, 23 Jun 2022 17:49:54 +0200 Subject: [PATCH 06/13] add encoded commands contribution --- .../browser/arduino-ide-frontend-module.ts | 2 ++ .../encoded-commands-contribution.ts | 23 +++++++++++++++ .../sketchbook-widget-contribution.ts | 29 +------------------ 3 files changed, 26 insertions(+), 28 deletions(-) create mode 100644 arduino-ide-extension/src/browser/widgets/sketchbook/encoded-commands-contribution.ts diff --git a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts index 08c9de2c9..1148e15e8 100644 --- a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts +++ b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts @@ -302,6 +302,7 @@ import { CoreErrorHandler } from './contributions/core-error-handler'; import { CompilerErrors } from './contributions/compiler-errors'; import { WidgetManager } from './theia/core/widget-manager'; import { WidgetManager as TheiaWidgetManager } from '@theia/core/lib/browser/widget-manager'; +import { EncodedCommandsContribution } from './widgets/sketchbook/encoded-commands-contribution'; MonacoThemingService.register({ id: 'arduino-theme', @@ -698,6 +699,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { Contribution.configure(bind, PlotterFrontendContribution); Contribution.configure(bind, Format); Contribution.configure(bind, CompilerErrors); + Contribution.configure(bind, EncodedCommandsContribution); // Disabled the quick-pick customization from Theia when multiple formatters are available. // Use the default VS Code behavior, and pick the first one. In the IDE2, clang-format has `exclusive` selectors. diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/encoded-commands-contribution.ts b/arduino-ide-extension/src/browser/widgets/sketchbook/encoded-commands-contribution.ts new file mode 100644 index 000000000..c2a1872e2 --- /dev/null +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/encoded-commands-contribution.ts @@ -0,0 +1,23 @@ +import { Command, CommandRegistry, MaybePromise } from '@theia/core'; +import { inject, injectable } from '@theia/core/shared/inversify'; +import { Contribution } from '../../contributions/contribution'; + +@injectable() +export class EncodedCommandsContribution extends Contribution { + @inject(CommandRegistry) + protected readonly commandRegistry: CommandRegistry; + + override onReady(): MaybePromise { + const params = new URLSearchParams(window.location.search); + const encoded = params.get('commands'); + if (!encoded) return; + + const commands = JSON.parse(decodeURIComponent(encoded)); + + if (Array.isArray(commands)) { + commands.forEach((c: Command) => { + this.commandRegistry.executeCommand(c.id); + }); + } + } +} diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts index 4eba51d4a..66a2d1535 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts @@ -1,6 +1,6 @@ import * as remote from '@theia/core/electron-shared/@electron/remote'; import { inject, injectable } from '@theia/core/shared/inversify'; -import { Command, CommandRegistry } from '@theia/core/lib/common/command'; +import { CommandRegistry } from '@theia/core/lib/common/command'; import { MenuModelRegistry } from '@theia/core/lib/common/menu'; import { PreferenceService } from '@theia/core/lib/browser/preferences/preference-service'; import { AbstractViewContribution } from '@theia/core/lib/browser/shell/view-contribution'; @@ -29,7 +29,6 @@ import { } from '../../../common/protocol/sketches-service-client-impl'; import { FileService } from '@theia/filesystem/lib/browser/file-service'; import { URI } from '../../contributions/contribution'; -import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state'; import { EditorManager } from '@theia/editor/lib/browser'; import { SketchControl } from '../../contributions/sketch-control'; import { CloudSketchbookCommands } from '../cloud-sketchbook/cloud-sketchbook-contributions'; @@ -71,12 +70,6 @@ export class SketchbookWidgetContribution @inject(FileService) protected readonly fileService: FileService; - @inject(CommandRegistry) - protected readonly commandRegistry: CommandRegistry; - - @inject(FrontendApplicationStateService) - private readonly app: FrontendApplicationStateService; - @inject(EditorManager) protected readonly editorManager: EditorManager; @@ -108,12 +101,6 @@ export class SketchbookWidgetContribution this.mainMenuManager.update(); } }); - - this.app.reachedState('ready').then(() => this.onReady()); - } - - onReady(): void { - this.runEncodedCommands(); } async initializeLayout(): Promise { @@ -272,18 +259,4 @@ export class SketchbookWidgetContribution } }); } - - protected runEncodedCommands(): void { - const params = new URLSearchParams(window.location.search); - const encoded = params.get('commands'); - if (!encoded) return; - - const commands = JSON.parse(decodeURIComponent(encoded)); - - if (Array.isArray(commands)) { - commands.forEach((c: Command) => { - this.commandRegistry.executeCommand(c.id); - }); - } - } } From 50e0233a5899febdb49eb1a188ea2b2509647e4d Mon Sep 17 00:00:00 2001 From: Alberto Iannaccone Date: Wed, 29 Jun 2022 15:22:28 +0200 Subject: [PATCH 07/13] try merge show sketchbook commands --- .../theia/workspace/workspace-service.ts | 4 +- .../encoded-commands-contribution.ts | 10 +++-- .../sketchbook-widget-contribution.ts | 37 ++++++++++++------- 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts b/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts index 25fce9df7..726899444 100644 --- a/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts +++ b/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts @@ -20,10 +20,10 @@ import { } from '../../../common/protocol/sketches-service'; import { BoardsServiceProvider } from '../../boards/boards-service-provider'; import { BoardsConfig } from '../../boards/boards-config'; -import { Command } from '@theia/core'; +import { EncodableCommad } from '../../widgets/sketchbook/encoded-commands-contribution'; interface WorkspaceOptions extends WorkspaceInput { - commands: Command[]; + commands: EncodableCommad[]; } @injectable() diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/encoded-commands-contribution.ts b/arduino-ide-extension/src/browser/widgets/sketchbook/encoded-commands-contribution.ts index c2a1872e2..80824509a 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/encoded-commands-contribution.ts +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/encoded-commands-contribution.ts @@ -1,7 +1,11 @@ -import { Command, CommandRegistry, MaybePromise } from '@theia/core'; +import { CommandRegistry, MaybePromise } from '@theia/core'; import { inject, injectable } from '@theia/core/shared/inversify'; import { Contribution } from '../../contributions/contribution'; +export type EncodableCommad = { + id: string; + args?: any[]; +}; @injectable() export class EncodedCommandsContribution extends Contribution { @inject(CommandRegistry) @@ -15,8 +19,8 @@ export class EncodedCommandsContribution extends Contribution { const commands = JSON.parse(decodeURIComponent(encoded)); if (Array.isArray(commands)) { - commands.forEach((c: Command) => { - this.commandRegistry.executeCommand(c.id); + commands.forEach((c: EncodableCommad) => { + this.commandRegistry.executeCommand(c.id, c.args); }); } } diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts index 66a2d1535..766ecd8b9 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts @@ -17,6 +17,7 @@ import { Navigatable, RenderContextMenuOptions, SelectableTreeNode, + TreeNode, Widget, } from '@theia/core/lib/browser'; import { @@ -29,9 +30,9 @@ import { } from '../../../common/protocol/sketches-service-client-impl'; import { FileService } from '@theia/filesystem/lib/browser/file-service'; import { URI } from '../../contributions/contribution'; -import { EditorManager } from '@theia/editor/lib/browser'; import { SketchControl } from '../../contributions/sketch-control'; -import { CloudSketchbookCommands } from '../cloud-sketchbook/cloud-sketchbook-contributions'; +import { SketchbookTreeWidget } from './sketchbook-tree-widget'; +import { EncodableCommad } from './encoded-commands-contribution'; export const SKETCHBOOK__CONTEXT = ['arduino-sketchbook--context']; @@ -70,9 +71,6 @@ export class SketchbookWidgetContribution @inject(FileService) protected readonly fileService: FileService; - @inject(EditorManager) - protected readonly editorManager: EditorManager; - @inject(SketchControl) protected readonly sketchControl: SketchControl; @@ -110,7 +108,8 @@ export class SketchbookWidgetContribution override registerCommands(registry: CommandRegistry): void { super.registerCommands(registry); registry.registerCommand(SketchbookCommands.SHOW_SKETCHBOOK_WIDGET, { - execute: () => this.showLocalSketchbookWidget(), + execute: (treeWidget: SketchbookTreeWidget, node: TreeNode) => + this.showSketchbookWidget(treeWidget, node), }); registry.registerCommand(SketchbookCommands.OPEN_NEW_WINDOW, { execute: (arg) => this.openSketchInNewWindow(arg), @@ -201,12 +200,16 @@ export class SketchbookWidgetContribution }); } - openSketchInNewWindow(arg: any): any { - const openSketchbookCommand = this.sketchControl.isCloudSketch(arg.node.uri) - ? CloudSketchbookCommands.SHOW_CLOUD_SKETCHBOOK_WIDGET - : SketchbookCommands.SHOW_SKETCHBOOK_WIDGET; + async openSketchInNewWindow(arg: any): Promise { + const treeWidget: SketchbookTreeWidget = ( + await this.widget + ).getTreeWidget(); + const command: EncodableCommad = { + id: SketchbookCommands.SHOW_SKETCHBOOK_WIDGET.id, + args: [treeWidget, arg.node], + }; return this.workspaceService.openWithCommands(arg.node.uri, { - commands: [openSketchbookCommand], + commands: [command], }); } @@ -249,13 +252,19 @@ export class SketchbookWidgetContribution this.selectWidgetFileNode(this.shell.currentWidget); } - protected async showLocalSketchbookWidget(): Promise { + protected async showSketchbookWidget( + treeWidget: SketchbookTreeWidget, + node: TreeNode + ): Promise { this.widget .then((widget) => this.shell.activateWidget(widget.id)) .then((widget) => { if (widget instanceof SketchbookWidget) { - widget.activateTreeWidget(widget.getTreeWidget().id); - this.selectWidgetFileNode(this.editorManager.currentEditor); + widget.activateTreeWidget(treeWidget.id); + if (SelectableTreeNode.is(node)) { + const { model } = treeWidget; + model.selectNode(node); + } } }); } From 49f2e5cbe372225280b70ac52313832addc177ea Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Thu, 30 Jun 2022 11:47:19 +0200 Subject: [PATCH 08/13] pair session changes. Signed-off-by: Akos Kitta --- .../browser/arduino-ide-frontend-module.ts | 5 +- .../browser/contributions/sketch-control.ts | 2 +- .../theia/workspace/workspace-service.ts | 62 +++++++++--------- .../cloud-sketchbook-widget.ts | 62 ++---------------- .../encoded-commands-contribution.ts | 27 -------- .../widgets/sketchbook/sketchbook-commands.ts | 7 +-- .../sketchbook-widget-contribution.ts | 63 +++++++++---------- .../widgets/sketchbook/sketchbook-widget.tsx | 60 +++++++++++++++--- .../widgets/sketchbook/startup-task.ts | 42 +++++++++++++ 9 files changed, 170 insertions(+), 160 deletions(-) delete mode 100644 arduino-ide-extension/src/browser/widgets/sketchbook/encoded-commands-contribution.ts create mode 100644 arduino-ide-extension/src/browser/widgets/sketchbook/startup-task.ts diff --git a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts index 1148e15e8..fdab829f3 100644 --- a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts +++ b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts @@ -302,7 +302,7 @@ import { CoreErrorHandler } from './contributions/core-error-handler'; import { CompilerErrors } from './contributions/compiler-errors'; import { WidgetManager } from './theia/core/widget-manager'; import { WidgetManager as TheiaWidgetManager } from '@theia/core/lib/browser/widget-manager'; -import { EncodedCommandsContribution } from './widgets/sketchbook/encoded-commands-contribution'; +import { StartupTask } from './widgets/sketchbook/startup-task'; MonacoThemingService.register({ id: 'arduino-theme', @@ -699,7 +699,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { Contribution.configure(bind, PlotterFrontendContribution); Contribution.configure(bind, Format); Contribution.configure(bind, CompilerErrors); - Contribution.configure(bind, EncodedCommandsContribution); + Contribution.configure(bind, StartupTask); // Disabled the quick-pick customization from Theia when multiple formatters are available. // Use the default VS Code behavior, and pick the first one. In the IDE2, clang-format has `exclusive` selectors. @@ -834,7 +834,6 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(CloudSketchbookWidget).toSelf(); rebind(SketchbookWidget).toService(CloudSketchbookWidget); - bind(CommandContribution).toService(CloudSketchbookWidget); bind(CloudSketchbookTreeWidget).toDynamicValue(({ container }) => createCloudSketchbookTreeWidget(container) ); diff --git a/arduino-ide-extension/src/browser/contributions/sketch-control.ts b/arduino-ide-extension/src/browser/contributions/sketch-control.ts index 1d2d77801..ea376fea1 100644 --- a/arduino-ide-extension/src/browser/contributions/sketch-control.ts +++ b/arduino-ide-extension/src/browser/contributions/sketch-control.ts @@ -250,7 +250,7 @@ export class SketchControl extends SketchContribution { }); } - isCloudSketch(uri: string): boolean { + protected isCloudSketch(uri: string): boolean { try { const cloudCacheLocation = this.localCacheFsProvider.from(new URI(uri)); diff --git a/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts b/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts index 726899444..f51479b28 100644 --- a/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts +++ b/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts @@ -20,11 +20,8 @@ import { } from '../../../common/protocol/sketches-service'; import { BoardsServiceProvider } from '../../boards/boards-service-provider'; import { BoardsConfig } from '../../boards/boards-config'; -import { EncodableCommad } from '../../widgets/sketchbook/encoded-commands-contribution'; - -interface WorkspaceOptions extends WorkspaceInput { - commands: EncodableCommad[]; -} +import { FileStat } from '@theia/filesystem/lib/common/files'; +import { StartupTask } from '../../widgets/sketchbook/startup-task'; @injectable() export class WorkspaceService extends TheiaWorkspaceService { @@ -90,11 +87,13 @@ export class WorkspaceService extends TheiaWorkspaceService { } } - /* - This method mostly duplicates super.doOpen and super.openWindow because they didn't let pass any custom - option to openNewWindow - */ - async openWithCommands(uri: URI, options?: WorkspaceOptions): Promise { + /** + * Copied from Theia as-is to be able to pass the original `options` down. + */ + protected override async doOpen( + uri: URI, + options?: WorkspaceInput + ): Promise { const stat = await this.toFileStat(uri); if (stat) { if (!stat.isDirectory && !this.isWorkspaceFile(stat)) { @@ -114,30 +113,35 @@ export class WorkspaceService extends TheiaWorkspaceService { if (preserveWindow) { this._workspace = stat; } - - const workspacePath = stat.resource.path.toString(); - - if (this.shouldPreserveWindow(options)) { - this.reloadWindow(); - } else { - try { - this.openNewWindow(workspacePath, options); - return; - } catch (error) { - // Fall back to reloading the current window in case the browser has blocked the new window - this._workspace = stat; - this.logger.error(error.toString()).then(() => this.reloadWindow()); - } - } + this.openWindow(stat, Object.assign(options ?? {}, { preserveWindow })); + return; } throw new Error( 'Invalid workspace root URI. Expected an existing directory or workspace file.' ); } + /** + * Copied from Theia. Can pass the `options` further down the chain. + */ + protected override openWindow(uri: FileStat, options?: WorkspaceInput): void { + const workspacePath = uri.resource.path.toString(); + if (this.shouldPreserveWindow(options)) { + this.reloadWindow(); + } else { + try { + this.openNewWindow(workspacePath, options); // Unlike Theia, IDE2 passes the `input` downstream. + } catch (error) { + // Fall back to reloading the current window in case the browser has blocked the new window + this._workspace = uri; + this.logger.error(error.toString()).then(() => this.reloadWindow()); + } + } + } + protected override openNewWindow( workspacePath: string, - options?: WorkspaceOptions + options?: WorkspaceInput ): void { const { boardsConfig } = this.boardsServiceProvider; const url = BoardsConfig.Config.setConfig( @@ -145,10 +149,10 @@ export class WorkspaceService extends TheiaWorkspaceService { new URL(window.location.href) ); // Set the current boards config for the new browser window. url.hash = workspacePath; - if (options?.commands) { + if (StartupTask.WorkspaceInput.is(options)) { url.searchParams.set( - 'commands', - encodeURIComponent(JSON.stringify(options.commands)) + StartupTask.QUERY_STRING, + encodeURIComponent(JSON.stringify(options.tasks)) ); } diff --git a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts index 5d1f20c87..22239a227 100644 --- a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts +++ b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts @@ -1,36 +1,15 @@ -import { - inject, - injectable, - postConstruct, -} from '@theia/core/shared/inversify'; +import { inject, injectable, postConstruct } from '@theia/core/shared/inversify'; import { CloudSketchbookCompositeWidget } from './cloud-sketchbook-composite-widget'; import { SketchbookWidget } from '../sketchbook/sketchbook-widget'; import { ArduinoPreferences } from '../../arduino-preferences'; -import { CommandContribution, CommandRegistry } from '@theia/core'; -import { ApplicationShell } from '@theia/core/lib/browser'; -import { CloudSketchbookCommands } from './cloud-sketchbook-contributions'; -import { EditorManager } from '@theia/editor/lib/browser'; -import { SketchbookWidgetContribution } from '../sketchbook/sketchbook-widget-contribution'; @injectable() -export class CloudSketchbookWidget - extends SketchbookWidget - implements CommandContribution -{ +export class CloudSketchbookWidget extends SketchbookWidget { @inject(CloudSketchbookCompositeWidget) - private readonly cloudSketchbookCompositeWidget: CloudSketchbookCompositeWidget; + protected readonly widget: CloudSketchbookCompositeWidget; @inject(ArduinoPreferences) - private readonly arduinoPreferences: ArduinoPreferences; - - @inject(ApplicationShell) - private readonly shell: ApplicationShell; - - @inject(SketchbookWidgetContribution) - private readonly sketchbookWidgetContribution: SketchbookWidgetContribution; - - @inject(EditorManager) - private readonly editorManager: EditorManager; + protected readonly arduinoPreferences: ArduinoPreferences; @postConstruct() protected override init(): void { @@ -48,9 +27,7 @@ export class CloudSketchbookWidget checkCloudEnabled() { if (this.arduinoPreferences['arduino.cloud.enabled']) { - this.sketchbookTreesContainer.activateWidget( - this.cloudSketchbookCompositeWidget - ); + this.sketchbookTreesContainer.activateWidget(this.widget); } else { this.sketchbookTreesContainer.activateWidget( this.localSketchbookTreeWidget @@ -68,9 +45,7 @@ export class CloudSketchbookWidget } protected override onAfterAttach(msg: any): void { - this.sketchbookTreesContainer.addWidget( - this.cloudSketchbookCompositeWidget - ); + this.sketchbookTreesContainer.addWidget(this.widget); this.setDocumentMode(); this.arduinoPreferences.onPreferenceChanged((event) => { if (event.preferenceName === 'arduino.cloud.enabled') { @@ -79,29 +54,4 @@ export class CloudSketchbookWidget }); super.onAfterAttach(msg); } - - registerCommands(registry: CommandRegistry): void { - this.sketchbookTreesContainer.addWidget( - this.cloudSketchbookCompositeWidget - ); - registry.registerCommand( - CloudSketchbookCommands.SHOW_CLOUD_SKETCHBOOK_WIDGET, - { - execute: () => this.showCloudSketchbookWidget(), - } - ); - } - - showCloudSketchbookWidget(): void { - if (this.arduinoPreferences['arduino.cloud.enabled']) { - this.shell.activateWidget(this.id).then((widget) => { - if (widget instanceof CloudSketchbookWidget) { - widget.activateTreeWidget(this.cloudSketchbookCompositeWidget.id); - } - this.sketchbookWidgetContribution.selectWidgetFileNode( - this.editorManager.currentEditor - ); - }); - } - } } diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/encoded-commands-contribution.ts b/arduino-ide-extension/src/browser/widgets/sketchbook/encoded-commands-contribution.ts deleted file mode 100644 index 80824509a..000000000 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/encoded-commands-contribution.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { CommandRegistry, MaybePromise } from '@theia/core'; -import { inject, injectable } from '@theia/core/shared/inversify'; -import { Contribution } from '../../contributions/contribution'; - -export type EncodableCommad = { - id: string; - args?: any[]; -}; -@injectable() -export class EncodedCommandsContribution extends Contribution { - @inject(CommandRegistry) - protected readonly commandRegistry: CommandRegistry; - - override onReady(): MaybePromise { - const params = new URLSearchParams(window.location.search); - const encoded = params.get('commands'); - if (!encoded) return; - - const commands = JSON.parse(decodeURIComponent(encoded)); - - if (Array.isArray(commands)) { - commands.forEach((c: EncodableCommad) => { - this.commandRegistry.executeCommand(c.id, c.args); - }); - } - } -} diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-commands.ts b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-commands.ts index c1f8bbd59..cf3a2dfbf 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-commands.ts +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-commands.ts @@ -5,12 +5,11 @@ export namespace SketchbookCommands { id: 'arduino-sketchbook-widget:toggle', }; - export const SHOW_SKETCHBOOK_WIDGET = Command.toLocalizedCommand( + export const REVEAL_SKETCH_NODE = Command.toLocalizedCommand( { - id: 'arduino-sketchbook--show-sketchbook-widget', - label: 'Show Sketchbook Widget', + id: 'arduino-sketchbook--reveal-sketch-node', }, - 'arduino/sketch/showSketchbookWidget' + 'arduino/sketch/revealSketchNode' ); export const OPEN_NEW_WINDOW = Command.toLocalizedCommand( diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts index 766ecd8b9..2c6ef0cf2 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts @@ -17,7 +17,6 @@ import { Navigatable, RenderContextMenuOptions, SelectableTreeNode, - TreeNode, Widget, } from '@theia/core/lib/browser'; import { @@ -30,9 +29,7 @@ import { } from '../../../common/protocol/sketches-service-client-impl'; import { FileService } from '@theia/filesystem/lib/browser/file-service'; import { URI } from '../../contributions/contribution'; -import { SketchControl } from '../../contributions/sketch-control'; -import { SketchbookTreeWidget } from './sketchbook-tree-widget'; -import { EncodableCommad } from './encoded-commands-contribution'; +import { WorkspaceInput } from '@theia/workspace/lib/browser'; export const SKETCHBOOK__CONTEXT = ['arduino-sketchbook--context']; @@ -71,9 +68,6 @@ export class SketchbookWidgetContribution @inject(FileService) protected readonly fileService: FileService; - @inject(SketchControl) - protected readonly sketchControl: SketchControl; - protected readonly toDisposeBeforeNewContextMenu = new DisposableCollection(); constructor() { @@ -107,12 +101,32 @@ export class SketchbookWidgetContribution override registerCommands(registry: CommandRegistry): void { super.registerCommands(registry); - registry.registerCommand(SketchbookCommands.SHOW_SKETCHBOOK_WIDGET, { - execute: (treeWidget: SketchbookTreeWidget, node: TreeNode) => - this.showSketchbookWidget(treeWidget, node), + registry.registerCommand(SketchbookCommands.REVEAL_SKETCH_NODE, { + execute: (treeWidgetId: string, nodeId: string) => + this.revealSketchNode(treeWidgetId, nodeId), }); registry.registerCommand(SketchbookCommands.OPEN_NEW_WINDOW, { - execute: (arg) => this.openSketchInNewWindow(arg), + execute: (arg) => { + const widget = this.tryGetWidget(); + if (widget) { + const treeWidgetId = widget.activeTreeWidgetId(); + if (!treeWidgetId) { + console.warn(`Could not retrieve active sketchbook tree ID.`); + return; + } + const nodeId = arg.node.id; + const options: WorkspaceInput = {}; + Object.assign(options, { + tasks: [ + { + command: SketchbookCommands.REVEAL_SKETCH_NODE.id, + args: [treeWidgetId, nodeId], + }, + ], + }); + return this.workspaceService.open(arg.node.uri, options); + } + }, isEnabled: (arg) => !!arg && 'node' in arg && SketchbookTree.SketchDirNode.is(arg.node), isVisible: (arg) => @@ -200,19 +214,6 @@ export class SketchbookWidgetContribution }); } - async openSketchInNewWindow(arg: any): Promise { - const treeWidget: SketchbookTreeWidget = ( - await this.widget - ).getTreeWidget(); - const command: EncodableCommad = { - id: SketchbookCommands.SHOW_SKETCHBOOK_WIDGET.id, - args: [treeWidget, arg.node], - }; - return this.workspaceService.openWithCommands(arg.node.uri, { - commands: [command], - }); - } - override registerMenus(registry: MenuModelRegistry): void { super.registerMenus(registry); @@ -252,19 +253,15 @@ export class SketchbookWidgetContribution this.selectWidgetFileNode(this.shell.currentWidget); } - protected async showSketchbookWidget( - treeWidget: SketchbookTreeWidget, - node: TreeNode + private async revealSketchNode( + treeWidgetId: string, + nodeId: string ): Promise { - this.widget + return this.widget .then((widget) => this.shell.activateWidget(widget.id)) .then((widget) => { if (widget instanceof SketchbookWidget) { - widget.activateTreeWidget(treeWidget.id); - if (SelectableTreeNode.is(node)) { - const { model } = treeWidget; - model.selectNode(node); - } + return widget.revealSketchNode(treeWidgetId, nodeId); } }); } diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx index a263b163e..2fd68fc75 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx @@ -11,6 +11,8 @@ import { Disposable } from '@theia/core/lib/common/disposable'; import { BaseWidget } from '@theia/core/lib/browser/widgets/widget'; import { SketchbookTreeWidget } from './sketchbook-tree-widget'; import { nls } from '@theia/core/lib/common'; +import { SelectableTreeNode, TreeWidget } from '@theia/core/lib/browser'; +import { CloudSketchbookCompositeWidget } from '../cloud-sketchbook/cloud-sketchbook-composite-widget'; @injectable() export class SketchbookWidget extends BaseWidget { @@ -49,14 +51,58 @@ export class SketchbookWidget extends BaseWidget { return this.localSketchbookTreeWidget; } - activateTreeWidget(treeWidgetId: string): boolean { - for (const widget of toArray(this.sketchbookTreesContainer.widgets())) { - if (widget.id === treeWidgetId) { - this.sketchbookTreesContainer.activateWidget(widget); - return true; - } + activeTreeWidgetId(): string | undefined { + const selectedTreeWidgets = toArray( + this.sketchbookTreesContainer.selectedWidgets() + ).map(({ id }) => id); + if (selectedTreeWidgets.length > 1) { + console.warn( + `Found multiple selected tree widgets: ${JSON.stringify( + selectedTreeWidgets + )}. Expected only one.` + ); + } + return selectedTreeWidgets.shift(); + } + + async revealSketchNode(treeWidgetId: string, nodeId: string): Promise { + const widget = toArray(this.sketchbookTreesContainer.widgets()) + .filter(({ id }) => id === treeWidgetId) + .shift(); + if (!widget) { + console.warn(`Could not find tree widget with ID: ${widget}`); + return; + } + const treeWidget = this.treeWidget( + toArray(this.sketchbookTreesContainer.widgets()) + .filter(({ id }) => id === treeWidgetId) + .shift() + ); + if (!treeWidget) { + console.warn(`Could not find tree widget with ID: ${treeWidget}`); + return; + } + this.sketchbookTreesContainer.activateWidget(widget); + const treeNode = treeWidget.model.getNode(nodeId); + if (!treeNode) { + console.warn(`Could not find tree node with ID: ${nodeId}`); + return; + } + if (!SelectableTreeNode.is(treeNode)) { + console.warn(`Tree node ${treeNode.id} is not selectable.`); + return; + } + treeWidget.model.selectNode(treeNode); + } + + private treeWidget(widget: Widget | undefined): TreeWidget | undefined { + if (widget instanceof TreeWidget) { + return widget; + } + if (widget instanceof CloudSketchbookCompositeWidget) { + return widget.getTreeWidget(); } - return false; + return undefined; } protected override onActivateRequest(message: Message): void { diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/startup-task.ts b/arduino-ide-extension/src/browser/widgets/sketchbook/startup-task.ts new file mode 100644 index 000000000..47ab60dbc --- /dev/null +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/startup-task.ts @@ -0,0 +1,42 @@ +import { injectable } from '@theia/core/shared/inversify'; +import { WorkspaceInput as TheiaWorkspaceInput } from '@theia/workspace/lib/browser'; +import { Contribution } from '../../contributions/contribution'; + +export interface Task { + command: string; + /** + * This must be JSON serializable. + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + args?: any[]; +} + +@injectable() +export class StartupTask extends Contribution { + override onReady(): void { + const params = new URLSearchParams(window.location.search); + const encoded = params.get(StartupTask.QUERY_STRING); + if (!encoded) return; + + const commands = JSON.parse(decodeURIComponent(encoded)); + + if (Array.isArray(commands)) { + commands.forEach(({ command, args }) => { + this.commandService.executeCommand(command, ...args); + }); + } + } +} +export namespace StartupTask { + export const QUERY_STRING = 'startupTasks'; + export interface WorkspaceInput extends TheiaWorkspaceInput { + tasks: Task[]; + } + export namespace WorkspaceInput { + export function is( + input: (TheiaWorkspaceInput & Partial) | undefined + ): input is WorkspaceInput { + return !!input && !!input.tasks; + } + } +} From bd6268030550886047763200477145ccb33c5f8c Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Thu, 30 Jun 2022 12:09:19 +0200 Subject: [PATCH 09/13] i18n fixup. Signed-off-by: Akos Kitta --- .../cloud-sketchbook/cloud-sketchbook-contributions.ts | 8 -------- .../browser/widgets/sketchbook/sketchbook-commands.ts | 9 +++------ 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-contributions.ts b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-contributions.ts index 13a840b7f..54594b2dc 100644 --- a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-contributions.ts +++ b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-contributions.ts @@ -64,14 +64,6 @@ export namespace CloudSketchbookCommands { } } - export const SHOW_CLOUD_SKETCHBOOK_WIDGET = Command.toLocalizedCommand( - { - id: 'arduino-cloud-sketchbook--show-cloud-sketchbook-widget', - label: 'Show Cloud Sketchbook Widget', - }, - 'arduino/sketch/showCloudSketchbookWidget' - ); - export const TOGGLE_CLOUD_SKETCHBOOK = Command.toLocalizedCommand( { id: 'arduino-cloud-sketchbook--disable', diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-commands.ts b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-commands.ts index cf3a2dfbf..50b5f9008 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-commands.ts +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-commands.ts @@ -5,12 +5,9 @@ export namespace SketchbookCommands { id: 'arduino-sketchbook-widget:toggle', }; - export const REVEAL_SKETCH_NODE = Command.toLocalizedCommand( - { - id: 'arduino-sketchbook--reveal-sketch-node', - }, - 'arduino/sketch/revealSketchNode' - ); + export const REVEAL_SKETCH_NODE: Command = { + id: 'arduino-sketchbook--reveal-sketch-node', + }; export const OPEN_NEW_WINDOW = Command.toLocalizedCommand( { From 6b4e00d9faf1e6f2b8fc264646a3e523cf371892 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Thu, 30 Jun 2022 12:11:05 +0200 Subject: [PATCH 10/13] minimized scope of hacky code. Signed-off-by: Akos Kitta --- .../widgets/sketchbook/sketchbook-widget.tsx | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx index 2fd68fc75..e0711d7c1 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx @@ -73,7 +73,19 @@ export class SketchbookWidget extends BaseWidget { console.warn(`Could not find tree widget with ID: ${widget}`); return; } - const treeWidget = this.treeWidget( + // TODO: remove this when the remote/local sketchbooks and their widgets are cleaned up. + const findTreeWidget = ( + widget: Widget | undefined + ): TreeWidget | undefined => { + if (widget instanceof TreeWidget) { + return widget; + } + if (widget instanceof CloudSketchbookCompositeWidget) { + return widget.getTreeWidget(); + } + return undefined; + }; + const treeWidget = findTreeWidget( toArray(this.sketchbookTreesContainer.widgets()) .filter(({ id }) => id === treeWidgetId) .shift() @@ -95,16 +107,6 @@ export class SketchbookWidget extends BaseWidget { treeWidget.model.selectNode(treeNode); } - private treeWidget(widget: Widget | undefined): TreeWidget | undefined { - if (widget instanceof TreeWidget) { - return widget; - } - if (widget instanceof CloudSketchbookCompositeWidget) { - return widget.getTreeWidget(); - } - return undefined; - } - protected override onActivateRequest(message: Message): void { super.onActivateRequest(message); From 309b13799381a90d6990ac2e498839c3c9fa75f7 Mon Sep 17 00:00:00 2001 From: Alberto Iannaccone Date: Thu, 30 Jun 2022 13:05:40 +0200 Subject: [PATCH 11/13] clean up OPEN_NEW_WINDOW command --- .../sketchbook-widget-contribution.ts | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts index 2c6ef0cf2..7e9fdc8bc 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts @@ -106,27 +106,7 @@ export class SketchbookWidgetContribution this.revealSketchNode(treeWidgetId, nodeId), }); registry.registerCommand(SketchbookCommands.OPEN_NEW_WINDOW, { - execute: (arg) => { - const widget = this.tryGetWidget(); - if (widget) { - const treeWidgetId = widget.activeTreeWidgetId(); - if (!treeWidgetId) { - console.warn(`Could not retrieve active sketchbook tree ID.`); - return; - } - const nodeId = arg.node.id; - const options: WorkspaceInput = {}; - Object.assign(options, { - tasks: [ - { - command: SketchbookCommands.REVEAL_SKETCH_NODE.id, - args: [treeWidgetId, nodeId], - }, - ], - }); - return this.workspaceService.open(arg.node.uri, options); - } - }, + execute: (arg) => this.openNewWindow(arg.node), isEnabled: (arg) => !!arg && 'node' in arg && SketchbookTree.SketchDirNode.is(arg.node), isVisible: (arg) => @@ -229,6 +209,28 @@ export class SketchbookWidgetContribution }); } + private openNewWindow(node: SketchbookTree.SketchDirNode): void { + const widget = this.tryGetWidget(); + if (widget) { + const treeWidgetId = widget.activeTreeWidgetId(); + if (!treeWidgetId) { + console.warn(`Could not retrieve active sketchbook tree ID.`); + return; + } + const nodeId = node.id; + const options: WorkspaceInput = {}; + Object.assign(options, { + tasks: [ + { + command: SketchbookCommands.REVEAL_SKETCH_NODE.id, + args: [treeWidgetId, nodeId], + }, + ], + }); + return this.workspaceService.open(node.uri, options); + } + } + /** * Reveals and selects node in the file navigator to which given widget is related. * Does nothing if given widget undefined or doesn't have related resource. From ebc63e83a57f5eafa986753e587951fec42307cd Mon Sep 17 00:00:00 2001 From: Alberto Iannaccone Date: Thu, 30 Jun 2022 13:16:15 +0200 Subject: [PATCH 12/13] add comment on workspace-service.ts --- .../src/browser/theia/workspace/workspace-service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts b/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts index f51479b28..3ba955c7c 100644 --- a/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts +++ b/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts @@ -113,7 +113,7 @@ export class WorkspaceService extends TheiaWorkspaceService { if (preserveWindow) { this._workspace = stat; } - this.openWindow(stat, Object.assign(options ?? {}, { preserveWindow })); + this.openWindow(stat, Object.assign(options ?? {}, { preserveWindow })); // Unlike Theia, IDE2 passes the whole `input` downstream and not only { preserveWindow } return; } throw new Error( From 80594de744d8139bd216400d4510d632e1787b2e Mon Sep 17 00:00:00 2001 From: Alberto Iannaccone Date: Mon, 4 Jul 2022 09:20:38 +0200 Subject: [PATCH 13/13] reveal node with URI --- .../sketchbook-widget-contribution.ts | 12 ++++++------ .../widgets/sketchbook/sketchbook-widget.tsx | 19 +++++++------------ 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts index 7e9fdc8bc..74b782887 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts @@ -102,8 +102,8 @@ export class SketchbookWidgetContribution override registerCommands(registry: CommandRegistry): void { super.registerCommands(registry); registry.registerCommand(SketchbookCommands.REVEAL_SKETCH_NODE, { - execute: (treeWidgetId: string, nodeId: string) => - this.revealSketchNode(treeWidgetId, nodeId), + execute: (treeWidgetId: string, nodeUri: string) => + this.revealSketchNode(treeWidgetId, nodeUri), }); registry.registerCommand(SketchbookCommands.OPEN_NEW_WINDOW, { execute: (arg) => this.openNewWindow(arg.node), @@ -217,13 +217,13 @@ export class SketchbookWidgetContribution console.warn(`Could not retrieve active sketchbook tree ID.`); return; } - const nodeId = node.id; + const nodeUri = node.uri.toString(); const options: WorkspaceInput = {}; Object.assign(options, { tasks: [ { command: SketchbookCommands.REVEAL_SKETCH_NODE.id, - args: [treeWidgetId, nodeId], + args: [treeWidgetId, nodeUri], }, ], }); @@ -257,13 +257,13 @@ export class SketchbookWidgetContribution private async revealSketchNode( treeWidgetId: string, - nodeId: string + nodeUIri: string ): Promise { return this.widget .then((widget) => this.shell.activateWidget(widget.id)) .then((widget) => { if (widget instanceof SketchbookWidget) { - return widget.revealSketchNode(treeWidgetId, nodeId); + return widget.revealSketchNode(treeWidgetId, nodeUIri); } }); } diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx index e0711d7c1..0b7b920a1 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx @@ -11,8 +11,8 @@ import { Disposable } from '@theia/core/lib/common/disposable'; import { BaseWidget } from '@theia/core/lib/browser/widgets/widget'; import { SketchbookTreeWidget } from './sketchbook-tree-widget'; import { nls } from '@theia/core/lib/common'; -import { SelectableTreeNode, TreeWidget } from '@theia/core/lib/browser'; import { CloudSketchbookCompositeWidget } from '../cloud-sketchbook/cloud-sketchbook-composite-widget'; +import { URI } from '../../contributions/contribution'; @injectable() export class SketchbookWidget extends BaseWidget { @@ -65,7 +65,7 @@ export class SketchbookWidget extends BaseWidget { return selectedTreeWidgets.shift(); } - async revealSketchNode(treeWidgetId: string, nodeId: string): Promise { + async revealSketchNode(treeWidgetId: string, nodeUri: string): Promise { const widget = toArray(this.sketchbookTreesContainer.widgets()) .filter(({ id }) => id === treeWidgetId) .shift(); @@ -76,8 +76,8 @@ export class SketchbookWidget extends BaseWidget { // TODO: remove this when the remote/local sketchbooks and their widgets are cleaned up. const findTreeWidget = ( widget: Widget | undefined - ): TreeWidget | undefined => { - if (widget instanceof TreeWidget) { + ): SketchbookTreeWidget | undefined => { + if (widget instanceof SketchbookTreeWidget) { return widget; } if (widget instanceof CloudSketchbookCompositeWidget) { @@ -95,16 +95,11 @@ export class SketchbookWidget extends BaseWidget { return; } this.sketchbookTreesContainer.activateWidget(widget); - const treeNode = treeWidget.model.getNode(nodeId); + + const treeNode = await treeWidget.model.revealFile(new URI(nodeUri)); if (!treeNode) { - console.warn(`Could not find tree node with ID: ${nodeId}`); - return; - } - if (!SelectableTreeNode.is(treeNode)) { - console.warn(`Tree node ${treeNode.id} is not selectable.`); - return; + console.warn(`Could not find tree node with URI: ${nodeUri}`); } - treeWidget.model.selectNode(treeNode); } protected override onActivateRequest(message: Message): void {