Skip to content

Commit 6a6329e

Browse files
author
Akos Kitta
committed
fix: moved UI labels into the model
1 parent a57cdff commit 6a6329e

File tree

4 files changed

+67
-62
lines changed

4 files changed

+67
-62
lines changed

arduino-ide-extension/src/browser/boards/boards-toolbar-item.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import classNames from 'classnames';
1212
import { boardIdentifierLabel, Port } from '../../common/protocol';
1313
import {
1414
BoardListItem,
15+
BoardListItemUI,
1516
InferredBoardListItem,
1617
isInferredBoardListItem,
1718
} from '../../common/protocol/board-list';
@@ -105,7 +106,7 @@ export class BoardListDropDown extends React.Component<
105106
);
106107
}
107108

108-
private readonly onDefaultAction = (item: BoardListItem): unknown => {
109+
private readonly onDefaultAction = (item: BoardListItemUI): unknown => {
109110
const { boardList } = this.props;
110111
const { type, params } = boardList.defaultAction(item);
111112
switch (type) {
@@ -124,11 +125,10 @@ export class BoardListDropDown extends React.Component<
124125
item,
125126
selected,
126127
}: {
127-
item: BoardListItem;
128+
item: BoardListItemUI;
128129
selected: boolean;
129130
}): React.ReactNode {
130-
const { boardLabel, portLabel, portProtocol, tooltip } =
131-
this.props.boardList.labelOf(item);
131+
const { boardLabel, portLabel, portProtocol, tooltip } = item.labels;
132132
const port = item.port;
133133
const onKeyUp = (e: React.KeyboardEvent) => {
134134
if (e.key === 'Enter') {

arduino-ide-extension/src/common/protocol/board-list.ts

Lines changed: 48 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { Mutable } from '@theia/core';
2-
import { Defined } from '../types';
1+
import type { Mutable } from '@theia/core/lib/common/types';
2+
import type { Defined } from '../types';
33
import { naturalCompare } from '../utils';
44
import {
55
BoardIdentifier,
@@ -225,11 +225,28 @@ function boardListItemComparator(
225225
if (!isMultiBoardsBoardListItem(left) && !isMultiBoardsBoardListItem(right)) {
226226
return 1;
227227
}
228+
// ambiguous boards with a unique board name comes first than other ambiguous ones
229+
if (isMultiBoardsBoardListItem(left) && isMultiBoardsBoardListItem(right)) {
230+
const leftUniqueName = findUniqueBoardName(left);
231+
const rightUniqueName = findUniqueBoardName(right);
232+
if (leftUniqueName && !rightUniqueName) {
233+
return -1;
234+
}
235+
if (!leftUniqueName && rightUniqueName) {
236+
return 1;
237+
}
238+
if (leftUniqueName && rightUniqueName) {
239+
return naturalCompare(leftUniqueName, rightUniqueName);
240+
}
241+
}
228242

229243
// fallback compare based on the address
230244
return naturalCompare(left.port.address, right.port.address);
231245
}
232246

247+
/**
248+
* What is show in the UI with all the refinements, fallbacks, and tooltips.
249+
*/
233250
export interface BoardListItemLabels {
234251
readonly boardLabel: string;
235252
readonly boardLabelWithFqbn: string;
@@ -238,9 +255,11 @@ export interface BoardListItemLabels {
238255
readonly tooltip: string;
239256
}
240257

241-
export function createBoardListItemLabels(
242-
item: BoardListItem
243-
): BoardListItemLabels {
258+
export interface BoardListItemUI extends BoardListItem {
259+
readonly labels: BoardListItemLabels;
260+
}
261+
262+
function createBoardListItemLabels(item: BoardListItem): BoardListItemLabels {
244263
const { port } = item;
245264
const portLabel = port.address;
246265
const portProtocol = port.protocol;
@@ -271,7 +290,11 @@ export function createBoardListItemLabels(
271290
};
272291
}
273292

274-
type BoardListItemOrIndex = BoardListItem | number;
293+
/**
294+
* When it's not a `number`, you must use a reference from `BoardList#items` at call-site.
295+
* More formally, `boardList.items.includes(itemOrIndex)` must be `true`.
296+
*/
297+
type BoardListItemUIOrIndex = BoardListItemUI | number;
275298

276299
/**
277300
* A list of boards discovered by the Arduino CLI. With the `board list --watch` gRPC equivalent command,
@@ -282,7 +305,7 @@ export interface BoardList {
282305
/**
283306
* All detected ports with zero to many boards and optional inferred information based on historical selection/usage.
284307
*/
285-
readonly items: readonly BoardListItem[]; // TODO: expose `labels`
308+
readonly items: readonly BoardListItemUI[];
286309
/**
287310
* A snapshot of the board and port configuration this board list has been initialized with.
288311
*/
@@ -312,19 +335,10 @@ export interface BoardList {
312335
Record<'serial' | 'network' | string, ReturnType<BoardList['ports']>>
313336
>;
314337

315-
/**
316-
* What is show in the UI with all the fallbacks and tooltips.
317-
*
318-
* _Notes:_ when the argument is not a number, `boardList.items.includes(itemOrIndex)` must be `true`.
319-
*/
320-
labelOf(itemOrIndex: BoardListItemOrIndex): BoardListItemLabels;
321-
322338
/**
323339
* What's the default action when the argument item is selected in the UI.
324-
*
325-
* _Notes:_ when the argument is not a number, `boardList.items.includes(itemOrIndex)` must be `true`.
326340
*/
327-
defaultAction(itemOrIndex: BoardListItemOrIndex): BoardListItemAction;
341+
defaultAction(itemOrIndex: BoardListItemUIOrIndex): BoardListItemAction;
328342

329343
/**
330344
* For dumping the current state of board list for debugging purposes.
@@ -356,27 +370,28 @@ export function createBoardList(
356370
boardsConfig: Readonly<BoardsConfig> = emptyBoardsConfig(),
357371
boardListHistory: BoardListHistory = {}
358372
): BoardList {
359-
const items: BoardListItem[] = [];
373+
const items: BoardListItemUI[] = [];
360374
for (const detectedPort of Object.values(detectedPorts)) {
361375
const { port, boards } = detectedPort;
362376
// boards with arduino vendor should come first
363377
boards?.sort(boardIdentifierComparator);
364378
const portKey = Port.keyOf(port);
365379
const inferredBoard = boardListHistory[portKey];
380+
let item: BoardListItem;
366381
if (!boards?.length) {
367-
let item: BoardListItem | InferredBoardListItem = { port };
382+
let unknownItem: BoardListItem | InferredBoardListItem = { port };
368383
// Infer unrecognized boards from the history
369384
if (inferredBoard) {
370-
item = {
371-
...item,
385+
unknownItem = {
386+
...unknownItem,
372387
inferredBoard,
373388
type: 'manually-selected',
374389
};
375390
}
376-
items.push(item);
391+
item = unknownItem;
377392
} else if (boards.length === 1) {
378393
const board = boards[0];
379-
let item: BoardListItemWithBoard | InferredBoardListItem = {
394+
let detectedItem: BoardListItemWithBoard | InferredBoardListItem = {
380395
port,
381396
board,
382397
};
@@ -385,30 +400,31 @@ export function createBoardList(
385400
// ignore the inferred item if it's the same as the discovered board
386401
!boardIdentifierEquals(board, inferredBoard)
387402
) {
388-
item = {
389-
...item,
403+
detectedItem = {
404+
...detectedItem,
390405
inferredBoard,
391406
type: 'board-overridden',
392407
};
393408
}
394-
items.push(item);
409+
item = detectedItem;
395410
} else {
396-
let item: MultiBoardsBoardListItem | InferredBoardListItem = {
411+
let ambiguousItem: MultiBoardsBoardListItem | InferredBoardListItem = {
397412
port,
398413
boards,
399414
};
400415
if (inferredBoard) {
401-
item = {
402-
...item,
416+
ambiguousItem = {
417+
...ambiguousItem,
403418
inferredBoard,
404419
type: 'manually-selected',
405420
};
406421
}
407-
items.push(item);
422+
item = ambiguousItem;
408423
}
424+
const labels = createBoardListItemLabels(item);
425+
items.push(Object.assign(item, { labels }));
409426
}
410427
items.sort(boardListItemComparator);
411-
const labels = items.map(createBoardListItemLabels);
412428
const length = items.length;
413429
const findSelectedIndex = (): number => {
414430
if (!isDefinedBoardsConfig(boardsConfig)) {
@@ -521,23 +537,14 @@ export function createBoardList(
521537
portsOnProtocol.push(detectedPort);
522538
}
523539
const matchItem = allPorts[allPorts.matchingIndex];
524-
// match index is per all ports, IDE2 needs to adjust it per protocol
540+
// the cached match index is per all ports. Here, IDE2 needs to adjust the match index per grouped protocol
525541
if (matchItem) {
526542
const matchProtocol = matchItem.port.protocol;
527543
const matchPorts = result[matchProtocol];
528544
matchPorts.matchingIndex = matchPorts.indexOf(matchItem);
529545
}
530546
return result;
531547
},
532-
labelOf(itemOrIndex) {
533-
let index: number | undefined = undefined;
534-
if (typeof itemOrIndex === 'number') {
535-
index = itemOrIndex;
536-
} else {
537-
index = items.indexOf(itemOrIndex);
538-
}
539-
return labels[index];
540-
},
541548
defaultAction(itemOrIndex) {
542549
let item: BoardListItem | undefined = undefined;
543550
if (typeof itemOrIndex === 'number') {
@@ -592,7 +599,6 @@ export function createBoardList(
592599
items,
593600
selectedIndex,
594601
boardListHistory,
595-
labels,
596602
},
597603
null,
598604
2

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { nls } from '@theia/core/lib/common/nls';
22
import type { MaybePromise } from '@theia/core/lib/common/types';
3-
import URI from '@theia/core/lib/common/uri';
3+
import type URI from '@theia/core/lib/common/uri';
44
import {
55
All,
66
Contributed,
77
Partner,
88
Type as TypeLabel,
99
Updatable,
1010
} from '../nls';
11-
import { Defined } from '../types';
11+
import type { Defined } from '../types';
1212
import { naturalCompare } from './../utils';
1313
import type { ArduinoComponent } from './arduino-component';
1414
import type { BoardList } from './board-list';

arduino-ide-extension/src/test/common/board-list.test.ts

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { expect } from 'chai';
22
import {
33
createBoardList,
44
isMultiBoardsBoardListItem,
5-
MultiBoardsBoardListItem,
65
} from '../../common/protocol/board-list';
76
import {
87
BoardIdentifier,
@@ -155,14 +154,14 @@ const detectedPorts: DetectedPorts = {
155154
...detectedPort(mkr1000NetworkPort, mkr1000),
156155
...detectedPort(undiscoveredSerialPort),
157156
...detectedPort(undiscoveredUsbToUARTSerialPort),
158-
// multiple discovered on the same port with the same board name
159-
...detectedPort(nanoEsp32SerialPort, arduinoNanoEsp32, esp32NanoEsp32),
160157
// multiple discovered on the same port with different board names
161158
...detectedPort(
162159
nanoEsp32DetectsMultipleEsp32BoardsSerialPort,
163160
esp32S3DevModule,
164161
esp32S3Box
165162
),
163+
// multiple discovered on the same port with the same board name
164+
...detectedPort(nanoEsp32SerialPort, arduinoNanoEsp32, esp32NanoEsp32),
166165
};
167166

168167
describe('board-list', () => {
@@ -171,19 +170,19 @@ describe('board-list', () => {
171170
const { items } = createBoardList(detectedPorts);
172171
expect(items.length).to.be.equal(Object.keys(detectedPorts).length);
173172
expect(items[0].board).deep.equal(mkr1000);
174-
expect(items[1].board).deep.equal(arduinoNanoEsp32);
175-
expect(isMultiBoardsBoardListItem(items[1])).to.be.true;
176-
expect((<MultiBoardsBoardListItem>items[1]).boards).deep.equal([
177-
arduinoNanoEsp32,
178-
esp32NanoEsp32,
179-
]);
180-
expect(items[2].board).deep.equal(uno);
173+
expect(items[1].board).deep.equal(uno);
174+
expect(items[2].board).is.undefined;
175+
expect(isMultiBoardsBoardListItem(items[2])).to.be.true;
176+
const boards2 = isMultiBoardsBoardListItem(items[2])
177+
? items[2].boards
178+
: undefined;
179+
expect(boards2).deep.equal([arduinoNanoEsp32, esp32NanoEsp32]);
181180
expect(items[3].board).is.undefined;
182181
expect(isMultiBoardsBoardListItem(items[3])).to.be.true;
183-
expect((<MultiBoardsBoardListItem>items[3]).boards).deep.equal([
184-
esp32S3Box, // alphabetic ordering here, `arduino` is not in FQBN
185-
esp32S3DevModule,
186-
]);
182+
const boards3 = isMultiBoardsBoardListItem(items[3])
183+
? items[3].boards
184+
: undefined;
185+
expect(boards3).deep.equal([esp32S3Box, esp32S3DevModule]);
187186
expect(items[4].port).deep.equal(builtinSerialPort);
188187
expect(items[5].port).deep.equal(bluetoothSerialPort);
189188
expect(items[6].port).deep.equal(undiscoveredSerialPort);

0 commit comments

Comments
 (0)