@@ -665,6 +665,8 @@ const TunnelPrivacyContextKey = new RawContextKey<TunnelPrivacy | undefined>('tu
665
665
const TunnelViewFocusContextKey = new RawContextKey < boolean > ( 'tunnelViewFocus' , false , nls . localize ( 'tunnel.focusContext' , "Whether the Ports view has focus." ) ) ;
666
666
const TunnelViewSelectionKeyName = 'tunnelViewSelection' ;
667
667
const TunnelViewSelectionContextKey = new RawContextKey < ITunnelItem | undefined > ( TunnelViewSelectionKeyName , undefined , true ) ;
668
+ const TunnelViewMultiSelectionKeyName = 'tunnelViewMultiSelection' ;
669
+ const TunnelViewMultiSelectionContextKey = new RawContextKey < ITunnelItem [ ] | undefined > ( TunnelViewMultiSelectionKeyName , undefined , true ) ;
668
670
const PortChangableContextKey = new RawContextKey < boolean > ( 'portChangable' , false , true ) ;
669
671
const WebContextKey = new RawContextKey < boolean > ( 'isWeb' , isWeb , true ) ;
670
672
@@ -679,6 +681,7 @@ export class TunnelPanel extends ViewPane {
679
681
private tunnelPrivacyContext : IContextKey < TunnelPrivacy | undefined > ;
680
682
private tunnelViewFocusContext : IContextKey < boolean > ;
681
683
private tunnelViewSelectionContext : IContextKey < ITunnelItem | undefined > ;
684
+ private tunnelViewMultiSelectionContext : IContextKey < ITunnelItem [ ] | undefined > ;
682
685
private portChangableContextKey : IContextKey < boolean > ;
683
686
private isEditing : boolean = false ;
684
687
private titleActions : IAction [ ] = [ ] ;
@@ -711,6 +714,7 @@ export class TunnelPanel extends ViewPane {
711
714
this . tunnelPrivacyContext = TunnelPrivacyContextKey . bindTo ( contextKeyService ) ;
712
715
this . tunnelViewFocusContext = TunnelViewFocusContextKey . bindTo ( contextKeyService ) ;
713
716
this . tunnelViewSelectionContext = TunnelViewSelectionContextKey . bindTo ( contextKeyService ) ;
717
+ this . tunnelViewMultiSelectionContext = TunnelViewMultiSelectionContextKey . bindTo ( contextKeyService ) ;
714
718
this . portChangableContextKey = PortChangableContextKey . bindTo ( contextKeyService ) ;
715
719
716
720
const overlayContextKeyService = this . _register ( this . contextKeyService . createOverlay ( [ [ 'view' , TunnelPanel . ID ] ] ) ) ;
@@ -762,7 +766,7 @@ export class TunnelPanel extends ViewPane {
762
766
return item . label ;
763
767
}
764
768
} ,
765
- multipleSelectionSupport : false ,
769
+ multipleSelectionSupport : true ,
766
770
accessibilityProvider : {
767
771
getAriaLabel : ( item : ITunnelItem ) => {
768
772
if ( item instanceof TunnelItem ) {
@@ -783,6 +787,7 @@ export class TunnelPanel extends ViewPane {
783
787
this . _register ( this . table . onContextMenu ( e => this . onContextMenu ( e , actionRunner ) ) ) ;
784
788
this . _register ( this . table . onMouseDblClick ( e => this . onMouseDblClick ( e ) ) ) ;
785
789
this . _register ( this . table . onDidChangeFocus ( e => this . onFocusChanged ( e ) ) ) ;
790
+ this . _register ( this . table . onDidChangeSelection ( e => this . onSelectionChanged ( e ) ) ) ;
786
791
this . _register ( this . table . onDidFocus ( ( ) => this . tunnelViewFocusContext . set ( true ) ) ) ;
787
792
this . _register ( this . table . onDidBlur ( ( ) => this . tunnelViewFocusContext . set ( false ) ) ) ;
788
793
@@ -879,6 +884,15 @@ export class TunnelPanel extends ViewPane {
879
884
}
880
885
}
881
886
887
+ private onSelectionChanged ( event : ITableEvent < ITunnelItem > ) {
888
+ const elements = event . elements ;
889
+ if ( elements . length > 1 ) {
890
+ this . tunnelViewMultiSelectionContext . set ( elements ) ;
891
+ } else {
892
+ this . tunnelViewMultiSelectionContext . set ( undefined ) ;
893
+ }
894
+ }
895
+
882
896
private onContextMenu ( event : ITableContextMenuEvent < ITunnelItem > , actionRunner : ActionRunner ) : void {
883
897
if ( ( event . element !== undefined ) && ! ( event . element instanceof TunnelItem ) ) {
884
898
return ;
@@ -1097,11 +1111,20 @@ namespace ClosePortAction {
1097
1111
1098
1112
export function inlineHandler ( ) : ICommandHandler {
1099
1113
return async ( accessor , arg ) => {
1100
- const context = ( arg !== undefined || arg instanceof TunnelItem ) ? arg : accessor . get ( IContextKeyService ) . getContextKeyValue ( TunnelViewSelectionKeyName ) ;
1101
- if ( context instanceof TunnelItem ) {
1102
- const remoteExplorerService = accessor . get ( IRemoteExplorerService ) ;
1103
- await remoteExplorerService . close ( { host : context . remoteHost , port : context . remotePort } ) ;
1114
+ const contextKeyService = accessor . get ( IContextKeyService ) ;
1115
+ let ports = contextKeyService . getContextKeyValue < ITunnelItem [ ] | undefined > ( TunnelViewMultiSelectionKeyName ) ;
1116
+ if ( ! ports ) {
1117
+ const context = ( arg !== undefined || arg instanceof TunnelItem ) ?
1118
+ arg : contextKeyService . getContextKeyValue < ITunnelItem | undefined > ( TunnelViewSelectionKeyName ) ;
1119
+ if ( context ) {
1120
+ ports = [ context ] ;
1121
+ }
1122
+ }
1123
+ if ( ! ports ) {
1124
+ return ;
1104
1125
}
1126
+ const remoteExplorerService = accessor . get ( IRemoteExplorerService ) ;
1127
+ return Promise . all ( ports . map ( port => remoteExplorerService . close ( { host : port . remoteHost , port : port . remotePort } ) ) ) ;
1105
1128
} ;
1106
1129
}
1107
1130
@@ -1351,10 +1374,14 @@ namespace MakePortPrivateAction {
1351
1374
1352
1375
const tunnelViewCommandsWeightBonus = 10 ; // give our commands a little bit more weight over other default list/tree commands
1353
1376
1377
+ const isForwardedExpr = TunnelTypeContextKey . isEqualTo ( TunnelType . Forwarded ) ;
1378
+ const isForwardedOrDetectedExpr = ContextKeyExpr . or ( isForwardedExpr , TunnelTypeContextKey . isEqualTo ( TunnelType . Detected ) ) ;
1379
+ const isNotMultiSelectionExpr = TunnelViewMultiSelectionContextKey . isEqualTo ( undefined ) ;
1380
+
1354
1381
KeybindingsRegistry . registerCommandAndKeybindingRule ( {
1355
1382
id : LabelTunnelAction . ID ,
1356
1383
weight : KeybindingWeight . WorkbenchContrib + tunnelViewCommandsWeightBonus ,
1357
- when : ContextKeyExpr . and ( TunnelViewFocusContextKey , TunnelTypeContextKey . isEqualTo ( TunnelType . Forwarded ) ) ,
1384
+ when : ContextKeyExpr . and ( TunnelViewFocusContextKey , isForwardedExpr , isNotMultiSelectionExpr ) ,
1358
1385
primary : KeyCode . F2 ,
1359
1386
mac : {
1360
1387
primary : KeyCode . Enter
@@ -1382,7 +1409,7 @@ CommandsRegistry.registerCommand(OpenPortInBrowserCommandPaletteAction.ID, OpenP
1382
1409
KeybindingsRegistry . registerCommandAndKeybindingRule ( {
1383
1410
id : CopyAddressAction . INLINE_ID ,
1384
1411
weight : KeybindingWeight . WorkbenchContrib + tunnelViewCommandsWeightBonus ,
1385
- when : ContextKeyExpr . or ( ContextKeyExpr . and ( TunnelViewFocusContextKey , TunnelTypeContextKey . isEqualTo ( TunnelType . Forwarded ) ) , ContextKeyExpr . and ( TunnelViewFocusContextKey , TunnelTypeContextKey . isEqualTo ( TunnelType . Detected ) ) ) ,
1412
+ when : ContextKeyExpr . and ( TunnelViewFocusContextKey , isForwardedOrDetectedExpr , isNotMultiSelectionExpr ) ,
1386
1413
primary : KeyMod . CtrlCmd | KeyCode . KEY_C ,
1387
1414
handler : CopyAddressAction . inlineHandler ( )
1388
1415
} ) ;
@@ -1427,7 +1454,7 @@ MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({
1427
1454
id : OpenPortInBrowserAction . ID ,
1428
1455
title : OpenPortInBrowserAction . LABEL ,
1429
1456
} ,
1430
- when : ContextKeyExpr . or ( TunnelTypeContextKey . isEqualTo ( TunnelType . Forwarded ) , TunnelTypeContextKey . isEqualTo ( TunnelType . Detected ) )
1457
+ when : ContextKeyExpr . and ( isForwardedOrDetectedExpr , isNotMultiSelectionExpr )
1431
1458
} ) ) ;
1432
1459
MenuRegistry . appendMenuItem ( MenuId . TunnelContext , ( {
1433
1460
group : '._open' ,
@@ -1438,7 +1465,8 @@ MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({
1438
1465
} ,
1439
1466
when : ContextKeyExpr . and (
1440
1467
ContextKeyExpr . or ( WebContextKey . negate ( ) , TunnelPrivacyContextKey . isEqualTo ( TunnelPrivacy . Public ) ) ,
1441
- ContextKeyExpr . or ( TunnelTypeContextKey . isEqualTo ( TunnelType . Forwarded ) , TunnelTypeContextKey . isEqualTo ( TunnelType . Detected ) ) )
1468
+ isForwardedOrDetectedExpr ,
1469
+ isNotMultiSelectionExpr )
1442
1470
} ) ) ;
1443
1471
// The group 0_manage is used by extensions, so try not to change it
1444
1472
MenuRegistry . appendMenuItem ( MenuId . TunnelContext , ( {
@@ -1449,7 +1477,7 @@ MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({
1449
1477
title : LabelTunnelAction . LABEL ,
1450
1478
icon : labelPortIcon
1451
1479
} ,
1452
- when : TunnelTypeContextKey . isEqualTo ( TunnelType . Forwarded )
1480
+ when : ContextKeyExpr . and ( isForwardedExpr , isNotMultiSelectionExpr )
1453
1481
} ) ) ;
1454
1482
MenuRegistry . appendMenuItem ( MenuId . TunnelContext , ( {
1455
1483
group : '2_localaddress' ,
@@ -1458,7 +1486,7 @@ MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({
1458
1486
id : CopyAddressAction . INLINE_ID ,
1459
1487
title : CopyAddressAction . INLINE_LABEL ,
1460
1488
} ,
1461
- when : ContextKeyExpr . or ( TunnelTypeContextKey . isEqualTo ( TunnelType . Forwarded ) , TunnelTypeContextKey . isEqualTo ( TunnelType . Detected ) )
1489
+ when : ContextKeyExpr . and ( isForwardedOrDetectedExpr , isNotMultiSelectionExpr )
1462
1490
} ) ) ;
1463
1491
MenuRegistry . appendMenuItem ( MenuId . TunnelContext , ( {
1464
1492
group : '2_localaddress' ,
@@ -1467,7 +1495,7 @@ MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({
1467
1495
id : ChangeLocalPortAction . ID ,
1468
1496
title : ChangeLocalPortAction . LABEL ,
1469
1497
} ,
1470
- when : ContextKeyExpr . and ( TunnelTypeContextKey . isEqualTo ( TunnelType . Forwarded ) , PortChangableContextKey )
1498
+ when : ContextKeyExpr . and ( isForwardedExpr , PortChangableContextKey , isNotMultiSelectionExpr )
1471
1499
} ) ) ;
1472
1500
MenuRegistry . appendMenuItem ( MenuId . TunnelContext , ( {
1473
1501
group : '2_localaddress' ,
@@ -1476,7 +1504,7 @@ MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({
1476
1504
id : MakePortPublicAction . ID ,
1477
1505
title : MakePortPublicAction . LABEL ,
1478
1506
} ,
1479
- when : TunnelPrivacyContextKey . isEqualTo ( TunnelPrivacy . Private )
1507
+ when : ContextKeyExpr . and ( TunnelPrivacyContextKey . isEqualTo ( TunnelPrivacy . Private ) , isNotMultiSelectionExpr )
1480
1508
} ) ) ;
1481
1509
MenuRegistry . appendMenuItem ( MenuId . TunnelContext , ( {
1482
1510
group : '2_localaddress' ,
@@ -1485,7 +1513,7 @@ MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({
1485
1513
id : MakePortPrivateAction . ID ,
1486
1514
title : MakePortPrivateAction . LABEL ,
1487
1515
} ,
1488
- when : TunnelPrivacyContextKey . isEqualTo ( TunnelPrivacy . Public )
1516
+ when : ContextKeyExpr . and ( TunnelPrivacyContextKey . isEqualTo ( TunnelPrivacy . Public ) , isNotMultiSelectionExpr )
1489
1517
} ) ) ;
1490
1518
MenuRegistry . appendMenuItem ( MenuId . TunnelContext , ( {
1491
1519
group : '3_forward' ,
@@ -1524,7 +1552,7 @@ MenuRegistry.appendMenuItem(MenuId.TunnelPortInline, ({
1524
1552
title : LabelTunnelAction . LABEL ,
1525
1553
icon : labelPortIcon
1526
1554
} ,
1527
- when : TunnelTypeContextKey . isEqualTo ( TunnelType . Forwarded )
1555
+ when : isForwardedExpr
1528
1556
} ) ) ;
1529
1557
MenuRegistry . appendMenuItem ( MenuId . TunnelPortInline , ( {
1530
1558
group : '0_manage' ,
@@ -1544,7 +1572,7 @@ MenuRegistry.appendMenuItem(MenuId.TunnelLocalAddressInline, ({
1544
1572
title : CopyAddressAction . INLINE_LABEL ,
1545
1573
icon : copyAddressIcon
1546
1574
} ,
1547
- when : ContextKeyExpr . or ( TunnelTypeContextKey . isEqualTo ( TunnelType . Forwarded ) , TunnelTypeContextKey . isEqualTo ( TunnelType . Detected ) )
1575
+ when : isForwardedOrDetectedExpr
1548
1576
} ) ) ;
1549
1577
MenuRegistry . appendMenuItem ( MenuId . TunnelLocalAddressInline , ( {
1550
1578
order : 0 ,
@@ -1553,7 +1581,7 @@ MenuRegistry.appendMenuItem(MenuId.TunnelLocalAddressInline, ({
1553
1581
title : OpenPortInBrowserAction . LABEL ,
1554
1582
icon : openBrowserIcon
1555
1583
} ,
1556
- when : ContextKeyExpr . or ( TunnelTypeContextKey . isEqualTo ( TunnelType . Forwarded ) , TunnelTypeContextKey . isEqualTo ( TunnelType . Detected ) )
1584
+ when : isForwardedOrDetectedExpr
1557
1585
} ) ) ;
1558
1586
MenuRegistry . appendMenuItem ( MenuId . TunnelLocalAddressInline , ( {
1559
1587
order : 1 ,
@@ -1564,7 +1592,7 @@ MenuRegistry.appendMenuItem(MenuId.TunnelLocalAddressInline, ({
1564
1592
} ,
1565
1593
when : ContextKeyExpr . and (
1566
1594
ContextKeyExpr . or ( WebContextKey . negate ( ) , TunnelPrivacyContextKey . isEqualTo ( TunnelPrivacy . Public ) ) ,
1567
- ContextKeyExpr . or ( TunnelTypeContextKey . isEqualTo ( TunnelType . Forwarded ) , TunnelTypeContextKey . isEqualTo ( TunnelType . Detected ) ) )
1595
+ isForwardedOrDetectedExpr )
1568
1596
} ) ) ;
1569
1597
1570
1598
export const portWithRunningProcessForeground = registerColor ( 'ports.iconRunningProcessForeground' , {
0 commit comments