@@ -65,6 +65,10 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
6565 protected _availablePorts : Port [ ] = [ ] ;
6666 protected _availableBoards : AvailableBoard [ ] = [ ] ;
6767
68+ private lastBoardsConfigOnUpload : BoardsConfig . Config | undefined ;
69+ private lastAvailablePortsOnUpload : Port [ ] | undefined ;
70+ private boardConfigToAutoSelect : BoardsConfig . Config | undefined ;
71+
6872 /**
6973 * Unlike `onAttachedBoardsChanged` this event fires when the user modifies the selected board in the IDE.\
7074 * This event also fires, when the boards package was not available for the currently selected board,
@@ -112,6 +116,84 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
112116 return this . _reconciled . promise ;
113117 }
114118
119+ snapshotBoardDiscoveryOnUpload ( ) : void {
120+ this . lastBoardsConfigOnUpload = this . _boardsConfig ;
121+ this . lastAvailablePortsOnUpload = this . _availablePorts ;
122+ }
123+
124+ clearBoardDiscoverySnapshot ( ) : void {
125+ this . lastBoardsConfigOnUpload = undefined ;
126+ this . lastAvailablePortsOnUpload = undefined ;
127+ }
128+
129+ private portToAutoSelectCanBeDerived ( ) : boolean {
130+ return Boolean (
131+ this . lastBoardsConfigOnUpload && this . lastAvailablePortsOnUpload
132+ ) ;
133+ }
134+
135+ attemptPostUploadAutoSelect ( ) : void {
136+ setTimeout ( ( ) => {
137+ if ( this . portToAutoSelectCanBeDerived ( ) ) {
138+ this . attemptAutoSelect ( {
139+ ports : this . _availablePorts ,
140+ boards : this . _availableBoards ,
141+ } ) ;
142+ }
143+ } , 2000 ) ; // 2 second delay same as IDE 1.8
144+ }
145+
146+ private attemptAutoSelect (
147+ newState : AttachedBoardsChangeEvent [ 'newState' ]
148+ ) : void {
149+ this . deriveBoardConfigToAutoSelect ( newState ) ;
150+ this . tryReconnect ( ) ;
151+ }
152+
153+ private deriveBoardConfigToAutoSelect (
154+ newState : AttachedBoardsChangeEvent [ 'newState' ]
155+ ) : void {
156+ if ( ! this . portToAutoSelectCanBeDerived ( ) ) {
157+ this . boardConfigToAutoSelect = undefined ;
158+ return ;
159+ }
160+
161+ const oldPorts = this . lastAvailablePortsOnUpload ! ;
162+ const { ports : newPorts , boards : newBoards } = newState ;
163+
164+ const appearedPorts =
165+ oldPorts . length > 0
166+ ? newPorts . filter ( ( newPort : Port ) =>
167+ oldPorts . every ( ( oldPort : Port ) => ! Port . sameAs ( newPort , oldPort ) )
168+ )
169+ : newPorts ;
170+
171+ for ( const port of appearedPorts ) {
172+ const boardOnAppearedPort = newBoards . find ( ( board : Board ) =>
173+ Port . sameAs ( board . port , port )
174+ ) ;
175+
176+ const lastBoardsConfigOnUpload = this . lastBoardsConfigOnUpload ! ;
177+
178+ if (
179+ boardOnAppearedPort &&
180+ lastBoardsConfigOnUpload . selectedBoard &&
181+ Board . sameAs (
182+ boardOnAppearedPort ,
183+ lastBoardsConfigOnUpload . selectedBoard
184+ )
185+ ) {
186+ this . clearBoardDiscoverySnapshot ( ) ;
187+
188+ this . boardConfigToAutoSelect = {
189+ selectedBoard : boardOnAppearedPort ,
190+ selectedPort : port ,
191+ } ;
192+ return ;
193+ }
194+ }
195+ }
196+
115197 protected notifyAttachedBoardsChanged (
116198 event : AttachedBoardsChangeEvent
117199 ) : void {
@@ -120,10 +202,18 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
120202 this . logger . info ( AttachedBoardsChangeEvent . toString ( event ) ) ;
121203 this . logger . info ( '------------------------------------------' ) ;
122204 }
205+
123206 this . _attachedBoards = event . newState . boards ;
124207 this . _availablePorts = event . newState . ports ;
125208 this . onAvailablePortsChangedEmitter . fire ( this . _availablePorts ) ;
126- this . reconcileAvailableBoards ( ) . then ( ( ) => this . tryReconnect ( ) ) ;
209+ this . reconcileAvailableBoards ( ) . then ( ( ) => {
210+ const { uploadInProgress } = event ;
211+ // avoid attempting "auto-selection" while an
212+ // upload is in progress
213+ if ( ! uploadInProgress ) {
214+ this . attemptAutoSelect ( event . newState ) ;
215+ }
216+ } ) ;
127217 }
128218
129219 protected notifyPlatformInstalled ( event : { item : BoardsPackage } ) : void {
@@ -239,24 +329,12 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
239329 return true ;
240330 }
241331 }
242- // If we could not find an exact match, we compare the board FQBN-name pairs and ignore the port, as it might have changed.
243- // See documentation on `latestValidBoardsConfig`.
244- for ( const board of this . availableBoards . filter (
245- ( { state } ) => state !== AvailableBoard . State . incomplete
246- ) ) {
247- if (
248- this . latestValidBoardsConfig . selectedBoard . fqbn === board . fqbn &&
249- this . latestValidBoardsConfig . selectedBoard . name === board . name &&
250- this . latestValidBoardsConfig . selectedPort . protocol ===
251- board . port ?. protocol
252- ) {
253- this . boardsConfig = {
254- ...this . latestValidBoardsConfig ,
255- selectedPort : board . port ,
256- } ;
257- return true ;
258- }
259- }
332+
333+ if ( ! this . boardConfigToAutoSelect ) return false ;
334+
335+ this . boardsConfig = this . boardConfigToAutoSelect ;
336+ this . boardConfigToAutoSelect = undefined ;
337+ return true ;
260338 }
261339 return false ;
262340 }
@@ -450,6 +528,11 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
450528 const board = attachedBoards . find ( ( { port } ) =>
451529 Port . sameAs ( boardPort , port )
452530 ) ;
531+ // "board" will always be falsey for
532+ // port that was originally mapped
533+ // to unknown board and then selected
534+ // manually by user
535+
453536 const lastSelectedBoard = await this . getLastSelectedBoardOnPort (
454537 boardPort
455538 ) ;
@@ -468,7 +551,9 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
468551 availableBoard = {
469552 ...lastSelectedBoard ,
470553 state : AvailableBoard . State . guessed ,
471- selected : BoardsConfig . Config . sameAs ( boardsConfig , lastSelectedBoard ) ,
554+ selected :
555+ BoardsConfig . Config . sameAs ( boardsConfig , lastSelectedBoard ) &&
556+ Port . sameAs ( boardPort , boardsConfig . selectedPort ) , // to avoid double selection
472557 port : boardPort ,
473558 } ;
474559 } else {
@@ -483,7 +568,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
483568
484569 if (
485570 boardsConfig . selectedBoard &&
486- ! availableBoards . some ( ( { selected } ) => selected )
571+ availableBoards . every ( ( { selected } ) => ! selected )
487572 ) {
488573 // If the selected board has the same port of an unknown board
489574 // that is already in availableBoards we might get a duplicate port.
0 commit comments