fix: expand boards if available on detected port

moved the board inference logic from UI to  model

Closes #2175

Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
This commit is contained in:
Akos Kitta 2023-08-19 12:36:43 +02:00 committed by Akos Kitta
parent 5a76be306a
commit db01efead3
5 changed files with 166 additions and 52 deletions

View File

@ -1,10 +1,7 @@
import { nls } from '@theia/core/lib/common/nls';
import React from '@theia/core/shared/react';
import Tippy from '@tippyjs/react';
import {
BoardList,
isInferredBoardListItem,
} from '../../../common/protocol/board-list';
import type { BoardList } from '../../../common/protocol/board-list';
import {
boardIdentifierEquals,
portIdentifierEquals,
@ -50,9 +47,7 @@ export const CertificateUploaderComponent = ({
if (!selectedItem) {
return;
}
const board = isInferredBoardListItem(selectedItem)
? selectedItem.inferredBoard
: selectedItem.board;
const board = selectedItem.board;
if (!board.fqbn) {
return;
}
@ -76,13 +71,9 @@ export const CertificateUploaderComponent = ({
if (!item) {
return;
}
const board = isInferredBoardListItem(item)
? item.inferredBoard
: item.board;
const selectedBoard = isInferredBoardListItem(selectedItem)
? selectedItem.inferredBoard
: selectedItem?.board;
const board = item.board;
const port = item.port;
const selectedBoard = selectedItem?.board;
const selectedPort = selectedItem?.port;
if (

View File

@ -1,14 +1,12 @@
import { nls } from '@theia/core/lib/common';
import React from '@theia/core/shared/react';
import {
import type {
BoardList,
BoardListItemWithBoard,
InferredBoardListItem,
isInferredBoardListItem,
} from '../../../common/protocol/board-list';
import { ArduinoSelect } from '../../widgets/arduino-select';
export type BoardOptionValue = BoardListItemWithBoard | InferredBoardListItem;
export type BoardOptionValue = BoardListItemWithBoard;
type BoardOption = { value: BoardOptionValue | undefined; label: string };
export const SelectBoardComponent = ({
@ -46,9 +44,7 @@ export const SelectBoardComponent = ({
'Select a board...'
);
const updatableBoards = boardList.boards.filter((item) => {
const fqbn = (
isInferredBoardListItem(item) ? item.inferredBoard : item.board
).fqbn;
const fqbn = item.board.fqbn;
return fqbn && updatableFqbns.includes(fqbn);
});
let selBoard = -1;
@ -57,15 +53,12 @@ export const SelectBoardComponent = ({
if (selectedItem === item) {
selBoard = i;
}
const board = isInferredBoardListItem(item)
? item.inferredBoard
: item.board;
return {
label: nls.localize(
'arduino/certificate/boardAtPort',
'{0} at {1}',
board.name,
item.port?.address ?? ''
item.board.name,
item.port.address ?? ''
),
value: item,
};
@ -100,10 +93,7 @@ export const SelectBoardComponent = ({
label: nls.localize(
'arduino/certificate/boardAtPort',
'{0} at {1}',
(isInferredBoardListItem(selectedItem)
? selectedItem.inferredBoard
: selectedItem.board
).name,
selectedItem.board.name,
selectedItem.port.address ?? ''
),
}) ||

View File

@ -9,10 +9,9 @@ import {
ArduinoFirmwareUploader,
FirmwareInfo,
} from '../../../common/protocol/arduino-firmware-uploader';
import {
import type {
BoardList,
BoardListItemWithBoard,
isInferredBoardListItem,
} from '../../../common/protocol/board-list';
import { ArduinoSelect } from '../../widgets/arduino-select';
import { SelectBoardComponent } from '../certificate-uploader/select-board-components';
@ -63,9 +62,7 @@ export const FirmwareUploaderComponent = ({
}
// fetch the firmwares for the selected board
const board = isInferredBoardListItem(selectedItem)
? selectedItem.inferredBoard
: selectedItem.board;
const board = selectedItem.board;
const firmwaresForFqbn = await firmwareUploader.availableFirmwares(
board.fqbn || ''
);
@ -89,11 +86,14 @@ export const FirmwareUploaderComponent = ({
(firmware) => firmware.firmware_version === selectedFirmware?.value
);
const selectedBoard = selectedItem?.board;
const selectedPort = selectedItem?.port;
try {
const installStatus =
!!firmwareToFlash &&
!!selectedItem?.board &&
(await flashFirmware(firmwareToFlash, selectedItem?.port));
firmwareToFlash &&
selectedBoard &&
selectedPort &&
(await flashFirmware(firmwareToFlash, selectedPort));
setInstallFeedback((installStatus && 'ok') || 'fail');
} catch {
@ -106,13 +106,9 @@ export const FirmwareUploaderComponent = ({
if (!item) {
return;
}
const board = isInferredBoardListItem(item)
? item.inferredBoard
: item.board;
const selectedBoard = isInferredBoardListItem(selectedItem)
? selectedItem.inferredBoard
: selectedItem?.board;
const board = item.board;
const port = item.port;
const selectedBoard = selectedItem?.board;
const selectedPort = selectedItem?.port;
if (

View File

@ -362,9 +362,12 @@ export interface BoardList {
readonly selectedIndex: number;
/**
* Contains all boards recognized from the detected port, and an optional unrecognized one that is derived from the detected port and the `initParam#selectedBoard`.
* Contains all the following board+port pairs:
* - one discovered board on a detected board (`1`),
* - manually selected or overridden board for a detected port (`1`),
* - multiple discovered boards on detected port (`1..*`)
*/
readonly boards: readonly (BoardListItemWithBoard | InferredBoardListItem)[];
readonly boards: readonly BoardListItemWithBoard[];
/**
* If `predicate` is not defined, no ports are filtered.
@ -511,17 +514,27 @@ function collectPorts(
function collectBoards(
items: readonly BoardListItem[]
): readonly (BoardListItemWithBoard | InferredBoardListItem)[] {
const boards: (BoardListItemWithBoard | InferredBoardListItem)[] = [];
): readonly BoardListItemWithBoard[] {
const result: BoardListItemWithBoard[] = [];
for (let i = 0; i < items.length; i++) {
const boards: BoardListItemWithBoard[] = [];
const item = items[i];
if (isInferredBoardListItem(item)) {
boards.push(item);
} else if (item.board?.fqbn) {
boards.push(<Required<BoardListItem>>item);
const { port } = item;
const board = getInferredBoardOrBoard(item);
if (board) {
boards.push({ board, port });
}
if (isMultiBoardsBoardListItem(item)) {
for (const otherBoard of item.boards) {
if (!boardIdentifierEquals(board, otherBoard)) {
boards.push({ board: otherBoard, port });
}
}
return boards;
}
boards.sort(boardListItemComparator);
result.push(...boards);
}
return result;
}
function findSelectedIndex(

View File

@ -328,6 +328,130 @@ describe('board-list', () => {
expect(items[0].labels.boardLabel).to.be.equal(Unknown);
});
describe('boards', () => {
it('should include discovered boards on detected ports', () => {
const { boards } = createBoardList({
...detectedPort(unoSerialPort, uno),
...detectedPort(mkr1000SerialPort, mkr1000),
...detectedPort(undiscoveredSerialPort),
});
expect(boards).to.deep.equal([
{
port: mkr1000SerialPort,
board: mkr1000,
},
{
port: unoSerialPort,
board: uno,
},
]);
});
it('should include manually selected boards on detected ports', () => {
const { boards } = createBoardList({
...detectedPort(unoSerialPort, uno),
...detectedPort(undiscoveredSerialPort, uno),
...detectedPort(undiscoveredUsbToUARTSerialPort),
});
expect(boards).to.deep.equal([
{
port: unoSerialPort,
board: uno,
},
{
port: undiscoveredSerialPort,
board: uno,
},
]);
});
it('should include manually overridden boards on detected ports', () => {
const { boards } = createBoardList(
{
...detectedPort(unoSerialPort, uno),
...detectedPort(mkr1000SerialPort, mkr1000),
},
emptyBoardsConfig(),
{
...history(unoSerialPort, mkr1000),
}
);
expect(boards).to.deep.equal([
{
port: mkr1000SerialPort,
board: mkr1000,
},
{
port: unoSerialPort,
board: mkr1000,
},
]);
});
it('should include all boards discovered on a port', () => {
const { boards } = createBoardList({
...detectedPort(
nanoEsp32SerialPort,
arduinoNanoEsp32,
esp32NanoEsp32
),
...detectedPort(
nanoEsp32DetectsMultipleEsp32BoardsSerialPort,
esp32S3DevModule,
esp32S3Box
),
});
expect(boards).to.deep.equal([
{
port: nanoEsp32SerialPort,
board: arduinoNanoEsp32,
},
{
port: nanoEsp32SerialPort,
board: esp32NanoEsp32,
},
{
port: nanoEsp32DetectsMultipleEsp32BoardsSerialPort,
board: esp32S3Box,
},
{
port: nanoEsp32DetectsMultipleEsp32BoardsSerialPort,
board: esp32S3DevModule,
},
]);
});
it('should include all boards discovered on a port (handle manual select)', () => {
const { boards } = createBoardList(
{
...detectedPort(
nanoEsp32SerialPort,
arduinoNanoEsp32,
esp32NanoEsp32
),
},
emptyBoardsConfig(),
{
...history(nanoEsp32SerialPort, esp32S3DevModule),
}
);
expect(boards).to.deep.equal([
{
port: nanoEsp32SerialPort,
board: arduinoNanoEsp32,
},
{
port: nanoEsp32SerialPort,
board: esp32NanoEsp32,
},
{
port: nanoEsp32SerialPort,
board: esp32S3DevModule,
},
]);
});
});
describe('defaultAction', () => {
it("'select' should be the default action for identifier boards", () => {
const { items } = createBoardList({