9
9
MenuButton ,
10
10
MenuItem ,
11
11
MenuList ,
12
- Tooltip
12
+ Tooltip ,
13
+ Text
13
14
} from '@chakra-ui/react' ;
14
15
import { useMessage } from '@sealos/ui' ;
15
16
import { useTranslations } from 'next-intl' ;
@@ -44,6 +45,13 @@ export interface JetBrainsGuideData {
44
45
configHost : string ;
45
46
}
46
47
48
+ interface MenuItem {
49
+ value : string ;
50
+ menuLabel : string ;
51
+ group ?: string ;
52
+ options ?: { value : string ; menuLabel : string } [ ] ;
53
+ }
54
+
47
55
const IDEButton = ( {
48
56
devboxName,
49
57
runtimeType,
@@ -138,13 +146,13 @@ const IDEButton = ({
138
146
>
139
147
{ isBigButton ? (
140
148
< Flex alignItems = { 'center' } w = { '100%' } justifyContent = { 'center' } >
141
- < MyIcon name = { currentIDE } w = { '25%' } />
142
- < Box w = { '75%' } textAlign = { 'center' } px = { '7px' } >
149
+ < MyIcon name = { getIconName ( currentIDE ) } w = { '25%' } />
150
+ < Box w = { '75%' } textAlign = { 'center' } px = { '7px' } whiteSpace = "nowrap" >
143
151
{ ideObj [ currentIDE ] ?. label }
144
152
</ Box >
145
153
</ Flex >
146
154
) : (
147
- < MyIcon name = { currentIDE } w = { '16px' } />
155
+ < MyIcon name = { getIconName ( currentIDE ) } w = { '16px' } />
148
156
) }
149
157
</ Button >
150
158
</ Tooltip >
@@ -182,32 +190,90 @@ const IDEButton = ({
182
190
fontWeight = { 500 }
183
191
fontSize = { '12px' }
184
192
defaultValue = { currentIDE }
185
- px = { 1 }
193
+ p = { '6px' }
194
+ w = { '186px' }
195
+ display = { 'flex' }
196
+ flexDirection = { 'column' }
197
+ gap = { '4px' }
186
198
>
187
- { menuItems . map ( ( item ) => (
188
- < MenuItem
189
- key = { item . value }
190
- value = { item . value }
191
- onClick = { ( ) => {
192
- updateDevboxIDE ( item . value as IDEType , devboxName ) ;
193
- handleGotoIDE ( item . value as IDEType ) ;
194
- } }
195
- icon = { < MyIcon name = { item . value as IDEType } w = { '16px' } /> }
196
- _hover = { {
197
- bg : '#1118240D' ,
198
- borderRadius : 4
199
- } }
200
- _focus = { {
201
- bg : '#1118240D' ,
202
- borderRadius : 4
203
- } }
204
- >
205
- < Flex justifyContent = "space-between" alignItems = "center" width = "100%" >
206
- { item ?. menuLabel }
207
- { currentIDE === item . value && < MyIcon name = "check" w = { '16px' } /> }
208
- </ Flex >
209
- </ MenuItem >
210
- ) ) }
199
+ { menuItems . map ( ( item ) => {
200
+ if ( item . group === 'trae' ) {
201
+ return (
202
+ < Flex key = { item . value } gap = { '4px' } >
203
+ { item . options ?. map ( ( option ) => (
204
+ < MenuItem
205
+ h = { '30px' }
206
+ w = { '90px' }
207
+ borderRadius = { '4px' }
208
+ bg = { 'grayModern.50' }
209
+ key = { option . value }
210
+ value = { option . value }
211
+ onClick = { ( ) => {
212
+ updateDevboxIDE ( option . value as IDEType , devboxName ) ;
213
+ handleGotoIDE ( option . value as IDEType ) ;
214
+ } }
215
+ _hover = { {
216
+ bg : 'grayModern.150' ,
217
+ borderRadius : 4
218
+ } }
219
+ _focus = { {
220
+ bg : '#1118240D' ,
221
+ borderRadius : 4
222
+ } }
223
+ { ...( currentIDE === option . value && {
224
+ bg : 'grayModern.50' ,
225
+ borderWidth : '1px' ,
226
+ borderColor : 'brightBlue.500' ,
227
+ color : 'brightBlue.600'
228
+ } ) }
229
+ >
230
+ < Flex alignItems = "center" w = { '100%' } >
231
+ < MyIcon name = "trae" w = { '16px' } mr = { '6px' } />
232
+ < Text whiteSpace = "nowrap" mr = { '2px' } >
233
+ { option . menuLabel }
234
+ </ Text >
235
+ </ Flex >
236
+ </ MenuItem >
237
+ ) ) }
238
+ </ Flex >
239
+ ) ;
240
+ } else {
241
+ return (
242
+ < MenuItem
243
+ borderRadius = { '4px' }
244
+ key = { item . value }
245
+ value = { item . value }
246
+ bg = { 'grayModern.50' }
247
+ fontWeight = { 500 }
248
+ onClick = { ( ) => {
249
+ updateDevboxIDE ( item . value as IDEType , devboxName ) ;
250
+ handleGotoIDE ( item . value as IDEType ) ;
251
+ } }
252
+ _hover = { {
253
+ bg : 'grayModern.150' ,
254
+ borderRadius : 4
255
+ } }
256
+ _focus = { {
257
+ bg : '#1118240D' ,
258
+ borderRadius : 4
259
+ } }
260
+ { ...( currentIDE === item . value && {
261
+ bg : 'grayModern.50' ,
262
+ borderWidth : '1px' ,
263
+ borderColor : 'brightBlue.500' ,
264
+ color : 'brightBlue.600'
265
+ } ) }
266
+ >
267
+ < Flex alignItems = "center" w = { '100%' } >
268
+ < MyIcon name = { getIconName ( item . value as IDEType ) } w = { '16px' } mr = { '6px' } />
269
+ < Text whiteSpace = "nowrap" overflow = "hidden" textOverflow = "ellipsis" mr = { '4px' } >
270
+ { item ?. menuLabel }
271
+ </ Text >
272
+ </ Flex >
273
+ </ MenuItem >
274
+ ) ;
275
+ }
276
+ } ) }
211
277
</ MenuList >
212
278
</ Menu >
213
279
{ ! ! onOpenJetbrainsModal && ! ! jetbrainsGuideData && (
@@ -228,52 +294,99 @@ export const ideObj = {
228
294
icon : 'vscode' ,
229
295
prefix : 'vscode://' ,
230
296
value : 'vscode' ,
231
- sortId : 0
297
+ sortId : 0 ,
298
+ group : ''
232
299
} ,
233
300
vscodeInsiders : {
234
301
label : 'Insiders' ,
235
302
menuLabel : 'VSCode Insiders' ,
236
303
icon : 'vscodeInsiders' ,
237
304
prefix : 'vscode-insiders://' ,
238
305
value : 'vscodeInsiders' ,
239
- sortId : 1
306
+ sortId : 1 ,
307
+ group : ''
240
308
} ,
241
309
cursor : {
242
310
label : 'Cursor' ,
243
311
menuLabel : 'Cursor' ,
244
312
icon : 'cursor' ,
245
313
prefix : 'cursor://' ,
246
314
value : 'cursor' ,
247
- sortId : 2
315
+ sortId : 2 ,
316
+ group : ''
248
317
} ,
249
318
windsurf : {
250
319
label : 'Windsurf' ,
251
320
menuLabel : 'Windsurf' ,
252
321
icon : 'windsurf' ,
253
322
prefix : 'windsurf://' ,
254
323
value : 'windsurf' ,
255
- sortId : 3
324
+ sortId : 3 ,
325
+ group : ''
256
326
} ,
257
327
trae : {
258
328
label : 'Trae' ,
259
329
menuLabel : 'Trae' ,
260
330
icon : 'trae' ,
261
331
prefix : 'trae://' ,
262
332
value : 'trae' ,
263
- sortId : 4
333
+ sortId : 4 ,
334
+ group : 'trae'
335
+ } ,
336
+ traeCN : {
337
+ label : 'Trae CN' ,
338
+ menuLabel : 'Trae CN' ,
339
+ icon : 'trae' ,
340
+ prefix : 'trae-cn://' ,
341
+ value : 'traeCN' ,
342
+ sortId : 4 ,
343
+ group : 'trae'
264
344
} ,
265
345
jetbrains : {
266
346
label : 'JetBrains' ,
267
347
icon : 'jetbrains' ,
268
348
menuLabel : 'JetBrains' ,
269
349
prefix : '-' ,
270
350
value : 'jetbrains' ,
271
- sortId : 4
351
+ sortId : 5 ,
352
+ group : ''
272
353
}
273
354
} as const ;
274
355
356
+ const getIconName = (
357
+ ide : IDEType
358
+ ) :
359
+ | 'link'
360
+ | 'search'
361
+ | 'template'
362
+ | 'ellipse'
363
+ | 'cursor'
364
+ | 'vscode'
365
+ | 'vscodeInsiders'
366
+ | 'windsurf'
367
+ | 'trae'
368
+ | 'jetbrains' => {
369
+ if ( ide === 'traeCN' ) return 'trae' ;
370
+ return ide ;
371
+ } ;
372
+
275
373
const menuItems = Object . values ( ideObj )
276
374
. sort ( ( a , b ) => a . sortId - b . sortId )
277
- . map ( ( { value, menuLabel } ) => ( { value, menuLabel } ) ) ;
375
+ . reduce ( ( acc , item ) => {
376
+ if ( item . group === 'trae' && ! acc . some ( ( i ) => i . group === 'trae' ) ) {
377
+ acc . push ( {
378
+ value : 'trae-group' ,
379
+ menuLabel : 'Trae' ,
380
+ group : 'trae' ,
381
+ options : [
382
+ { value : 'trae' , menuLabel : 'Trae' } ,
383
+ { value : 'traeCN' , menuLabel : 'Trae CN' }
384
+ ]
385
+ } ) ;
386
+ } else if ( item . group === '' ) {
387
+ acc . push ( { value : item . value , menuLabel : item . menuLabel } ) ;
388
+ }
389
+ return acc ;
390
+ } , [ ] as MenuItem [ ] ) ;
278
391
279
392
export default IDEButton ;
0 commit comments