Skip to content

Commit a090dfe

Browse files
silvanocerzaAlberto Iannaccone
and
Alberto Iannaccone
authored
Add dialog to insert user fields for board that require them to upload (#550)
* Rebuild gRPC protocol interfaces * Implement methods to get user fields for board/port combination * Implement dialog to input board user fields * Add configure and upload step when uploading to board requiring user fields * Disable Sketch > Configure and Upload menu if board doesn't support user fields * Fix serial upload not working with all boards * Update i18n source file * fix user fields UI * regenerate cli protocol * fix localisation * check if user fields are empty Co-authored-by: Alberto Iannaccone <a.iannaccone@arduino.cc>
1 parent 74bfdc4 commit a090dfe

19 files changed

+568
-679
lines changed

arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ export class ArduinoFrontendContribution
445445
'arduino/debug/optimizeForDebugging',
446446
'Optimize for Debugging'
447447
),
448-
order: '4',
448+
order: '5',
449449
});
450450
}
451451

arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts

+11
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,11 @@ import {
254254
UploadCertificateDialogWidget,
255255
} from './dialogs/certificate-uploader/certificate-uploader-dialog';
256256
import { PlotterFrontendContribution } from './serial/plotter/plotter-frontend-contribution';
257+
import {
258+
UserFieldsDialog,
259+
UserFieldsDialogProps,
260+
UserFieldsDialogWidget,
261+
} from './dialogs/user-fields/user-fields-dialog';
257262
import { nls } from '@theia/core/lib/browser/nls';
258263

259264
const ElementQueries = require('css-element-queries/src/ElementQueries');
@@ -739,4 +744,10 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
739744
bind(UploadCertificateDialogProps).toConstantValue({
740745
title: 'UploadCertificate',
741746
});
747+
748+
bind(UserFieldsDialogWidget).toSelf().inSingletonScope();
749+
bind(UserFieldsDialog).toSelf().inSingletonScope();
750+
bind(UserFieldsDialogProps).toConstantValue({
751+
title: 'UserFields',
752+
});
742753
});

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

+62-23
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
BoardsPackage,
1313
AttachedBoardsChangeEvent,
1414
BoardWithPackage,
15+
BoardUserField,
1516
} from '../../common/protocol';
1617
import { BoardsConfig } from './boards-config';
1718
import { naturalCompare } from '../../common/utils';
@@ -68,7 +69,8 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
6869
* This event is also emitted when the board package for the currently selected board was uninstalled.
6970
*/
7071
readonly onBoardsConfigChanged = this.onBoardsConfigChangedEmitter.event;
71-
readonly onAvailableBoardsChanged = this.onAvailableBoardsChangedEmitter.event;
72+
readonly onAvailableBoardsChanged =
73+
this.onAvailableBoardsChangedEmitter.event;
7274
readonly onAvailablePortsChanged = this.onAvailablePortsChangedEmitter.event;
7375

7476
onStart(): void {
@@ -183,8 +185,8 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
183185
const selectedAvailableBoard = AvailableBoard.is(selectedBoard)
184186
? selectedBoard
185187
: this._availableBoards.find((availableBoard) =>
186-
Board.sameAs(availableBoard, selectedBoard)
187-
);
188+
Board.sameAs(availableBoard, selectedBoard)
189+
);
188190
if (
189191
selectedAvailableBoard &&
190192
selectedAvailableBoard.selected &&
@@ -274,6 +276,18 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
274276
return boards;
275277
}
276278

