Skip to content

Commit 134e65c

Browse files
committed
Reworked board selection dropdown ordering
Ordering is now: 1. Serial with recognized boards 2. Serial with guessed boards 3. Serial with incomplete boards 4. Network with recognized boards 5. Other protocols with recognized boards
1 parent f35a1e4 commit 134e65c

File tree

1 file changed

+85
-89
lines changed

1 file changed

+85
-89
lines changed

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

+85-89
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,8 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
180180
const selectedAvailableBoard = AvailableBoard.is(selectedBoard)
181181
? selectedBoard
182182
: this._availableBoards.find((availableBoard) =>
183-
Board.sameAs(availableBoard, selectedBoard)
184-
);
183+
Board.sameAs(availableBoard, selectedBoard)
184+
);
185185
if (
186186
selectedAvailableBoard &&
187187
selectedAvailableBoard.selected &&
@@ -358,14 +358,14 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
358358
const timeoutTask =
359359
!!timeout && timeout > 0
360360
? new Promise<void>((_, reject) =>
361-
setTimeout(
362-
() => reject(new Error(`Timeout after ${timeout} ms.`)),
363-
timeout
364-
)
361+
setTimeout(
362+
() => reject(new Error(`Timeout after ${timeout} ms.`)),
363+
timeout
365364
)
365+
)
366366
: new Promise<void>(() => {
367-
/* never */
368-
});
367+
/* never */
368+
});
369369
const waitUntilTask = new Promise<void>((resolve) => {
370370
let candidate = find(what, this.availableBoards);
371371
if (candidate) {
@@ -384,7 +384,6 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
384384
}
385385

386386
protected async reconcileAvailableBoards(): Promise<void> {
387-
const attachedBoards = this._attachedBoards;
388387
const availablePorts = this._availablePorts;
389388
// Unset the port on the user's config, if it is not available anymore.
390389
if (
@@ -402,51 +401,64 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
402401
const boardsConfig = this.boardsConfig;
403402
const currentAvailableBoards = this._availableBoards;
404403
const availableBoards: AvailableBoard[] = [];
405-
const availableBoardPorts = availablePorts.filter(Port.isBoardPort);
406-
const attachedSerialBoards = attachedBoards.filter(({ port }) => !!port);
404+
const attachedBoards = this._attachedBoards.filter(({ port }) => !!port);
405+
const availableBoardPorts = availablePorts.filter((port) => {
406+
if (port.protocol === "serial") {
407+
// We always show all serial ports, even if there
408+
// is no recognized board connected to it
409+
return true;
410+
}
411+
412+
// All other ports with different protocol are
413+
// only shown if there is a recognized board
414+
// connected
415+
for (const board of attachedBoards) {
416+
if (board.port?.address === port.address) {
417+
return true;
418+
}
419+
}
420+
return false;
421+
});
407422

408423
for (const boardPort of availableBoardPorts) {
409-
let state = AvailableBoard.State.incomplete; // Initial pessimism.
410-
let board = attachedSerialBoards.find(({ port }) =>
411-
Port.sameAs(boardPort, port)
412-
);
424+
let board = attachedBoards.find(({ port }) => Port.sameAs(boardPort, port));
425+
const lastSelectedBoard = await this.getLastSelectedBoardOnPort(boardPort);
426+
427+
let availableBoard = {} as AvailableBoard;
413428
if (board) {
414-
state = AvailableBoard.State.recognized;
415-
} else {
429+
availableBoard = {
430+
...board,
431+
state: AvailableBoard.State.recognized,
432+
selected: BoardsConfig.Config.sameAs(boardsConfig, board),
433+
port: boardPort,
434+
};
435+
} else if (lastSelectedBoard) {
416436
// If the selected board is not recognized because it is a 3rd party board: https://github.com/arduino/arduino-cli/issues/623
417437
// We still want to show it without the red X in the boards toolbar: https://github.com/arduino/arduino-pro-ide/issues/198#issuecomment-599355836
418-
const lastSelectedBoard = await this.getLastSelectedBoardOnPort(
419-
boardPort
420-
);
421-
if (lastSelectedBoard) {
422-
board = {
423-
...lastSelectedBoard,
424-
port: boardPort,
425-
};
426-
state = AvailableBoard.State.guessed;
427-
}
428-
}
429-
if (!board) {
430-
availableBoards.push({
431-
name: nls.localize('arduino/common/unknown', 'Unknown'),
438+
availableBoard = {
439+
...lastSelectedBoard,
440+
state: AvailableBoard.State.guessed,
441+
selected: BoardsConfig.Config.sameAs(boardsConfig, lastSelectedBoard),
432442
port: boardPort,
433-
state,
434-
});
443+
};
435444
} else {
436-
const selected = BoardsConfig.Config.sameAs(boardsConfig, board);
437-
availableBoards.push({
438-
...board,
439-
state,
440-
selected,
445+
availableBoard = {
446+
name: nls.localize('arduino/common/unknown', 'Unknown'),
441447
port: boardPort,
442-
});
448+
state: AvailableBoard.State.incomplete,
449+
};
443450
}
451+
availableBoards.push(availableBoard);
444452
}
445453

446-
if (
447-
boardsConfig.selectedBoard &&
448-
!availableBoards.some(({ selected }) => selected)
449-
) {
454+
if (boardsConfig.selectedBoard && !availableBoards.some(({ selected }) => selected)) {
455+
// If the selected board has the same port of an unknown board
456+
// that is already in availableBoards we might get a duplicate port.
457+
// So we remove the one already in the array and add the selected one.
458+
const found = availableBoards.findIndex(board => board.port?.address === boardsConfig.selectedPort?.address);
459+
if (found >= 0) {
460+
availableBoards.splice(found, 1);
461+
}
450462
availableBoards.push({
451463
...boardsConfig.selectedBoard,
452464
port: boardsConfig.selectedPort,
@@ -455,28 +467,20 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
455467
});
456468
}
457469

458-
const sortedAvailableBoards = availableBoards.sort(AvailableBoard.compare);
459-
let hasChanged =
460-
sortedAvailableBoards.length !== currentAvailableBoards.length;
461-
for (let i = 0; !hasChanged && i < sortedAvailableBoards.length; i++) {
462-
hasChanged =
463-
AvailableBoard.compare(
464-
sortedAvailableBoards[i],
465-
currentAvailableBoards[i]
466-
) !== 0;
470+
availableBoards.sort(AvailableBoard.compare);
471+
472+
let hasChanged = availableBoards.length !== currentAvailableBoards.length;
473+
for (let i = 0; !hasChanged && i < availableBoards.length; i++) {
474+
const [left, right] = [availableBoards[i], currentAvailableBoards[i]];
475+
hasChanged = !!AvailableBoard.compare(left, right);
467476
}
468477
if (hasChanged) {
469-
this._availableBoards = sortedAvailableBoards;
478+
this._availableBoards = availableBoards;
470479
this.onAvailableBoardsChangedEmitter.fire(this._availableBoards);
471480
}
472481
}
473482

474-
protected async getLastSelectedBoardOnPort(
475-
port: Port | string | undefined
476-
): Promise<Board | undefined> {
477-
if (!port) {
478-
return undefined;
479-
}
483+
protected async getLastSelectedBoardOnPort(port: Port): Promise<Board | undefined> {
480484
const key = this.getLastSelectedBoardOnPortKey(port);
481485
return this.getData<Board>(key);
482486
}
@@ -497,11 +501,8 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
497501
]);
498502
}
499503

500-
protected getLastSelectedBoardOnPortKey(port: Port | string): string {
501-
// TODO: we lose the port's `protocol` info (`serial`, `network`, etc.) here if the `port` is a `string`.
502-
return `last-selected-board-on-port:${
503-
typeof port === 'string' ? port : Port.toString(port)
504-
}`;
504+
protected getLastSelectedBoardOnPortKey(port: Port): string {
505+
return `last-selected-board-on-port:${Port.toString(port)}`;
505506
}
506507

507508
protected async loadState(): Promise<void> {
@@ -585,35 +586,30 @@ export namespace AvailableBoard {
585586
return !!board.port;
586587
}
587588

589+
// Available boards must be sorted in this order:
590+
// 1. Serial with recognized boards
591+
// 2. Serial with guessed boards
592+
// 3. Serial with incomplete boards
593+
// 4. Network with recognized boards
594+
// 5. Other protocols with recognized boards
588595
export const compare = (left: AvailableBoard, right: AvailableBoard) => {
589-
if (left.selected && !right.selected) {
596+
if (left.port?.protocol === "serial" && right.port?.protocol !== "serial") {
590597
return -1;
591-
}
592-
if (right.selected && !left.selected) {
598+
} else if (left.port?.protocol !== "serial" && right.port?.protocol === "serial") {
593599
return 1;
594-
}
595-
let result = naturalCompare(left.name, right.name);
596-
if (result !== 0) {
597-
return result;
598-
}
599-
if (left.fqbn && right.fqbn) {
600-
result = naturalCompare(left.fqbn, right.fqbn);
601-
if (result !== 0) {
602-
return result;
603-
}
604-
}
605-
if (left.port && right.port) {
606-
result = Port.compare(left.port, right.port);
607-
if (result !== 0) {
608-
return result;
609-
}
610-
}
611-
if (!!left.selected && !right.selected) {
600+
} else if (left.port?.protocol === "network" && right.port?.protocol !== "network") {
612601
return -1;
613-
}
614-
if (!!right.selected && !left.selected) {
602+
} else if (left.port?.protocol !== "network" && right.port?.protocol === "network") {
615603
return 1;
604+
} else if (left.port?.protocol === "serial" && right.port?.protocol === "serial") {
605+
// We show all serial ports, including those that have guessed
606+
// or unrecognized boards, so we must sort those too.
607+
if (left.state < right.state) {
608+
return -1;
609+
} else if (left.state > right.state) {
610+
return 1;
611+
}
616612
}
617-
return left.state - right.state;
618-
};
613+
return naturalCompare(left.port?.address!, right.port?.address!);
614+
}
619615
}

0 commit comments

Comments
 (0)