Skip to content

Commit afb3ef7

Browse files
ensure auto-select doesn't select wrong port
prevent auto-select of unattached boards Co-authored-by: Francesco Spissu <francescospissu@users.noreply.github.com>
1 parent a39ab47 commit afb3ef7

File tree

5 files changed

+127
-4
lines changed

5 files changed

+127
-4
lines changed

arduino-ide-extension/src/browser/boards/boards-service-provider.ts

Lines changed: 108 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
6565
protected _availablePorts: Port[] = [];
6666
protected _availableBoards: AvailableBoard[] = [];
6767

68+
private uploadInProgress = false;
69+
70+
private lastItemRemovedForUpload: { board: Board; port: Port } | undefined;
71+
// "lastPersistingUploadPort", is a port created during an upload, that persisted after
72+
// the upload finished, it's "substituting" the port selected when the user invoked the upload
73+
private lastPersistingUploadPort: Port | undefined;
74+
6875
/**
6976
* Unlike `onAttachedBoardsChanged` this even fires when the user modifies the selected board in the IDE.\
7077
* 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 {
8087
private readonly _reconciled = new Deferred<void>();
8188

8289
onStart(): void {
90+
this.notificationCenter.onUploadInProgress(
91+
this.onUploadNotificationReceived.bind(this)
92+
);
8393
this.notificationCenter.onAttachedBoardsDidChange(
8494
this.notifyAttachedBoardsChanged.bind(this)
8595
);
@@ -111,6 +121,68 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
111121
return this._reconciled.promise;
112122
}
113123

124+
private onUploadNotificationReceived(uploadInProgress: boolean): void {
125+
this.uploadInProgress = uploadInProgress;
126+
}
127+
128+
private checkForItemRemoved(event: AttachedBoardsChangeEvent): void {
129+
if (!this.lastItemRemovedForUpload) {
130+
const {
131+
oldState: { ports: oldPorts, boards: oldBoards },
132+
newState: { ports: newPorts },
133+
} = event;
134+
135+
const disappearedPorts = oldPorts.filter((oldPort: Port) =>
136+
newPorts.every((newPort: Port) => !Port.sameAs(oldPort, newPort))
137+
);
138+
139+
if (disappearedPorts.length > 0) {
140+
this.lastItemRemovedForUpload = {
141+
board: oldBoards.find((board: Board) =>
142+
Port.sameAs(board.port, disappearedPorts[0])
143+
) as Board,
144+
port: disappearedPorts[0],
145+
};
146+
}
147+
148+
return;
149+
}
150+
}
151+
152+
private checkForPersistingPort(event: AttachedBoardsChangeEvent): void {
153+
if (this.lastItemRemovedForUpload) {
154+
const {
155+
oldState: { ports: oldPorts },
156+
newState: { ports: newPorts, boards: newBoards },
157+
} = event;
158+
159+
const disappearedItem = this.lastItemRemovedForUpload;
160+
this.lastItemRemovedForUpload = undefined;
161+
162+
const appearedPorts = newPorts.filter((newPort: Port) =>
163+
oldPorts.every((oldPort: Port) => !Port.sameAs(newPort, oldPort))
164+
);
165+
166+
if (appearedPorts.length > 0) {
167+
const boardOnAppearedPort = newBoards.find((board: Board) =>
168+
Port.sameAs(board.port, appearedPorts[0])
169+
);
170+
171+
if (
172+
boardOnAppearedPort &&
173+
Board.sameAs(boardOnAppearedPort, disappearedItem.board)
174+
) {
175+
this.lastPersistingUploadPort = appearedPorts[0];
176+
return;
177+
}
178+
}
179+
180+
return;
181+
}
182+
183+
this.lastPersistingUploadPort = undefined;
184+
}
185+
114186
protected notifyAttachedBoardsChanged(
115187
event: AttachedBoardsChangeEvent
116188
): void {
@@ -119,10 +191,21 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
119191
this.logger.info(AttachedBoardsChangeEvent.toString(event));
120192
this.logger.info('------------------------------------------');
121193
}
194+
195+
if (this.uploadInProgress) {
196+
this.checkForItemRemoved(event);
197+
} else {
198+
this.checkForPersistingPort(event);
199+
}
200+
122201
this._attachedBoards = event.newState.boards;
123202
this._availablePorts = event.newState.ports;
124203
this.onAvailablePortsChangedEmitter.fire(this._availablePorts);
125-
this.reconcileAvailableBoards().then(() => this.tryReconnect());
204+
this.reconcileAvailableBoards().then(() => {
205+
if (!this.uploadInProgress) {
206+
this.tryReconnect();
207+
}
208+
});
126209
}
127210

128211
protected notifyPlatformInstalled(event: { item: BoardsPackage }): void {
@@ -240,6 +323,21 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
240323
}
241324
// If we could not find an exact match, we compare the board FQBN-name pairs and ignore the port, as it might have changed.
242325
// See documentation on `latestValidBoardsConfig`.
326+
327+
if (!this.lastPersistingUploadPort) return false;
328+
329+
const lastPersistingUploadPort = this.lastPersistingUploadPort;
330+
this.lastPersistingUploadPort = undefined;
331+
332+
if (
333+
!Port.sameAs(
334+
lastPersistingUploadPort,
335+
this.latestValidBoardsConfig.selectedPort
336+
)
337+
) {
338+
return false;
339+
}
340+
243341
for (const board of this.availableBoards.filter(
244342
({ state }) => state !== AvailableBoard.State.incomplete
245343
)) {
@@ -458,6 +556,11 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
458556
const board = attachedBoards.find(({ port }) =>
459557
Port.sameAs(boardPort, port)
460558
);
559+
// "board" will always be falsey for
560+
// port that was originally mapped
561+
// to unknown board and then selected
562+
// manually by user
563+
461564
const lastSelectedBoard = await this.getLastSelectedBoardOnPort(
462565
boardPort
463566
);
@@ -476,7 +579,9 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
476579
availableBoard = {
477580
...lastSelectedBoard,
478581
state: AvailableBoard.State.guessed,
479-
selected: BoardsConfig.Config.sameAs(boardsConfig, lastSelectedBoard),
582+
selected:
583+
BoardsConfig.Config.sameAs(boardsConfig, lastSelectedBoard) &&
584+
Port.sameAs(boardPort, boardsConfig.selectedPort), // to avoid double selection
480585
port: boardPort,
481586
};
482587
} else {
@@ -491,7 +596,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
491596

492597
if (
493598
boardsConfig.selectedBoard &&
494-
!availableBoards.some(({ selected }) => selected)
599+
availableBoards.every(({ selected }) => !selected)
495600
) {
496601
// If the selected board has the same port of an unknown board
497602
// that is already in availableBoards we might get a duplicate port.

arduino-ide-extension/src/browser/contributions/upload-sketch.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { UserFieldsDialog } from '../dialogs/user-fields/user-fields-dialog';
1515
import { DisposableCollection, nls } from '@theia/core/lib/common';
1616
import { CurrentSketch } from '../../common/protocol/sketches-service-client-impl';
1717
import type { VerifySketchParams } from './verify-sketch';
18+
import { NotificationCenter } from '../notification-center';
1819

1920
@injectable()
2021
export class UploadSketch extends CoreServiceContribution {
@@ -24,6 +25,9 @@ export class UploadSketch extends CoreServiceContribution {
2425
@inject(UserFieldsDialog)
2526
private readonly userFieldsDialog: UserFieldsDialog;
2627

28+
@inject(NotificationCenter)
29+
private readonly notificationCenter: NotificationCenter;
30+
2731
private boardRequiresUserFields = false;
2832
private readonly cachedUserFields: Map<string, BoardUserField[]> = new Map();
2933
private readonly menuActionsDisposables = new DisposableCollection();
@@ -191,6 +195,7 @@ export class UploadSketch extends CoreServiceContribution {
191195
// uploadInProgress will be set to false whether the upload fails or not
192196
this.uploadInProgress = true;
193197
this.onDidChangeEmitter.fire();
198+
this.notificationCenter.notifyUploadInProgress(this.uploadInProgress);
194199

195200
const verifyOptions =
196201
await this.commandService.executeCommand<CoreService.Options.Compile>(
@@ -243,6 +248,7 @@ export class UploadSketch extends CoreServiceContribution {
243248
} finally {
244249
this.uploadInProgress = false;
245250
this.onDidChangeEmitter.fire();
251+
this.notificationCenter.notifyUploadInProgress(this.uploadInProgress);
246252
}
247253
}
248254

arduino-ide-extension/src/browser/notification-center.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ export class NotificationCenter
6666
}>();
6767
private readonly onAppStateDidChangeEmitter =
6868
new Emitter<FrontendApplicationState>();
69+
private readonly onUploadInProgressEmitter = new Emitter<boolean>();
6970

7071
protected readonly toDispose = new DisposableCollection(
7172
this.indexWillUpdateEmitter,
@@ -79,7 +80,8 @@ export class NotificationCenter
7980
this.platformDidUninstallEmitter,
8081
this.libraryDidInstallEmitter,
8182
this.libraryDidUninstallEmitter,
82-
this.attachedBoardsDidChangeEmitter
83+
this.attachedBoardsDidChangeEmitter,
84+
this.onUploadInProgressEmitter
8385
);
8486

8587
readonly onIndexDidUpdate = this.indexDidUpdateEmitter.event;
@@ -97,6 +99,7 @@ export class NotificationCenter
9799
this.attachedBoardsDidChangeEmitter.event;
98100
readonly onRecentSketchesDidChange = this.recentSketchesChangedEmitter.event;
99101
readonly onAppStateDidChange = this.onAppStateDidChangeEmitter.event;
102+
readonly onUploadInProgress = this.onUploadInProgressEmitter.event;
100103

101104
@postConstruct()
102105
protected init(): void {
@@ -169,4 +172,8 @@ export class NotificationCenter
169172
notifyRecentSketchesDidChange(event: { sketches: Sketch[] }): void {
170173
this.recentSketchesChangedEmitter.fire(event);
171174
}
175+
176+
notifyUploadInProgress(event: boolean): void {
177+
this.onUploadInProgressEmitter.fire(event);
178+
}
172179
}

arduino-ide-extension/src/common/protocol/notification-service.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export interface NotificationServiceClient {
2828
notifyLibraryDidUninstall(event: { item: LibraryPackage }): void;
2929
notifyAttachedBoardsDidChange(event: AttachedBoardsChangeEvent): void;
3030
notifyRecentSketchesDidChange(event: { sketches: Sketch[] }): void;
31+
notifyUploadInProgress(event: boolean): void;
3132
}
3233

3334
export const NotificationServicePath = '/services/notification-service';

arduino-ide-extension/src/node/notification-service-server.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ export class NotificationServiceServerImpl
8282
);
8383
}
8484

85+
notifyUploadInProgress(event: boolean): void {
86+
this.clients.forEach((client) => client.notifyUploadInProgress(event));
87+
}
88+
8589
setClient(client: NotificationServiceClient): void {
8690
this.clients.push(client);
8791
}

0 commit comments

Comments
 (0)