279+
async selectedBoardUserFields(): Promise<BoardUserField[]> {
280+
if (!this._boardsConfig.selectedBoard || !this._boardsConfig.selectedPort) {
281+
return [];
282+
}
283+
const fqbn = this._boardsConfig.selectedBoard.fqbn;
284+
if (!fqbn) {
285+
return [];
286+
}
287+
const protocol = this._boardsConfig.selectedPort.protocol;
288+
return await this.boardsService.getBoardUserFields({ fqbn, protocol });
289+
}
290+
277291
/**
278292
* `true` if the `config.selectedBoard` is defined; hence can compile against the board. Otherwise, `false`.
279293
*/
@@ -361,14 +375,14 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
361375
const timeoutTask =
362376
!!timeout && timeout > 0
363377
? new Promise<void>((_, reject) =>
364-
setTimeout(
365-
() => reject(new Error(`Timeout after ${timeout} ms.`)),
366-
timeout
378+
setTimeout(
379+
() => reject(new Error(`Timeout after ${timeout} ms.`)),
380+
timeout
381+
)
367382
)
368-
)
369383
: new Promise<void>(() => {
370-
/* never */
371-
});
384+
/* never */
385+
});
372386
const waitUntilTask = new Promise<void>((resolve) => {
373387
let candidate = find(what, this.availableBoards);
374388
if (candidate) {
@@ -406,7 +420,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
406420
const availableBoards: AvailableBoard[] = [];
407421
const attachedBoards = this._attachedBoards.filter(({ port }) => !!port);
408422
const availableBoardPorts = availablePorts.filter((port) => {
409-
if (port.protocol === "serial") {
423+
if (port.protocol === 'serial') {
410424
// We always show all serial ports, even if there
411425
// is no recognized board connected to it
412426
return true;
@@ -424,8 +438,12 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
424438
});
425439

426440
for (const boardPort of availableBoardPorts) {
427-
let board = attachedBoards.find(({ port }) => Port.sameAs(boardPort, port));
428-
const lastSelectedBoard = await this.getLastSelectedBoardOnPort(boardPort);
441+
const board = attachedBoards.find(({ port }) =>
442+
Port.sameAs(boardPort, port)
443+
);
444+
const lastSelectedBoard = await this.getLastSelectedBoardOnPort(
445+
boardPort
446+
);
429447

430448
let availableBoard = {} as AvailableBoard;
431449
if (board) {
@@ -454,11 +472,16 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
454472
availableBoards.push(availableBoard);
455473
}
456474

457-
if (boardsConfig.selectedBoard && !availableBoards.some(({ selected }) => selected)) {
475+
if (
476+
boardsConfig.selectedBoard &&
477+
!availableBoards.some(({ selected }) => selected)
478+
) {
458479
// If the selected board has the same port of an unknown board
459480
// that is already in availableBoards we might get a duplicate port.
460481
// So we remove the one already in the array and add the selected one.
461-
const found = availableBoards.findIndex(board => board.port?.address === boardsConfig.selectedPort?.address);
482+
const found = availableBoards.findIndex(
483+
(board) => board.port?.address === boardsConfig.selectedPort?.address
484+
);
462485
if (found >= 0) {
463486
availableBoards.splice(found, 1);
464487
}
@@ -475,15 +498,19 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
475498
let hasChanged = availableBoards.length !== currentAvailableBoards.length;
476499
for (let i = 0; !hasChanged && i < availableBoards.length; i++) {
477500
const [left, right] = [availableBoards[i], currentAvailableBoards[i]];
478-
hasChanged = !!AvailableBoard.compare(left, right) || left.selected !== right.selected;
501+
hasChanged =
502+
!!AvailableBoard.compare(left, right) ||
503+
left.selected !== right.selected;
479504
}
480505
if (hasChanged) {
481506
this._availableBoards = availableBoards;
482507
this.onAvailableBoardsChangedEmitter.fire(this._availableBoards);
483508
}
484509
}
485510

486-
protected async getLastSelectedBoardOnPort(port: Port): Promise<Board | undefined> {
511+
protected async getLastSelectedBoardOnPort(
512+
port: Port
513+
): Promise<Board | undefined> {
487514
const key = this.getLastSelectedBoardOnPortKey(port);
488515
return this.getData<Board>(key);
489516
}
@@ -504,8 +531,11 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
504531
]);
505532
}
506533

507-
protected getLastSelectedBoardOnPortKey(port: Port): string {
508-
return `last-selected-board-on-port:${Port.toString(port)}`;
534+
protected getLastSelectedBoardOnPortKey(port: Port | string): string {
535+
// TODO: we lose the port's `protocol` info (`serial`, `network`, etc.) here if the `port` is a `string`.
536+
return `last-selected-board-on-port:${
537+
typeof port === 'string' ? port : Port.toString(port)
538+
}`;
509539
}
510540

511541
protected async loadState(): Promise<void> {
@@ -596,13 +626,22 @@ export namespace AvailableBoard {
596626
// 4. Network with recognized boards
597627
// 5. Other protocols with recognized boards
598628
export const compare = (left: AvailableBoard, right: AvailableBoard) => {
599-
if (left.port?.protocol === "serial" && right.port?.protocol !== "serial") {
629+
if (left.port?.protocol === 'serial' && right.port?.protocol !== 'serial') {
600630
return -1;
601-
} else if (left.port?.protocol !== "serial" && right.port?.protocol === "serial") {
631+
} else if (
632+
left.port?.protocol !== 'serial' &&
633+
right.port?.protocol === 'serial'
634+
) {
602635
return 1;
603-
} else if (left.port?.protocol === "network" && right.port?.protocol !== "network") {
636+
} else if (
637+
left.port?.protocol === 'network' &&
638+
right.port?.protocol !== 'network'
639+
) {
604640
return -1;
605-
} else if (left.port?.protocol !== "network" && right.port?.protocol === "network") {
641+
} else if (
642+
left.port?.protocol !== 'network' &&
643+
right.port?.protocol === 'network'
644+
) {
606645
return 1;
607646
} else if (left.port?.protocol === right.port?.protocol) {
608647
// We show all ports, including those that have guessed
@@ -614,5 +653,5 @@ export namespace AvailableBoard {
614653
}
615654
}
616655
return naturalCompare(left.port?.address!, right.port?.address!);
617-
}
656+
};
618657
}

0 commit comments

Comments
 (0)