From 53d3fc8d1bb2efe4d062eef91f3631394b3a73d7 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 22 Jan 2020 10:37:41 +0100 Subject: [PATCH] Add Stop forwarding port command --- .../contrib/remote/browser/tunnelView.ts | 72 ++++++++++++++++--- 1 file changed, 63 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index b12db223085..4ba21ce84cc 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -14,7 +14,7 @@ import { IContextKeyService, IContextKey, RawContextKey, ContextKeyExpr } from ' import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput'; import { ICommandService, ICommandHandler, CommandsRegistry } from 'vs/platform/commands/common/commands'; import { Event, Emitter } from 'vs/base/common/event'; import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; @@ -26,7 +26,7 @@ import { IconLabel } from 'vs/base/browser/ui/iconLabel/iconLabel'; import { ActionRunner, IAction } from 'vs/base/common/actions'; import { IMenuService, MenuId, IMenu, MenuRegistry, MenuItemAction } from 'vs/platform/actions/common/actions'; import { createAndFillInContextMenuActions, createAndFillInActionBarActions, ContextAwareMenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; -import { IRemoteExplorerService, TunnelModel, MakeAddress, TunnelType, ITunnelItem } from 'vs/workbench/services/remote/common/remoteExplorerService'; +import { IRemoteExplorerService, TunnelModel, MakeAddress, TunnelType, ITunnelItem, Tunnel } from 'vs/workbench/services/remote/common/remoteExplorerService'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { InputBox, MessageType } from 'vs/base/browser/ui/inputbox/inputBox'; @@ -116,7 +116,7 @@ export class TunnelViewModel extends Disposable implements ITunnelViewModel { get forwarded(): TunnelItem[] { const forwarded = Array.from(this.model.forwarded.values()).map(tunnel => { - return new TunnelItem(TunnelType.Forwarded, tunnel.remoteHost, tunnel.remotePort, tunnel.localAddress, tunnel.closeable, tunnel.name, tunnel.description); + return TunnelItem.createFromTunnel(tunnel); }); if (this.remoteExplorerService.getEditableData(undefined)) { forwarded.push(this._input); @@ -126,7 +126,7 @@ export class TunnelViewModel extends Disposable implements ITunnelViewModel { get detected(): TunnelItem[] { return Array.from(this.model.detected.values()).map(tunnel => { - return new TunnelItem(TunnelType.Detected, tunnel.remoteHost, tunnel.remotePort, tunnel.localAddress, false, tunnel.name, tunnel.description); + return TunnelItem.createFromTunnel(tunnel, TunnelType.Detected, false); }); } @@ -352,6 +352,10 @@ interface ITunnelGroup { } class TunnelItem implements ITunnelItem { + static createFromTunnel(tunnel: Tunnel, type: TunnelType = TunnelType.Forwarded, closeable?: boolean) { + return new TunnelItem(type, tunnel.remoteHost, tunnel.remotePort, tunnel.localAddress, closeable === undefined ? tunnel.closeable : closeable, tunnel.name, tunnel.description); + } + constructor( public tunnelType: TunnelType, public remoteHost: string, @@ -681,11 +685,37 @@ namespace ForwardPortAction { } } + +interface QuickPickTunnel extends IQuickPickItem { + tunnel?: Tunnel +} + +function makeTunnelPicks(remoteExplorerService: IRemoteExplorerService): QuickPickInput[] { + const picks: QuickPickInput[] = []; + Array.from(remoteExplorerService.tunnelModel.forwarded.values()).forEach(forwarded => { + if (forwarded.closeable) { + const item = TunnelItem.createFromTunnel(forwarded); + picks.push({ + label: item.label, + description: item.description, + tunnel: forwarded + }); + } + }); + if (picks.length === 0) { + picks.push({ + label: nls.localize('remote.tunnel.closeNoPorts', "No ports currently forwarded. Try running the {0} command", ForwardPortAction.LABEL) + }); + } + return picks; +} + namespace ClosePortAction { - export const ID = 'remote.tunnel.close'; + export const INLINE_ID = 'remote.tunnel.closeInline'; + export const COMMANDPALETTE_ID = 'remote.tunnel.closeCommandPalette'; export const LABEL = nls.localize('remote.tunnel.close', "Stop Forwarding Port"); - export function handler(): ICommandHandler { + export function inlineHandler(): ICommandHandler { return async (accessor, arg) => { if (arg instanceof TunnelItem) { const remoteExplorerService = accessor.get(IRemoteExplorerService); @@ -693,6 +723,22 @@ namespace ClosePortAction { } }; } + + export function commandPaletteHandler(): ICommandHandler { + return async (accessor) => { + const quickInputService = accessor.get(IQuickInputService); + const remoteExplorerService = accessor.get(IRemoteExplorerService); + const commandService = accessor.get(ICommandService); + + const picks: QuickPickInput[] = makeTunnelPicks(remoteExplorerService); + const result = await quickInputService.pick(picks, { placeHolder: nls.localize('remote.tunnel.closePlaceholder', "Choose a port to stop forwarding") }); + if (result && result.tunnel) { + await remoteExplorerService.close({ host: result.tunnel.remoteHost, port: result.tunnel.remotePort }); + } else if (result) { + await commandService.executeCommand(ForwardPortAction.COMMANDPALETTE_ID); + } + }; + } } namespace OpenPortInBrowserAction { @@ -749,11 +795,19 @@ namespace RefreshTunnelViewAction { CommandsRegistry.registerCommand(LabelTunnelAction.ID, LabelTunnelAction.handler()); CommandsRegistry.registerCommand(ForwardPortAction.INLINE_ID, ForwardPortAction.inlineHandler()); CommandsRegistry.registerCommand(ForwardPortAction.COMMANDPALETTE_ID, ForwardPortAction.commandPaletteHandler()); -CommandsRegistry.registerCommand(ClosePortAction.ID, ClosePortAction.handler()); +CommandsRegistry.registerCommand(ClosePortAction.INLINE_ID, ClosePortAction.inlineHandler()); +CommandsRegistry.registerCommand(ClosePortAction.COMMANDPALETTE_ID, ClosePortAction.commandPaletteHandler()); CommandsRegistry.registerCommand(OpenPortInBrowserAction.ID, OpenPortInBrowserAction.handler()); CommandsRegistry.registerCommand(CopyAddressAction.ID, CopyAddressAction.handler()); CommandsRegistry.registerCommand(RefreshTunnelViewAction.ID, RefreshTunnelViewAction.handler()); +MenuRegistry.appendMenuItem(MenuId.CommandPalette, ({ + command: { + id: ClosePortAction.COMMANDPALETTE_ID, + title: ClosePortAction.LABEL + }, + when: forwardedPortsViewEnabled +})); MenuRegistry.appendMenuItem(MenuId.CommandPalette, ({ command: { id: ForwardPortAction.COMMANDPALETTE_ID, @@ -819,7 +873,7 @@ MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({ group: '0_manage', order: 3, command: { - id: ClosePortAction.ID, + id: ClosePortAction.INLINE_ID, title: ClosePortAction.LABEL, }, when: TunnelCloseableContextKey @@ -846,7 +900,7 @@ MenuRegistry.appendMenuItem(MenuId.TunnelInline, ({ MenuRegistry.appendMenuItem(MenuId.TunnelInline, ({ order: 2, command: { - id: ClosePortAction.ID, + id: ClosePortAction.INLINE_ID, title: ClosePortAction.LABEL, icon: { id: 'codicon/x' } },