@@ -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