@@ -9,12 +9,18 @@ import { nls } from '@theia/core/lib/common/nls';
99import React from '@theia/core/shared/react' ;
1010import ReactDOM from '@theia/core/shared/react-dom' ;
1111import classNames from 'classnames' ;
12- import { unknownBoard } from '../../common/protocol' ;
12+ import {
13+ boardIdentifierEquals ,
14+ createPlatformIdentifier ,
15+ serializePlatformIdentifier ,
16+ unknownBoard ,
17+ } from '../../common/protocol' ;
1318import {
1419 BoardListItem ,
1520 getInferredBoardOrBoard ,
1621 InferredBoardListItem ,
1722 isInferredBoardListItem ,
23+ isMultiBoardsBoardListItem ,
1824} from '../../common/protocol/board-list' ;
1925import {
2026 BoardListUI ,
@@ -38,7 +44,10 @@ export namespace BoardsDropDown {
3844 }
3945}
4046
41- export class BoardListDropDown extends React . Component < BoardsDropDown . Props > {
47+ export class BoardListDropDown extends React . Component <
48+ BoardsDropDown . Props ,
49+ { expandedItems : BoardListItem [ ] }
50+ > {
4251 private dropdownElement : HTMLElement ;
4352 private listRef : React . RefObject < HTMLDivElement > ;
4453
@@ -52,6 +61,7 @@ export class BoardListDropDown extends React.Component<BoardsDropDown.Props> {
5261 document . body . appendChild ( list ) ;
5362 this . dropdownElement = list ;
5463 }
64+ this . state = { expandedItems : [ ] } ;
5565 }
5666
5767 override componentDidUpdate ( prevProps : BoardsDropDown . Props ) : void {
@@ -123,7 +133,6 @@ export class BoardListDropDown extends React.Component<BoardsDropDown.Props> {
123133 const board = getInferredBoardOrBoard ( item ) ;
124134 const boardLabel = board ?. name ?? unknownBoard ;
125135 const boardFqbn = board ?. fqbn ;
126- const vendor = item . metadata ?. vendor ;
127136 const onDefaultAction = ( ) => {
128137 if ( board ) {
129138 onSelect ( { selectedBoard : board , selectedPort : port } ) ;
@@ -166,18 +175,107 @@ export class BoardListDropDown extends React.Component<BoardsDropDown.Props> {
166175 < div className = "arduino-boards-dropdown-item--board-label noWrapInfo noselect" >
167176 { boardLabel }
168177 </ div >
169- { vendor && < div className = "vendor" > { vendor } </ div > }
170178 </ div >
171179 < div className = "arduino-boards-dropdown-item--port-label noWrapInfo noselect" >
172180 { port . addressLabel }
173181 </ div >
182+ { this . renderVendors ( item , onSelect ) }
174183 </ div >
175184 { isInferredBoardListItem ( item ) &&
176185 this . renderActions ( item , onSelect , onEdit ) }
177186 </ div >
178187 ) ;
179188 }
180189
190+ private renderVendors (
191+ item : BoardListItem ,
192+ onSelect : SelectBoardsConfigAction
193+ ) : React . ReactNode {
194+ if ( ! isMultiBoardsBoardListItem ( item ) ) {
195+ return undefined ;
196+ }
197+ const inferredBoard = isInferredBoardListItem ( item )
198+ ? item . inferredBoard
199+ : undefined ;
200+ // If the inferred board is not one of the discovered ones, do not show the vendors.
201+ // It's the same use-case when there is one discoverd board, but the user overrides it.
202+ if (
203+ inferredBoard &&
204+ item . allBoards . every (
205+ ( otherBoard ) => ! boardIdentifierEquals ( inferredBoard , otherBoard )
206+ )
207+ ) {
208+ return undefined ;
209+ }
210+ const expanded = this . state . expandedItems . includes ( item ) ;
211+ const boards = ! expanded
212+ ? [ inferredBoard ? inferredBoard : item . board ]
213+ : item . allBoards ;
214+ return (
215+ < div className = "arduino-boards-dropdown-item--vendors noWrapInfo noselect" >
216+ < div className = { TabBarToolbar . Styles . TAB_BAR_TOOLBAR } >
217+ < div
218+ className = { `${ TabBarToolbar . Styles . TAB_BAR_TOOLBAR_ITEM } enabled` }
219+ >
220+ { expanded ? (
221+ < div
222+ id = "collapse"
223+ className = { codicon ( 'chevron-down' , true ) }
224+ onClick = { ( event ) => {
225+ event . preventDefault ( ) ;
226+ event . stopPropagation ( ) ;
227+ this . setState ( ( prevState ) => ( {
228+ expandedItems : prevState . expandedItems . filter (
229+ ( expendedItem ) => item !== expendedItem
230+ ) ,
231+ } ) ) ;
232+ } }
233+ />
234+ ) : (
235+ < div
236+ id = "expand"
237+ className = { codicon ( 'chevron-right' , true ) }
238+ onClick = { ( event ) => {
239+ event . preventDefault ( ) ;
240+ event . stopPropagation ( ) ;
241+ this . setState ( ( prevState ) => ( {
242+ expandedItems : prevState . expandedItems . concat ( item ) ,
243+ } ) ) ;
244+ } }
245+ />
246+ ) }
247+ </ div >
248+ </ div >
249+ < div >
250+ { boards . map ( ( board ) => {
251+ const platformId = createPlatformIdentifier ( board ) ;
252+ if ( ! platformId ) {
253+ return undefined ;
254+ }
255+ return (
256+ < div
257+ key = { board . fqbn }
258+ className = "vendor"
259+ onClick = { ( event ) => {
260+ event . preventDefault ( ) ;
261+ event . stopPropagation ( ) ;
262+ this . setState ( ( prevState ) => ( {
263+ expandedItems : prevState . expandedItems . filter (
264+ ( expendedItem ) => item !== expendedItem
265+ ) ,
266+ } ) ) ;
267+ onSelect ( { selectedBoard : board , selectedPort : item . port } ) ;
268+ } }
269+ >
270+ { serializePlatformIdentifier ( platformId ) }
271+ </ div >
272+ ) ;
273+ } ) }
274+ </ div >
275+ </ div >
276+ ) ;
277+ }
278+
181279 private renderActions (
182280 inferredItem : InferredBoardListItem ,
183281 onRevert : SelectBoardsConfigAction ,
@@ -210,9 +308,10 @@ export class BoardListDropDown extends React.Component<BoardsDropDown.Props> {
210308 className = { codicon ( 'discard' , true ) }
211309 title = { nls . localize (
212310 'arduino/board/revertBoardsConfig' ,
213- "Revert the selected '{0}' board to '{1}' detected on '{2}'" ,
214- inferredItem . inferredBoard . name ,
215- inferredItem . board . name ,
311+ "Use '{0}' discovered on '{1}'" ,
312+ `${ inferredItem . board . name } ${
313+ inferredItem . board . fqbn ? ` (${ inferredItem . board . fqbn } )` : ''
314+ } `,
216315 port . address
217316 ) }
218317 onClick = { ( event ) => {
0 commit comments