From afb3ef72ac15b5491d6468aa9af8985538796019 Mon Sep 17 00:00:00 2001 From: David Simpson <45690499+davegarthsimpson@users.noreply.github.com> Date: Thu, 11 Aug 2022 17:40:58 +0200 Subject: [PATCH 01/11] ensure auto-select doesn't select wrong port prevent auto-select of unattached boards Co-authored-by: Francesco Spissu --- .../browser/boards/boards-service-provider.ts | 111 +++++++++++++++++- .../browser/contributions/upload-sketch.ts | 6 + .../src/browser/notification-center.ts | 9 +- .../common/protocol/notification-service.ts | 1 + .../src/node/notification-service-server.ts | 4 + 5 files changed, 127 insertions(+), 4 deletions(-) diff --git a/arduino-ide-extension/src/browser/boards/boards-service-provider.ts b/arduino-ide-extension/src/browser/boards/boards-service-provider.ts index dc4e66834..226fbd33d 100644 --- a/arduino-ide-extension/src/browser/boards/boards-service-provider.ts +++ b/arduino-ide-extension/src/browser/boards/boards-service-provider.ts @@ -65,6 +65,13 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { protected _availablePorts: Port[] = []; protected _availableBoards: AvailableBoard[] = []; + private uploadInProgress = false; + + private lastItemRemovedForUpload: { board: Board; port: Port } | undefined; + // "lastPersistingUploadPort", is a port created during an upload, that persisted after + // the upload finished, it's "substituting" the port selected when the user invoked the upload + private lastPersistingUploadPort: Port | undefined; + /** * Unlike `onAttachedBoardsChanged` this even fires when the user modifies the selected board in the IDE.\ * This even also fires, when the boards package was not available for the currently selected board, @@ -80,6 +87,9 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { private readonly _reconciled = new Deferred(); onStart(): void { + this.notificationCenter.onUploadInProgress( + this.onUploadNotificationReceived.bind(this) + ); this.notificationCenter.onAttachedBoardsDidChange( this.notifyAttachedBoardsChanged.bind(this) ); @@ -111,6 +121,68 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { return this._reconciled.promise; } + private onUploadNotificationReceived(uploadInProgress: boolean): void { + this.uploadInProgress = uploadInProgress; + } + + private checkForItemRemoved(event: AttachedBoardsChangeEvent): void { + if (!this.lastItemRemovedForUpload) { + const { + oldState: { ports: oldPorts, boards: oldBoards }, + newState: { ports: newPorts }, + } = event; + + const disappearedPorts = oldPorts.filter((oldPort: Port) => + newPorts.every((newPort: Port) => !Port.sameAs(oldPort, newPort)) + ); + + if (disappearedPorts.length > 0) { + this.lastItemRemovedForUpload = { + board: oldBoards.find((board: Board) => + Port.sameAs(board.port, disappearedPorts[0]) + ) as Board, + port: disappearedPorts[0], + }; + } + + return; + } + } + + private checkForPersistingPort(event: AttachedBoardsChangeEvent): void { + if (this.lastItemRemovedForUpload) { + const { + oldState: { ports: oldPorts }, + newState: { ports: newPorts, boards: newBoards }, + } = event; + + const disappearedItem = this.lastItemRemovedForUpload; + this.lastItemRemovedForUpload = undefined; + + const appearedPorts = newPorts.filter((newPort: Port) => + oldPorts.every((oldPort: Port) => !Port.sameAs(newPort, oldPort)) + ); + + if (appearedPorts.length > 0) { + const boardOnAppearedPort = newBoards.find((board: Board) => + Port.sameAs(board.port, appearedPorts[0]) + ); + + if ( + boardOnAppearedPort && + Board.sameAs(boardOnAppearedPort, disappearedItem.board) + ) { + this.lastPersistingUploadPort = appearedPorts[0]; + return; + } + } + + return; + } + + this.lastPersistingUploadPort = undefined; + } + protected notifyAttachedBoardsChanged( event: AttachedBoardsChangeEvent ): void { @@ -119,10 +191,21 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { this.logger.info(AttachedBoardsChangeEvent.toString(event)); this.logger.info('------------------------------------------'); } + + if (this.uploadInProgress) { + this.checkForItemRemoved(event); + } else { + this.checkForPersistingPort(event); + } + this._attachedBoards = event.newState.boards; this._availablePorts = event.newState.ports; this.onAvailablePortsChangedEmitter.fire(this._availablePorts); - this.reconcileAvailableBoards().then(() => this.tryReconnect()); + this.reconcileAvailableBoards().then(() => { + if (!this.uploadInProgress) { + this.tryReconnect(); + } + }); } protected notifyPlatformInstalled(event: { item: BoardsPackage }): void { @@ -240,6 +323,21 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { } // If we could not find an exact match, we compare the board FQBN-name pairs and ignore the port, as it might have changed. // See documentation on `latestValidBoardsConfig`. + + if (!this.lastPersistingUploadPort) return false; + + const lastPersistingUploadPort = this.lastPersistingUploadPort; + this.lastPersistingUploadPort = undefined; + + if ( + !Port.sameAs( + lastPersistingUploadPort, + this.latestValidBoardsConfig.selectedPort + ) + ) { + return false; + } + for (const board of this.availableBoards.filter( ({ state }) => state !== AvailableBoard.State.incomplete )) { @@ -458,6 +556,11 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { const board = attachedBoards.find(({ port }) => Port.sameAs(boardPort, port) ); + // "board" will always be falsey for + // port that was originally mapped + // to unknown board and then selected + // manually by user + const lastSelectedBoard = await this.getLastSelectedBoardOnPort( boardPort ); @@ -476,7 +579,9 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { availableBoard = { ...lastSelectedBoard, state: AvailableBoard.State.guessed, - selected: BoardsConfig.Config.sameAs(boardsConfig, lastSelectedBoard), + selected: + BoardsConfig.Config.sameAs(boardsConfig, lastSelectedBoard) && + Port.sameAs(boardPort, boardsConfig.selectedPort), // to avoid double selection port: boardPort, }; } else { @@ -491,7 +596,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { if ( boardsConfig.selectedBoard && - !availableBoards.some(({ selected }) => selected) + availableBoards.every(({ selected }) => !selected) ) { // If the selected board has the same port of an unknown board // that is already in availableBoards we might get a duplicate port. diff --git a/arduino-ide-extension/src/browser/contributions/upload-sketch.ts b/arduino-ide-extension/src/browser/contributions/upload-sketch.ts index e15e612ad..ef1e318a2 100644 --- a/arduino-ide-extension/src/browser/contributions/upload-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/upload-sketch.ts @@ -15,6 +15,7 @@ import { UserFieldsDialog } from '../dialogs/user-fields/user-fields-dialog'; import { DisposableCollection, nls } from '@theia/core/lib/common'; import { CurrentSketch } from '../../common/protocol/sketches-service-client-impl'; import type { VerifySketchParams } from './verify-sketch'; +import { NotificationCenter } from '../notification-center'; @injectable() export class UploadSketch extends CoreServiceContribution { @@ -24,6 +25,9 @@ export class UploadSketch extends CoreServiceContribution { @inject(UserFieldsDialog) private readonly userFieldsDialog: UserFieldsDialog; + @inject(NotificationCenter) + private readonly notificationCenter: NotificationCenter; + private boardRequiresUserFields = false; private readonly cachedUserFields: Map = new Map(); private readonly menuActionsDisposables = new DisposableCollection(); @@ -191,6 +195,7 @@ export class UploadSketch extends CoreServiceContribution { // uploadInProgress will be set to false whether the upload fails or not this.uploadInProgress = true; this.onDidChangeEmitter.fire(); + this.notificationCenter.notifyUploadInProgress(this.uploadInProgress); const verifyOptions = await this.commandService.executeCommand( @@ -243,6 +248,7 @@ export class UploadSketch extends CoreServiceContribution { } finally { this.uploadInProgress = false; this.onDidChangeEmitter.fire(); + this.notificationCenter.notifyUploadInProgress(this.uploadInProgress); } } diff --git a/arduino-ide-extension/src/browser/notification-center.ts b/arduino-ide-extension/src/browser/notification-center.ts index b17853d0a..a67e42432 100644 --- a/arduino-ide-extension/src/browser/notification-center.ts +++ b/arduino-ide-extension/src/browser/notification-center.ts @@ -66,6 +66,7 @@ export class NotificationCenter }>(); private readonly onAppStateDidChangeEmitter = new Emitter(); + private readonly onUploadInProgressEmitter = new Emitter(); protected readonly toDispose = new DisposableCollection( this.indexWillUpdateEmitter, @@ -79,7 +80,8 @@ export class NotificationCenter this.platformDidUninstallEmitter, this.libraryDidInstallEmitter, this.libraryDidUninstallEmitter, - this.attachedBoardsDidChangeEmitter + this.attachedBoardsDidChangeEmitter, + this.onUploadInProgressEmitter ); readonly onIndexDidUpdate = this.indexDidUpdateEmitter.event; @@ -97,6 +99,7 @@ export class NotificationCenter this.attachedBoardsDidChangeEmitter.event; readonly onRecentSketchesDidChange = this.recentSketchesChangedEmitter.event; readonly onAppStateDidChange = this.onAppStateDidChangeEmitter.event; + readonly onUploadInProgress = this.onUploadInProgressEmitter.event; @postConstruct() protected init(): void { @@ -169,4 +172,8 @@ export class NotificationCenter notifyRecentSketchesDidChange(event: { sketches: Sketch[] }): void { this.recentSketchesChangedEmitter.fire(event); } + + notifyUploadInProgress(event: boolean): void { + this.onUploadInProgressEmitter.fire(event); + } } diff --git a/arduino-ide-extension/src/common/protocol/notification-service.ts b/arduino-ide-extension/src/common/protocol/notification-service.ts index e1b192ece..a703595fb 100644 --- a/arduino-ide-extension/src/common/protocol/notification-service.ts +++ b/arduino-ide-extension/src/common/protocol/notification-service.ts @@ -28,6 +28,7 @@ export interface NotificationServiceClient { notifyLibraryDidUninstall(event: { item: LibraryPackage }): void; notifyAttachedBoardsDidChange(event: AttachedBoardsChangeEvent): void; notifyRecentSketchesDidChange(event: { sketches: Sketch[] }): void; + notifyUploadInProgress(event: boolean): void; } export const NotificationServicePath = '/services/notification-service'; diff --git a/arduino-ide-extension/src/node/notification-service-server.ts b/arduino-ide-extension/src/node/notification-service-server.ts index 733edb336..0223242c9 100644 --- a/arduino-ide-extension/src/node/notification-service-server.ts +++ b/arduino-ide-extension/src/node/notification-service-server.ts @@ -82,6 +82,10 @@ export class NotificationServiceServerImpl ); } + notifyUploadInProgress(event: boolean): void { + this.clients.forEach((client) => client.notifyUploadInProgress(event)); + } + setClient(client: NotificationServiceClient): void { this.clients.push(client); } From 09534c64074fa497db192582fa788dae67142820 Mon Sep 17 00:00:00 2001 From: David Simpson <45690499+davegarthsimpson@users.noreply.github.com> Date: Tue, 16 Aug 2022 14:26:05 +0200 Subject: [PATCH 02/11] clean up --- .../src/browser/boards/boards-service-provider.ts | 14 +++++++------- .../src/browser/contributions/upload-sketch.ts | 8 ++++++-- .../src/browser/notification-center.ts | 11 ++++++----- .../src/common/protocol/notification-service.ts | 2 +- .../src/node/notification-service-server.ts | 6 ++++-- 5 files changed, 24 insertions(+), 17 deletions(-) diff --git a/arduino-ide-extension/src/browser/boards/boards-service-provider.ts b/arduino-ide-extension/src/browser/boards/boards-service-provider.ts index 226fbd33d..ef7106f82 100644 --- a/arduino-ide-extension/src/browser/boards/boards-service-provider.ts +++ b/arduino-ide-extension/src/browser/boards/boards-service-provider.ts @@ -65,7 +65,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { protected _availablePorts: Port[] = []; protected _availableBoards: AvailableBoard[] = []; - private uploadInProgress = false; + private uploadAttemptInProgress = false; private lastItemRemovedForUpload: { board: Board; port: Port } | undefined; // "lastPersistingUploadPort", is a port created during an upload, that persisted after @@ -87,8 +87,8 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { private readonly _reconciled = new Deferred(); onStart(): void { - this.notificationCenter.onUploadInProgress( - this.onUploadNotificationReceived.bind(this) + this.notificationCenter.onUploadAttemptInProgress( + this.onUploadAttemptEventReceived.bind(this) ); this.notificationCenter.onAttachedBoardsDidChange( this.notifyAttachedBoardsChanged.bind(this) @@ -121,8 +121,8 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { return this._reconciled.promise; } - private onUploadNotificationReceived(uploadInProgress: boolean): void { - this.uploadInProgress = uploadInProgress; + private onUploadAttemptEventReceived(uploadAttemptInProgress: boolean): void { + this.uploadAttemptInProgress = uploadAttemptInProgress; } private checkForItemRemoved(event: AttachedBoardsChangeEvent): void { @@ -192,7 +192,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { this.logger.info('------------------------------------------'); } - if (this.uploadInProgress) { + if (this.uploadAttemptInProgress) { this.checkForItemRemoved(event); } else { this.checkForPersistingPort(event); @@ -202,7 +202,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { this._availablePorts = event.newState.ports; this.onAvailablePortsChangedEmitter.fire(this._availablePorts); this.reconcileAvailableBoards().then(() => { - if (!this.uploadInProgress) { + if (!this.uploadAttemptInProgress) { this.tryReconnect(); } }); diff --git a/arduino-ide-extension/src/browser/contributions/upload-sketch.ts b/arduino-ide-extension/src/browser/contributions/upload-sketch.ts index a11740826..99fb1932e 100644 --- a/arduino-ide-extension/src/browser/contributions/upload-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/upload-sketch.ts @@ -195,8 +195,10 @@ export class UploadSketch extends CoreServiceContribution { // uploadInProgress will be set to false whether the upload fails or not this.uploadInProgress = true; this.onDidChangeEmitter.fire(); - this.notificationCenter.notifyUploadInProgress(this.uploadInProgress); this.clearVisibleNotification(); + this.notificationCenter.notifyUploadAttemptInProgress( + this.uploadInProgress + ); const verifyOptions = await this.commandService.executeCommand( @@ -249,7 +251,9 @@ export class UploadSketch extends CoreServiceContribution { } finally { this.uploadInProgress = false; this.onDidChangeEmitter.fire(); - this.notificationCenter.notifyUploadInProgress(this.uploadInProgress); + this.notificationCenter.notifyUploadAttemptInProgress( + this.uploadInProgress + ); } } diff --git a/arduino-ide-extension/src/browser/notification-center.ts b/arduino-ide-extension/src/browser/notification-center.ts index a67e42432..bd67fbb83 100644 --- a/arduino-ide-extension/src/browser/notification-center.ts +++ b/arduino-ide-extension/src/browser/notification-center.ts @@ -66,7 +66,7 @@ export class NotificationCenter }>(); private readonly onAppStateDidChangeEmitter = new Emitter(); - private readonly onUploadInProgressEmitter = new Emitter(); + private readonly onUploadAttemptInProgressEmitter = new Emitter(); protected readonly toDispose = new DisposableCollection( this.indexWillUpdateEmitter, @@ -81,7 +81,7 @@ export class NotificationCenter this.libraryDidInstallEmitter, this.libraryDidUninstallEmitter, this.attachedBoardsDidChangeEmitter, - this.onUploadInProgressEmitter + this.onUploadAttemptInProgressEmitter ); readonly onIndexDidUpdate = this.indexDidUpdateEmitter.event; @@ -99,7 +99,8 @@ export class NotificationCenter this.attachedBoardsDidChangeEmitter.event; readonly onRecentSketchesDidChange = this.recentSketchesChangedEmitter.event; readonly onAppStateDidChange = this.onAppStateDidChangeEmitter.event; - readonly onUploadInProgress = this.onUploadInProgressEmitter.event; + readonly onUploadAttemptInProgress = + this.onUploadAttemptInProgressEmitter.event; @postConstruct() protected init(): void { @@ -173,7 +174,7 @@ export class NotificationCenter this.recentSketchesChangedEmitter.fire(event); } - notifyUploadInProgress(event: boolean): void { - this.onUploadInProgressEmitter.fire(event); + notifyUploadAttemptInProgress(event: boolean): void { + this.onUploadAttemptInProgressEmitter.fire(event); } } diff --git a/arduino-ide-extension/src/common/protocol/notification-service.ts b/arduino-ide-extension/src/common/protocol/notification-service.ts index a703595fb..26da6e336 100644 --- a/arduino-ide-extension/src/common/protocol/notification-service.ts +++ b/arduino-ide-extension/src/common/protocol/notification-service.ts @@ -28,7 +28,7 @@ export interface NotificationServiceClient { notifyLibraryDidUninstall(event: { item: LibraryPackage }): void; notifyAttachedBoardsDidChange(event: AttachedBoardsChangeEvent): void; notifyRecentSketchesDidChange(event: { sketches: Sketch[] }): void; - notifyUploadInProgress(event: boolean): void; + notifyUploadAttemptInProgress(event: boolean): void; } export const NotificationServicePath = '/services/notification-service'; diff --git a/arduino-ide-extension/src/node/notification-service-server.ts b/arduino-ide-extension/src/node/notification-service-server.ts index 0223242c9..34555f69f 100644 --- a/arduino-ide-extension/src/node/notification-service-server.ts +++ b/arduino-ide-extension/src/node/notification-service-server.ts @@ -82,8 +82,10 @@ export class NotificationServiceServerImpl ); } - notifyUploadInProgress(event: boolean): void { - this.clients.forEach((client) => client.notifyUploadInProgress(event)); + notifyUploadAttemptInProgress(event: boolean): void { + this.clients.forEach((client) => + client.notifyUploadAttemptInProgress(event) + ); } setClient(client: NotificationServiceClient): void { From e9137f79663af52526bb873d35569e032b45ab59 Mon Sep 17 00:00:00 2001 From: David Simpson <45690499+davegarthsimpson@users.noreply.github.com> Date: Tue, 16 Aug 2022 16:29:27 +0200 Subject: [PATCH 03/11] add "uploadInProgress" prop to boards change event --- .../src/browser/boards/boards-service-provider.ts | 15 ++++----------- .../src/browser/notification-center.ts | 10 +--------- .../src/common/protocol/boards-service.ts | 1 + .../src/common/protocol/notification-service.ts | 1 - arduino-ide-extension/src/node/board-discovery.ts | 7 +++++++ .../src/node/core-service-impl.ts | 6 ++++++ 6 files changed, 19 insertions(+), 21 deletions(-) diff --git a/arduino-ide-extension/src/browser/boards/boards-service-provider.ts b/arduino-ide-extension/src/browser/boards/boards-service-provider.ts index ef7106f82..bfaa17005 100644 --- a/arduino-ide-extension/src/browser/boards/boards-service-provider.ts +++ b/arduino-ide-extension/src/browser/boards/boards-service-provider.ts @@ -65,8 +65,6 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { protected _availablePorts: Port[] = []; protected _availableBoards: AvailableBoard[] = []; - private uploadAttemptInProgress = false; - private lastItemRemovedForUpload: { board: Board; port: Port } | undefined; // "lastPersistingUploadPort", is a port created during an upload, that persisted after // the upload finished, it's "substituting" the port selected when the user invoked the upload @@ -87,9 +85,6 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { private readonly _reconciled = new Deferred(); onStart(): void { - this.notificationCenter.onUploadAttemptInProgress( - this.onUploadAttemptEventReceived.bind(this) - ); this.notificationCenter.onAttachedBoardsDidChange( this.notifyAttachedBoardsChanged.bind(this) ); @@ -121,10 +116,6 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { return this._reconciled.promise; } - private onUploadAttemptEventReceived(uploadAttemptInProgress: boolean): void { - this.uploadAttemptInProgress = uploadAttemptInProgress; - } - private checkForItemRemoved(event: AttachedBoardsChangeEvent): void { if (!this.lastItemRemovedForUpload) { const { @@ -192,7 +183,9 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { this.logger.info('------------------------------------------'); } - if (this.uploadAttemptInProgress) { + const { uploadInProgress } = event; + + if (uploadInProgress) { this.checkForItemRemoved(event); } else { this.checkForPersistingPort(event); @@ -202,7 +195,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { this._availablePorts = event.newState.ports; this.onAvailablePortsChangedEmitter.fire(this._availablePorts); this.reconcileAvailableBoards().then(() => { - if (!this.uploadAttemptInProgress) { + if (!uploadInProgress) { this.tryReconnect(); } }); diff --git a/arduino-ide-extension/src/browser/notification-center.ts b/arduino-ide-extension/src/browser/notification-center.ts index bd67fbb83..b17853d0a 100644 --- a/arduino-ide-extension/src/browser/notification-center.ts +++ b/arduino-ide-extension/src/browser/notification-center.ts @@ -66,7 +66,6 @@ export class NotificationCenter }>(); private readonly onAppStateDidChangeEmitter = new Emitter(); - private readonly onUploadAttemptInProgressEmitter = new Emitter(); protected readonly toDispose = new DisposableCollection( this.indexWillUpdateEmitter, @@ -80,8 +79,7 @@ export class NotificationCenter this.platformDidUninstallEmitter, this.libraryDidInstallEmitter, this.libraryDidUninstallEmitter, - this.attachedBoardsDidChangeEmitter, - this.onUploadAttemptInProgressEmitter + this.attachedBoardsDidChangeEmitter ); readonly onIndexDidUpdate = this.indexDidUpdateEmitter.event; @@ -99,8 +97,6 @@ export class NotificationCenter this.attachedBoardsDidChangeEmitter.event; readonly onRecentSketchesDidChange = this.recentSketchesChangedEmitter.event; readonly onAppStateDidChange = this.onAppStateDidChangeEmitter.event; - readonly onUploadAttemptInProgress = - this.onUploadAttemptInProgressEmitter.event; @postConstruct() protected init(): void { @@ -173,8 +169,4 @@ export class NotificationCenter notifyRecentSketchesDidChange(event: { sketches: Sketch[] }): void { this.recentSketchesChangedEmitter.fire(event); } - - notifyUploadAttemptInProgress(event: boolean): void { - this.onUploadAttemptInProgressEmitter.fire(event); - } } diff --git a/arduino-ide-extension/src/common/protocol/boards-service.ts b/arduino-ide-extension/src/common/protocol/boards-service.ts index 41809626f..8d5c57944 100644 --- a/arduino-ide-extension/src/common/protocol/boards-service.ts +++ b/arduino-ide-extension/src/common/protocol/boards-service.ts @@ -25,6 +25,7 @@ export namespace AvailablePorts { export interface AttachedBoardsChangeEvent { readonly oldState: Readonly<{ boards: Board[]; ports: Port[] }>; readonly newState: Readonly<{ boards: Board[]; ports: Port[] }>; + readonly uploadInProgress: boolean; } export namespace AttachedBoardsChangeEvent { export function isEmpty(event: AttachedBoardsChangeEvent): boolean { diff --git a/arduino-ide-extension/src/common/protocol/notification-service.ts b/arduino-ide-extension/src/common/protocol/notification-service.ts index 26da6e336..e1b192ece 100644 --- a/arduino-ide-extension/src/common/protocol/notification-service.ts +++ b/arduino-ide-extension/src/common/protocol/notification-service.ts @@ -28,7 +28,6 @@ export interface NotificationServiceClient { notifyLibraryDidUninstall(event: { item: LibraryPackage }): void; notifyAttachedBoardsDidChange(event: AttachedBoardsChangeEvent): void; notifyRecentSketchesDidChange(event: { sketches: Sketch[] }): void; - notifyUploadAttemptInProgress(event: boolean): void; } export const NotificationServicePath = '/services/notification-service'; diff --git a/arduino-ide-extension/src/node/board-discovery.ts b/arduino-ide-extension/src/node/board-discovery.ts index 448d48e42..361749a54 100644 --- a/arduino-ide-extension/src/node/board-discovery.ts +++ b/arduino-ide-extension/src/node/board-discovery.ts @@ -54,6 +54,8 @@ export class BoardDiscovery private readonly onStreamDidCancelEmitter = new Emitter(); // when the watcher is canceled by the IDE2 private readonly toDisposeOnStopWatch = new DisposableCollection(); + private uploadInProgress = false; + /** * Keys are the `address` of the ports. * @@ -123,6 +125,10 @@ export class BoardDiscovery }); } + public setUploadInProgress(uploadAttemptInProgress: boolean): void { + this.uploadInProgress = uploadAttemptInProgress; + } + private createTimeout( after: number, onTimeout: (error: Error) => void @@ -318,6 +324,7 @@ export class BoardDiscovery ports: newAvailablePorts, boards: newAttachedBoards, }, + uploadInProgress: this.uploadInProgress, }; this._availablePorts = newState; diff --git a/arduino-ide-extension/src/node/core-service-impl.ts b/arduino-ide-extension/src/node/core-service-impl.ts index e556048ce..7034a279f 100644 --- a/arduino-ide-extension/src/node/core-service-impl.ts +++ b/arduino-ide-extension/src/node/core-service-impl.ts @@ -34,6 +34,7 @@ import { Instance } from './cli-protocol/cc/arduino/cli/commands/v1/common_pb'; import { firstToUpperCase, notEmpty } from '../common/utils'; import { ServiceError } from './service-error'; import { ExecuteWithProgress, ProgressResponse } from './grpc-progressible'; +import { BoardDiscovery } from './board-discovery'; namespace Uploadable { export type Request = UploadRequest | UploadUsingProgrammerRequest; @@ -51,6 +52,9 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { @inject(CommandService) private readonly commandService: CommandService; + @inject(BoardDiscovery) + protected readonly boardDiscovery: BoardDiscovery; + async compile(options: CoreService.Options.Compile): Promise { const coreClient = await this.coreClient; const { client, instance } = coreClient; @@ -378,6 +382,7 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { fqbn?: string | undefined; port?: Port | undefined; }): Promise { + this.boardDiscovery.setUploadInProgress(true); return this.monitorManager.notifyUploadStarted(fqbn, port); } @@ -388,6 +393,7 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { fqbn?: string | undefined; port?: Port | undefined; }): Promise { + this.boardDiscovery.setUploadInProgress(false); return this.monitorManager.notifyUploadFinished(fqbn, port); } From b15603cce703c7087001bd0dc2039d86473e1d16 Mon Sep 17 00:00:00 2001 From: David Simpson <45690499+davegarthsimpson@users.noreply.github.com> Date: Tue, 16 Aug 2022 16:39:59 +0200 Subject: [PATCH 04/11] remove unused methods and deps --- .../src/browser/contributions/upload-sketch.ts | 10 ---------- .../src/node/notification-service-server.ts | 6 ------ 2 files changed, 16 deletions(-) diff --git a/arduino-ide-extension/src/browser/contributions/upload-sketch.ts b/arduino-ide-extension/src/browser/contributions/upload-sketch.ts index 99fb1932e..d4bad139f 100644 --- a/arduino-ide-extension/src/browser/contributions/upload-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/upload-sketch.ts @@ -15,7 +15,6 @@ import { UserFieldsDialog } from '../dialogs/user-fields/user-fields-dialog'; import { DisposableCollection, nls } from '@theia/core/lib/common'; import { CurrentSketch } from '../../common/protocol/sketches-service-client-impl'; import type { VerifySketchParams } from './verify-sketch'; -import { NotificationCenter } from '../notification-center'; @injectable() export class UploadSketch extends CoreServiceContribution { @@ -25,9 +24,6 @@ export class UploadSketch extends CoreServiceContribution { @inject(UserFieldsDialog) private readonly userFieldsDialog: UserFieldsDialog; - @inject(NotificationCenter) - private readonly notificationCenter: NotificationCenter; - private boardRequiresUserFields = false; private readonly cachedUserFields: Map = new Map(); private readonly menuActionsDisposables = new DisposableCollection(); @@ -196,9 +192,6 @@ export class UploadSketch extends CoreServiceContribution { this.uploadInProgress = true; this.onDidChangeEmitter.fire(); this.clearVisibleNotification(); - this.notificationCenter.notifyUploadAttemptInProgress( - this.uploadInProgress - ); const verifyOptions = await this.commandService.executeCommand( @@ -251,9 +244,6 @@ export class UploadSketch extends CoreServiceContribution { } finally { this.uploadInProgress = false; this.onDidChangeEmitter.fire(); - this.notificationCenter.notifyUploadAttemptInProgress( - this.uploadInProgress - ); } } diff --git a/arduino-ide-extension/src/node/notification-service-server.ts b/arduino-ide-extension/src/node/notification-service-server.ts index 34555f69f..733edb336 100644 --- a/arduino-ide-extension/src/node/notification-service-server.ts +++ b/arduino-ide-extension/src/node/notification-service-server.ts @@ -82,12 +82,6 @@ export class NotificationServiceServerImpl ); } - notifyUploadAttemptInProgress(event: boolean): void { - this.clients.forEach((client) => - client.notifyUploadAttemptInProgress(event) - ); - } - setClient(client: NotificationServiceClient): void { this.clients.push(client); } From b7b155ca1b5487f79f07359d059658e00a043edc Mon Sep 17 00:00:00 2001 From: David Simpson <45690499+davegarthsimpson@users.noreply.github.com> Date: Mon, 22 Aug 2022 18:42:46 +0200 Subject: [PATCH 05/11] [WIP]: leverage upload event to derived new port --- .../browser/boards/boards-service-provider.ts | 126 +++++++----------- .../browser/contributions/upload-sketch.ts | 3 + 2 files changed, 50 insertions(+), 79 deletions(-) diff --git a/arduino-ide-extension/src/browser/boards/boards-service-provider.ts b/arduino-ide-extension/src/browser/boards/boards-service-provider.ts index bfaa17005..893510022 100644 --- a/arduino-ide-extension/src/browser/boards/boards-service-provider.ts +++ b/arduino-ide-extension/src/browser/boards/boards-service-provider.ts @@ -65,10 +65,10 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { protected _availablePorts: Port[] = []; protected _availableBoards: AvailableBoard[] = []; - private lastItemRemovedForUpload: { board: Board; port: Port } | undefined; + private lastBoardsConfigOnUpload: BoardsConfig.Config | undefined; // "lastPersistingUploadPort", is a port created during an upload, that persisted after // the upload finished, it's "substituting" the port selected when the user invoked the upload - private lastPersistingUploadPort: Port | undefined; + private lastPersistingUploadPortWithBoard: BoardsConfig.Config | undefined; /** * Unlike `onAttachedBoardsChanged` this even fires when the user modifies the selected board in the IDE.\ @@ -116,62 +116,57 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { return this._reconciled.promise; } - private checkForItemRemoved(event: AttachedBoardsChangeEvent): void { - if (!this.lastItemRemovedForUpload) { - const { - oldState: { ports: oldPorts, boards: oldBoards }, - newState: { ports: newPorts }, - } = event; + public setLastBoardsConfigOnUpload( + value: BoardsConfig.Config | undefined + ): void { + this.lastBoardsConfigOnUpload = value; + } - const disappearedPorts = oldPorts.filter((oldPort: Port) => - newPorts.every((newPort: Port) => !Port.sameAs(oldPort, newPort)) - ); + private derivePersistingUploadPort(event: AttachedBoardsChangeEvent): void { + if (!this.lastBoardsConfigOnUpload) { + this.lastPersistingUploadPortWithBoard = undefined; + return; + } - if (disappearedPorts.length > 0) { - this.lastItemRemovedForUpload = { - board: oldBoards.find((board: Board) => - Port.sameAs(board.port, disappearedPorts[0]) - ) as Board, - port: disappearedPorts[0], - }; - } + const { + oldState: { ports: oldPorts }, + newState: { ports: newPorts, boards: newBoards }, + } = event; + if (newPorts.length === 0) { + setTimeout(() => { + this.setLastBoardsConfigOnUpload(undefined); + }, 5000); return; } - } - private checkForPersistingPort(event: AttachedBoardsChangeEvent): void { - if (this.lastItemRemovedForUpload) { - const { - oldState: { ports: oldPorts }, - newState: { ports: newPorts, boards: newBoards }, - } = event; + const lastSelectionOnUpload = this.lastBoardsConfigOnUpload; + this.setLastBoardsConfigOnUpload(undefined); - const disappearedItem = this.lastItemRemovedForUpload; - this.lastItemRemovedForUpload = undefined; + const appearedPorts = + oldPorts.length > 0 + ? newPorts.filter((newPort: Port) => + oldPorts.every((oldPort: Port) => !Port.sameAs(newPort, oldPort)) + ) + : newPorts; - const appearedPorts = newPorts.filter((newPort: Port) => - oldPorts.every((oldPort: Port) => !Port.sameAs(newPort, oldPort)) + if (appearedPorts.length > 0) { + const boardOnAppearedPort = newBoards.find((board: Board) => + Port.sameAs(board.port, appearedPorts[0]) ); - if (appearedPorts.length > 0) { - const boardOnAppearedPort = newBoards.find((board: Board) => - Port.sameAs(board.port, appearedPorts[0]) - ); - - if ( - boardOnAppearedPort && - Board.sameAs(boardOnAppearedPort, disappearedItem.board) - ) { - this.lastPersistingUploadPort = appearedPorts[0]; - return; - } + if ( + boardOnAppearedPort && + lastSelectionOnUpload.selectedBoard && + Board.sameAs(boardOnAppearedPort, lastSelectionOnUpload.selectedBoard) + ) { + this.lastPersistingUploadPortWithBoard = { + selectedBoard: boardOnAppearedPort, + selectedPort: appearedPorts[0], + }; + return; } - - return; } - - this.lastPersistingUploadPort = undefined; } protected notifyAttachedBoardsChanged( @@ -185,10 +180,8 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { const { uploadInProgress } = event; - if (uploadInProgress) { - this.checkForItemRemoved(event); - } else { - this.checkForPersistingPort(event); + if (!uploadInProgress) { + this.derivePersistingUploadPort(event); } this._attachedBoards = event.newState.boards; @@ -317,36 +310,11 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { // If we could not find an exact match, we compare the board FQBN-name pairs and ignore the port, as it might have changed. // See documentation on `latestValidBoardsConfig`. - if (!this.lastPersistingUploadPort) return false; - - const lastPersistingUploadPort = this.lastPersistingUploadPort; - this.lastPersistingUploadPort = undefined; + if (!this.lastPersistingUploadPortWithBoard) return false; - if ( - !Port.sameAs( - lastPersistingUploadPort, - this.latestValidBoardsConfig.selectedPort - ) - ) { - return false; - } - - 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 && - this.latestValidBoardsConfig.selectedPort.protocol === - board.port?.protocol - ) { - this.boardsConfig = { - ...this.latestValidBoardsConfig, - selectedPort: board.port, - }; - return true; - } - } + this.boardsConfig = this.lastPersistingUploadPortWithBoard; + this.lastPersistingUploadPortWithBoard = undefined; + return true; } return false; } diff --git a/arduino-ide-extension/src/browser/contributions/upload-sketch.ts b/arduino-ide-extension/src/browser/contributions/upload-sketch.ts index d4bad139f..3dc915dee 100644 --- a/arduino-ide-extension/src/browser/contributions/upload-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/upload-sketch.ts @@ -190,6 +190,9 @@ export class UploadSketch extends CoreServiceContribution { // toggle the toolbar button and menu item state. // uploadInProgress will be set to false whether the upload fails or not this.uploadInProgress = true; + this.boardsServiceProvider.setLastBoardsConfigOnUpload( + this.boardsServiceProvider.boardsConfig + ); this.onDidChangeEmitter.fire(); this.clearVisibleNotification(); From bbeabd9b3096816716ba99746ebefe9317df5b3f Mon Sep 17 00:00:00 2001 From: David Simpson <45690499+davegarthsimpson@users.noreply.github.com> Date: Mon, 22 Aug 2022 20:40:11 +0200 Subject: [PATCH 06/11] remove timeout --- .../src/browser/boards/boards-service-provider.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arduino-ide-extension/src/browser/boards/boards-service-provider.ts b/arduino-ide-extension/src/browser/boards/boards-service-provider.ts index 893510022..24e06074e 100644 --- a/arduino-ide-extension/src/browser/boards/boards-service-provider.ts +++ b/arduino-ide-extension/src/browser/boards/boards-service-provider.ts @@ -129,17 +129,17 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { } const { - oldState: { ports: oldPorts }, - newState: { ports: newPorts, boards: newBoards }, + newState: { ports: newPorts }, } = event; - if (newPorts.length === 0) { - setTimeout(() => { - this.setLastBoardsConfigOnUpload(undefined); - }, 5000); return; } + const { + oldState: { ports: oldPorts }, + newState: { boards: newBoards }, + } = event; + const lastSelectionOnUpload = this.lastBoardsConfigOnUpload; this.setLastBoardsConfigOnUpload(undefined); From 03f82fc1b11240ca4e0c641576c1c0898c70c1b7 Mon Sep 17 00:00:00 2001 From: David Simpson <45690499+davegarthsimpson@users.noreply.github.com> Date: Mon, 22 Aug 2022 23:52:15 +0200 Subject: [PATCH 07/11] refine port selection logic --- .../browser/boards/boards-service-provider.ts | 31 ++++++------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/arduino-ide-extension/src/browser/boards/boards-service-provider.ts b/arduino-ide-extension/src/browser/boards/boards-service-provider.ts index 24e06074e..71c1efa84 100644 --- a/arduino-ide-extension/src/browser/boards/boards-service-provider.ts +++ b/arduino-ide-extension/src/browser/boards/boards-service-provider.ts @@ -66,9 +66,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { protected _availableBoards: AvailableBoard[] = []; private lastBoardsConfigOnUpload: BoardsConfig.Config | undefined; - // "lastPersistingUploadPort", is a port created during an upload, that persisted after - // the upload finished, it's "substituting" the port selected when the user invoked the upload - private lastPersistingUploadPortWithBoard: BoardsConfig.Config | undefined; + private boardConfigToSelect: BoardsConfig.Config | undefined; /** * Unlike `onAttachedBoardsChanged` this even fires when the user modifies the selected board in the IDE.\ @@ -124,25 +122,15 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { private derivePersistingUploadPort(event: AttachedBoardsChangeEvent): void { if (!this.lastBoardsConfigOnUpload) { - this.lastPersistingUploadPortWithBoard = undefined; - return; - } - - const { - newState: { ports: newPorts }, - } = event; - if (newPorts.length === 0) { + this.boardConfigToSelect = undefined; return; } const { oldState: { ports: oldPorts }, - newState: { boards: newBoards }, + newState: { ports: newPorts, boards: newBoards }, } = event; - const lastSelectionOnUpload = this.lastBoardsConfigOnUpload; - this.setLastBoardsConfigOnUpload(undefined); - const appearedPorts = oldPorts.length > 0 ? newPorts.filter((newPort: Port) => @@ -151,6 +139,9 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { : newPorts; if (appearedPorts.length > 0) { + const lastSelectionOnUpload = this.lastBoardsConfigOnUpload; + this.setLastBoardsConfigOnUpload(undefined); + const boardOnAppearedPort = newBoards.find((board: Board) => Port.sameAs(board.port, appearedPorts[0]) ); @@ -160,7 +151,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { lastSelectionOnUpload.selectedBoard && Board.sameAs(boardOnAppearedPort, lastSelectionOnUpload.selectedBoard) ) { - this.lastPersistingUploadPortWithBoard = { + this.boardConfigToSelect = { selectedBoard: boardOnAppearedPort, selectedPort: appearedPorts[0], }; @@ -307,13 +298,11 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { return true; } } - // If we could not find an exact match, we compare the board FQBN-name pairs and ignore the port, as it might have changed. - // See documentation on `latestValidBoardsConfig`. - if (!this.lastPersistingUploadPortWithBoard) return false; + if (!this.boardConfigToSelect) return false; - this.boardsConfig = this.lastPersistingUploadPortWithBoard; - this.lastPersistingUploadPortWithBoard = undefined; + this.boardsConfig = this.boardConfigToSelect; + this.boardConfigToSelect = undefined; return true; } return false; From cac5dabb3b03b9ae8261cb5f2ee312f4cf40b267 Mon Sep 17 00:00:00 2001 From: David Simpson <45690499+davegarthsimpson@users.noreply.github.com> Date: Tue, 23 Aug 2022 09:25:17 +0200 Subject: [PATCH 08/11] clean up naming --- .../browser/boards/boards-service-provider.ts | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/arduino-ide-extension/src/browser/boards/boards-service-provider.ts b/arduino-ide-extension/src/browser/boards/boards-service-provider.ts index 71c1efa84..2f75428b6 100644 --- a/arduino-ide-extension/src/browser/boards/boards-service-provider.ts +++ b/arduino-ide-extension/src/browser/boards/boards-service-provider.ts @@ -66,7 +66,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { protected _availableBoards: AvailableBoard[] = []; private lastBoardsConfigOnUpload: BoardsConfig.Config | undefined; - private boardConfigToSelect: BoardsConfig.Config | undefined; + private boardConfigToAutoSelect: BoardsConfig.Config | undefined; /** * Unlike `onAttachedBoardsChanged` this even fires when the user modifies the selected board in the IDE.\ @@ -120,9 +120,11 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { this.lastBoardsConfigOnUpload = value; } - private derivePersistingUploadPort(event: AttachedBoardsChangeEvent): void { + private deriveBoardConfigToAutoSelect( + event: AttachedBoardsChangeEvent + ): void { if (!this.lastBoardsConfigOnUpload) { - this.boardConfigToSelect = undefined; + this.boardConfigToAutoSelect = undefined; return; } @@ -142,8 +144,10 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { const lastSelectionOnUpload = this.lastBoardsConfigOnUpload; this.setLastBoardsConfigOnUpload(undefined); + const appearedPort = appearedPorts[0]; + const boardOnAppearedPort = newBoards.find((board: Board) => - Port.sameAs(board.port, appearedPorts[0]) + Port.sameAs(board.port, appearedPort) ); if ( @@ -151,9 +155,9 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { lastSelectionOnUpload.selectedBoard && Board.sameAs(boardOnAppearedPort, lastSelectionOnUpload.selectedBoard) ) { - this.boardConfigToSelect = { + this.boardConfigToAutoSelect = { selectedBoard: boardOnAppearedPort, - selectedPort: appearedPorts[0], + selectedPort: appearedPort, }; return; } @@ -172,7 +176,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { const { uploadInProgress } = event; if (!uploadInProgress) { - this.derivePersistingUploadPort(event); + this.deriveBoardConfigToAutoSelect(event); } this._attachedBoards = event.newState.boards; @@ -299,10 +303,10 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { } } - if (!this.boardConfigToSelect) return false; + if (!this.boardConfigToAutoSelect) return false; - this.boardsConfig = this.boardConfigToSelect; - this.boardConfigToSelect = undefined; + this.boardsConfig = this.boardConfigToAutoSelect; + this.boardConfigToAutoSelect = undefined; return true; } return false; From a414c87813139bd205bce08a4eba46ae347f3199 Mon Sep 17 00:00:00 2001 From: David Simpson <45690499+davegarthsimpson@users.noreply.github.com> Date: Tue, 23 Aug 2022 13:45:34 +0200 Subject: [PATCH 09/11] refine port selection logic & add delayed clean up --- .../browser/boards/boards-service-provider.ts | 74 ++++++++++++------- .../browser/contributions/upload-sketch.ts | 5 +- 2 files changed, 51 insertions(+), 28 deletions(-) diff --git a/arduino-ide-extension/src/browser/boards/boards-service-provider.ts b/arduino-ide-extension/src/browser/boards/boards-service-provider.ts index 2f75428b6..f723ddabf 100644 --- a/arduino-ide-extension/src/browser/boards/boards-service-provider.ts +++ b/arduino-ide-extension/src/browser/boards/boards-service-provider.ts @@ -66,6 +66,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { protected _availableBoards: AvailableBoard[] = []; private lastBoardsConfigOnUpload: BoardsConfig.Config | undefined; + private lastAvailablePortsOnUpload: Port[] | undefined; private boardConfigToAutoSelect: BoardsConfig.Config | undefined; /** @@ -114,24 +115,44 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { return this._reconciled.promise; } - public setLastBoardsConfigOnUpload( + public snapshotBoardDiscoveryOnUpload(): void { + this.setLastBoardsConfigOnUpload(this.boardsConfig); + this.setAvailablePortsOnUpload(this._availablePorts); + } + + private setLastBoardsConfigOnUpload( value: BoardsConfig.Config | undefined ): void { this.lastBoardsConfigOnUpload = value; } + private setAvailablePortsOnUpload(value: Port[] | undefined): void { + this.lastAvailablePortsOnUpload = value; + } + + public forcePostUploadReconnect(): void { + setTimeout(() => { + const newState = { + ports: this._availablePorts, + boards: this._availableBoards, + }; + this.deriveBoardConfigToAutoSelect(newState); + if (this.lastBoardsConfigOnUpload) { + this.tryReconnect(); + } + }, 2000); // 2 second delay same as IDE 1.8 + } + private deriveBoardConfigToAutoSelect( - event: AttachedBoardsChangeEvent + newState: AttachedBoardsChangeEvent['newState'] ): void { - if (!this.lastBoardsConfigOnUpload) { + if (!this.lastBoardsConfigOnUpload || !this.lastAvailablePortsOnUpload) { this.boardConfigToAutoSelect = undefined; return; } - const { - oldState: { ports: oldPorts }, - newState: { ports: newPorts, boards: newBoards }, - } = event; + const oldPorts = this.lastAvailablePortsOnUpload; + const { ports: newPorts, boards: newBoards } = newState; const appearedPorts = oldPorts.length > 0 @@ -141,25 +162,28 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { : newPorts; if (appearedPorts.length > 0) { - const lastSelectionOnUpload = this.lastBoardsConfigOnUpload; - this.setLastBoardsConfigOnUpload(undefined); - - const appearedPort = appearedPorts[0]; + for (const port of appearedPorts) { + const boardOnAppearedPort = newBoards.find((board: Board) => + Port.sameAs(board.port, port) + ); - const boardOnAppearedPort = newBoards.find((board: Board) => - Port.sameAs(board.port, appearedPort) - ); + if ( + boardOnAppearedPort && + this.lastBoardsConfigOnUpload.selectedBoard && + Board.sameAs( + boardOnAppearedPort, + this.lastBoardsConfigOnUpload.selectedBoard + ) + ) { + this.setLastBoardsConfigOnUpload(undefined); + this.setAvailablePortsOnUpload(undefined); - if ( - boardOnAppearedPort && - lastSelectionOnUpload.selectedBoard && - Board.sameAs(boardOnAppearedPort, lastSelectionOnUpload.selectedBoard) - ) { - this.boardConfigToAutoSelect = { - selectedBoard: boardOnAppearedPort, - selectedPort: appearedPort, - }; - return; + this.boardConfigToAutoSelect = { + selectedBoard: boardOnAppearedPort, + selectedPort: port, + }; + return; + } } } } @@ -176,7 +200,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { const { uploadInProgress } = event; if (!uploadInProgress) { - this.deriveBoardConfigToAutoSelect(event); + this.deriveBoardConfigToAutoSelect(event.newState); } this._attachedBoards = event.newState.boards; diff --git a/arduino-ide-extension/src/browser/contributions/upload-sketch.ts b/arduino-ide-extension/src/browser/contributions/upload-sketch.ts index 3dc915dee..ed1720581 100644 --- a/arduino-ide-extension/src/browser/contributions/upload-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/upload-sketch.ts @@ -190,9 +190,7 @@ export class UploadSketch extends CoreServiceContribution { // toggle the toolbar button and menu item state. // uploadInProgress will be set to false whether the upload fails or not this.uploadInProgress = true; - this.boardsServiceProvider.setLastBoardsConfigOnUpload( - this.boardsServiceProvider.boardsConfig - ); + this.boardsServiceProvider.snapshotBoardDiscoveryOnUpload(); this.onDidChangeEmitter.fire(); this.clearVisibleNotification(); @@ -246,6 +244,7 @@ export class UploadSketch extends CoreServiceContribution { this.handleError(e); } finally { this.uploadInProgress = false; + this.boardsServiceProvider.forcePostUploadReconnect(); this.onDidChangeEmitter.fire(); } } From b002fca9bfcd917b53927aa206b7e8b7d49f9f96 Mon Sep 17 00:00:00 2001 From: David Simpson <45690499+davegarthsimpson@users.noreply.github.com> Date: Tue, 23 Aug 2022 14:56:03 +0200 Subject: [PATCH 10/11] renaming & refactoring --- .../browser/boards/boards-service-provider.ts | 48 +++++++++++-------- .../browser/contributions/upload-sketch.ts | 2 +- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/arduino-ide-extension/src/browser/boards/boards-service-provider.ts b/arduino-ide-extension/src/browser/boards/boards-service-provider.ts index f723ddabf..686f9bceb 100644 --- a/arduino-ide-extension/src/browser/boards/boards-service-provider.ts +++ b/arduino-ide-extension/src/browser/boards/boards-service-provider.ts @@ -130,28 +130,39 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { this.lastAvailablePortsOnUpload = value; } - public forcePostUploadReconnect(): void { + private portToAutoSelectCanBeDerived(): boolean { + return Boolean( + this.lastBoardsConfigOnUpload && this.lastAvailablePortsOnUpload + ); + } + + public attemptPostUploadAutoSelect(): void { setTimeout(() => { - const newState = { - ports: this._availablePorts, - boards: this._availableBoards, - }; - this.deriveBoardConfigToAutoSelect(newState); - if (this.lastBoardsConfigOnUpload) { - this.tryReconnect(); + if (this.portToAutoSelectCanBeDerived()) { + this.attemptAutoSelect({ + ports: this._availablePorts, + boards: this._availableBoards, + }); } }, 2000); // 2 second delay same as IDE 1.8 } + private attemptAutoSelect( + newState: AttachedBoardsChangeEvent['newState'] + ): void { + this.deriveBoardConfigToAutoSelect(newState); + this.tryReconnect(); + } + private deriveBoardConfigToAutoSelect( newState: AttachedBoardsChangeEvent['newState'] ): void { - if (!this.lastBoardsConfigOnUpload || !this.lastAvailablePortsOnUpload) { + if (!this.portToAutoSelectCanBeDerived()) { this.boardConfigToAutoSelect = undefined; return; } - const oldPorts = this.lastAvailablePortsOnUpload; + const oldPorts = this.lastAvailablePortsOnUpload!; const { ports: newPorts, boards: newBoards } = newState; const appearedPorts = @@ -167,12 +178,14 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { Port.sameAs(board.port, port) ); + const lastBoardsConfigOnUpload = this.lastBoardsConfigOnUpload!; + if ( boardOnAppearedPort && - this.lastBoardsConfigOnUpload.selectedBoard && + lastBoardsConfigOnUpload.selectedBoard && Board.sameAs( boardOnAppearedPort, - this.lastBoardsConfigOnUpload.selectedBoard + lastBoardsConfigOnUpload.selectedBoard ) ) { this.setLastBoardsConfigOnUpload(undefined); @@ -197,18 +210,15 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { this.logger.info('------------------------------------------'); } - const { uploadInProgress } = event; - - if (!uploadInProgress) { - this.deriveBoardConfigToAutoSelect(event.newState); - } - this._attachedBoards = event.newState.boards; this._availablePorts = event.newState.ports; this.onAvailablePortsChangedEmitter.fire(this._availablePorts); this.reconcileAvailableBoards().then(() => { + const { uploadInProgress } = event; + // avoid attempting "auto-selection" while an + // upload is in progress if (!uploadInProgress) { - this.tryReconnect(); + this.attemptAutoSelect(event.newState); } }); } diff --git a/arduino-ide-extension/src/browser/contributions/upload-sketch.ts b/arduino-ide-extension/src/browser/contributions/upload-sketch.ts index ed1720581..d3278f0ec 100644 --- a/arduino-ide-extension/src/browser/contributions/upload-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/upload-sketch.ts @@ -244,7 +244,7 @@ export class UploadSketch extends CoreServiceContribution { this.handleError(e); } finally { this.uploadInProgress = false; - this.boardsServiceProvider.forcePostUploadReconnect(); + this.boardsServiceProvider.attemptPostUploadAutoSelect(); this.onDidChangeEmitter.fire(); } } From c5fbad787874a1d3f522fcc64e98d70971c0b573 Mon Sep 17 00:00:00 2001 From: David Simpson <45690499+davegarthsimpson@users.noreply.github.com> Date: Wed, 24 Aug 2022 11:01:09 +0200 Subject: [PATCH 11/11] method syntax & remove unnecessary methods --- .../browser/boards/boards-service-provider.ts | 60 ++++++++----------- .../src/node/board-discovery.ts | 2 +- .../src/node/core-service-impl.ts | 2 +- 3 files changed, 28 insertions(+), 36 deletions(-) diff --git a/arduino-ide-extension/src/browser/boards/boards-service-provider.ts b/arduino-ide-extension/src/browser/boards/boards-service-provider.ts index 686f9bceb..827d976da 100644 --- a/arduino-ide-extension/src/browser/boards/boards-service-provider.ts +++ b/arduino-ide-extension/src/browser/boards/boards-service-provider.ts @@ -115,19 +115,14 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { return this._reconciled.promise; } - public snapshotBoardDiscoveryOnUpload(): void { - this.setLastBoardsConfigOnUpload(this.boardsConfig); - this.setAvailablePortsOnUpload(this._availablePorts); + snapshotBoardDiscoveryOnUpload(): void { + this.lastBoardsConfigOnUpload = this._boardsConfig; + this.lastAvailablePortsOnUpload = this._availablePorts; } - private setLastBoardsConfigOnUpload( - value: BoardsConfig.Config | undefined - ): void { - this.lastBoardsConfigOnUpload = value; - } - - private setAvailablePortsOnUpload(value: Port[] | undefined): void { - this.lastAvailablePortsOnUpload = value; + clearBoardDiscoverySnapshot(): void { + this.lastBoardsConfigOnUpload = undefined; + this.lastAvailablePortsOnUpload = undefined; } private portToAutoSelectCanBeDerived(): boolean { @@ -136,7 +131,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { ); } - public attemptPostUploadAutoSelect(): void { + attemptPostUploadAutoSelect(): void { setTimeout(() => { if (this.portToAutoSelectCanBeDerived()) { this.attemptAutoSelect({ @@ -172,31 +167,28 @@ export class BoardsServiceProvider implements FrontendApplicationContribution { ) : newPorts; - if (appearedPorts.length > 0) { - for (const port of appearedPorts) { - const boardOnAppearedPort = newBoards.find((board: Board) => - Port.sameAs(board.port, port) - ); + for (const port of appearedPorts) { + const boardOnAppearedPort = newBoards.find((board: Board) => + Port.sameAs(board.port, port) + ); - const lastBoardsConfigOnUpload = this.lastBoardsConfigOnUpload!; + const lastBoardsConfigOnUpload = this.lastBoardsConfigOnUpload!; - if ( - boardOnAppearedPort && - lastBoardsConfigOnUpload.selectedBoard && - Board.sameAs( - boardOnAppearedPort, - lastBoardsConfigOnUpload.selectedBoard - ) - ) { - this.setLastBoardsConfigOnUpload(undefined); - this.setAvailablePortsOnUpload(undefined); + if ( + boardOnAppearedPort && + lastBoardsConfigOnUpload.selectedBoard && + Board.sameAs( + boardOnAppearedPort, + lastBoardsConfigOnUpload.selectedBoard + ) + ) { + this.clearBoardDiscoverySnapshot(); - this.boardConfigToAutoSelect = { - selectedBoard: boardOnAppearedPort, - selectedPort: port, - }; - return; - } + this.boardConfigToAutoSelect = { + selectedBoard: boardOnAppearedPort, + selectedPort: port, + }; + return; } } } diff --git a/arduino-ide-extension/src/node/board-discovery.ts b/arduino-ide-extension/src/node/board-discovery.ts index 361749a54..65663ced2 100644 --- a/arduino-ide-extension/src/node/board-discovery.ts +++ b/arduino-ide-extension/src/node/board-discovery.ts @@ -125,7 +125,7 @@ export class BoardDiscovery }); } - public setUploadInProgress(uploadAttemptInProgress: boolean): void { + setUploadInProgress(uploadAttemptInProgress: boolean): void { this.uploadInProgress = uploadAttemptInProgress; } diff --git a/arduino-ide-extension/src/node/core-service-impl.ts b/arduino-ide-extension/src/node/core-service-impl.ts index 7034a279f..db730d940 100644 --- a/arduino-ide-extension/src/node/core-service-impl.ts +++ b/arduino-ide-extension/src/node/core-service-impl.ts @@ -53,7 +53,7 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { private readonly commandService: CommandService; @inject(BoardDiscovery) - protected readonly boardDiscovery: BoardDiscovery; + private readonly boardDiscovery: BoardDiscovery; async compile(options: CoreService.Options.Compile): Promise { const coreClient = await this.coreClient;