@@ -180,8 +180,8 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
180
180
const selectedAvailableBoard = AvailableBoard . is ( selectedBoard )
181
181
? selectedBoard
182
182
: this . _availableBoards . find ( ( availableBoard ) =>
183
- Board . sameAs ( availableBoard , selectedBoard )
184
- ) ;
183
+ Board . sameAs ( availableBoard , selectedBoard )
184
+ ) ;
185
185
if (
186
186
selectedAvailableBoard &&
187
187
selectedAvailableBoard . selected &&
@@ -358,14 +358,14 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
358
358
const timeoutTask =
359
359
! ! timeout && timeout > 0
360
360
? 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
365
364
)
365
+ )
366
366
: new Promise < void > ( ( ) => {
367
- /* never */
368
- } ) ;
367
+ /* never */
368
+ } ) ;
369
369
const waitUntilTask = new Promise < void > ( ( resolve ) => {
370
370
let candidate = find ( what , this . availableBoards ) ;
371
371
if ( candidate ) {
@@ -384,7 +384,6 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
384
384
}
385
385
386
386
protected async reconcileAvailableBoards ( ) : Promise < void > {
387
- const attachedBoards = this . _attachedBoards ;
388
387
const availablePorts = this . _availablePorts ;
389
388
// Unset the port on the user's config, if it is not available anymore.
390
389
if (
@@ -402,51 +401,64 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
402
401
const boardsConfig = this . boardsConfig ;
403
402
const currentAvailableBoards = this . _availableBoards ;
404
403
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
+ } ) ;
407
422
408
423
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 ;
413
428
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 ) {
416
436
// If the selected board is not recognized because it is a 3rd party board: https://github.com/arduino/arduino-cli/issues/623
417
437
// 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 ) ,
432
442
port : boardPort ,
433
- state,
434
- } ) ;
443
+ } ;
435
444
} 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' ) ,
441
447
port : boardPort ,
442
- } ) ;
448
+ state : AvailableBoard . State . incomplete ,
449
+ } ;
443
450
}
451
+ availableBoards . push ( availableBoard ) ;
444
452
}
445
453
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
+ }
450
462
availableBoards . push ( {
451
463
...boardsConfig . selectedBoard ,
452
464
port : boardsConfig . selectedPort ,
@@ -455,28 +467,20 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
455
467
} ) ;
456
468
}
457
469
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 ) ;
467
476
}
468
477
if ( hasChanged ) {
469
- this . _availableBoards = sortedAvailableBoards ;
478
+ this . _availableBoards = availableBoards ;
470
479
this . onAvailableBoardsChangedEmitter . fire ( this . _availableBoards ) ;
471
480
}
472
481
}
473
482
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 > {
480
484
const key = this . getLastSelectedBoardOnPortKey ( port ) ;
481
485
return this . getData < Board > ( key ) ;
482
486
}
@@ -497,11 +501,8 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
497
501
] ) ;
498
502
}
499
503
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 ) } ` ;
505
506
}
506
507
507
508
protected async loadState ( ) : Promise < void > {
@@ -585,35 +586,30 @@ export namespace AvailableBoard {
585
586
return ! ! board . port ;
586
587
}
587
588
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
588
595
export const compare = ( left : AvailableBoard , right : AvailableBoard ) => {
589
- if ( left . selected && ! right . selected ) {
596
+ if ( left . port ?. protocol === "serial" && right . port ?. protocol !== "serial" ) {
590
597
return - 1 ;
591
- }
592
- if ( right . selected && ! left . selected ) {
598
+ } else if ( left . port ?. protocol !== "serial" && right . port ?. protocol === "serial" ) {
593
599
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" ) {
612
601
return - 1 ;
613
- }
614
- if ( ! ! right . selected && ! left . selected ) {
602
+ } else if ( left . port ?. protocol !== "network" && right . port ?. protocol === "network" ) {
615
603
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
+ }
616
612
}
617
- return left . state - right . state ;
618
- } ;
613
+ return naturalCompare ( left . port ?. address ! , right . port ?. address ! ) ;
614
+ }
619
615
}
0 commit comments