@codingame/monaco-vscode-1b4486de-4fe4-59c4-9e6d-34f265ff6625-common 12.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/empty.js +1 -0
- package/package.json +41 -0
- package/vscode/src/vs/workbench/contrib/externalUriOpener/common/externalUriOpenerService.d.ts +44 -0
- package/vscode/src/vs/workbench/contrib/externalUriOpener/common/externalUriOpenerService.js +167 -0
- package/vscode/src/vs/workbench/contrib/remote/browser/media/tunnelView.css.js +6 -0
- package/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.d.ts +66 -0
- package/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.js +847 -0
- package/vscode/src/vs/workbench/contrib/remote/browser/remoteIcons.d.ts +17 -0
- package/vscode/src/vs/workbench/contrib/remote/browser/remoteIcons.js +24 -0
- package/vscode/src/vs/workbench/contrib/remote/browser/tunnelView.d.ts +189 -0
- package/vscode/src/vs/workbench/contrib/remote/browser/tunnelView.js +1745 -0
- package/vscode/src/vs/workbench/contrib/remote/browser/urlFinder.d.ts +21 -0
- package/vscode/src/vs/workbench/contrib/remote/browser/urlFinder.js +110 -0
@@ -0,0 +1,1745 @@
|
|
1
|
+
|
2
|
+
import { __decorate, __param } from 'vscode/external/tslib/tslib.es6';
|
3
|
+
import './media/tunnelView.css.js';
|
4
|
+
import { localize, localize2 } from 'vscode/vscode/vs/nls';
|
5
|
+
import { append, $, addStandardDisposableListener, EventType, addDisposableListener, clearNode } from 'vscode/vscode/vs/base/browser/dom';
|
6
|
+
import { IViewDescriptorService } from 'vscode/vscode/vs/workbench/common/views.service';
|
7
|
+
import { IViewsService } from 'vscode/vscode/vs/workbench/services/views/common/viewsService.service';
|
8
|
+
import { IKeybindingService } from 'vscode/vscode/vs/platform/keybinding/common/keybinding.service';
|
9
|
+
import { IContextViewService, IContextMenuService } from 'vscode/vscode/vs/platform/contextview/browser/contextView.service';
|
10
|
+
import { RawContextKey, ContextKeyExpr } from 'vscode/vscode/vs/platform/contextkey/common/contextkey';
|
11
|
+
import { IContextKeyService } from 'vscode/vscode/vs/platform/contextkey/common/contextkey.service';
|
12
|
+
import { ConfigurationTarget } from 'vscode/vscode/vs/platform/configuration/common/configuration';
|
13
|
+
import { IConfigurationService } from 'vscode/vscode/vs/platform/configuration/common/configuration.service';
|
14
|
+
import { IInstantiationService } from 'vscode/vscode/vs/platform/instantiation/common/instantiation';
|
15
|
+
import { IOpenerService } from 'vscode/vscode/vs/platform/opener/common/opener.service';
|
16
|
+
import { IQuickInputService } from 'vscode/vscode/vs/platform/quickinput/common/quickInput.service';
|
17
|
+
import { CommandsRegistry } from 'vscode/vscode/vs/platform/commands/common/commands';
|
18
|
+
import { ICommandService } from 'vscode/vscode/vs/platform/commands/common/commands.service';
|
19
|
+
import { Event } from 'vscode/vscode/vs/base/common/event';
|
20
|
+
import { IWorkbenchEnvironmentService } from 'vscode/vscode/vs/workbench/services/environment/common/environmentService.service';
|
21
|
+
import { Disposable, DisposableStore, dispose, toDisposable } from 'vscode/vscode/vs/base/common/lifecycle';
|
22
|
+
import { ActionBar } from 'vscode/vscode/vs/base/browser/ui/actionbar/actionbar';
|
23
|
+
import { IconLabel } from 'vscode/vscode/vs/base/browser/ui/iconLabel/iconLabel';
|
24
|
+
import { ActionRunner } from 'vscode/vscode/vs/base/common/actions';
|
25
|
+
import { MenuId, MenuRegistry } from 'vscode/vscode/vs/platform/actions/common/actions';
|
26
|
+
import { IMenuService } from 'vscode/vscode/vs/platform/actions/common/actions.service';
|
27
|
+
import { createActionViewItem, getFlatActionBarActions } from 'vscode/vscode/vs/platform/actions/browser/menuEntryActionViewItem';
|
28
|
+
import { TunnelType, TunnelEditId, TUNNEL_VIEW_ID } from 'vscode/vscode/vs/workbench/services/remote/common/remoteExplorerService';
|
29
|
+
import { IRemoteExplorerService } from 'vscode/vscode/vs/workbench/services/remote/common/remoteExplorerService.service';
|
30
|
+
import { IClipboardService } from 'vscode/vscode/vs/platform/clipboard/common/clipboardService.service';
|
31
|
+
import 'vscode/vscode/vs/platform/notification/common/notification';
|
32
|
+
import { INotificationService } from 'vscode/vscode/vs/platform/notification/common/notification.service';
|
33
|
+
import { InputBox, MessageType } from 'vscode/vscode/vs/base/browser/ui/inputbox/inputBox';
|
34
|
+
import { createSingleCallFunction } from 'vscode/vscode/vs/base/common/functional';
|
35
|
+
import { KeyCode, KeyMod } from 'vscode/vscode/vs/base/common/keyCodes';
|
36
|
+
import { IThemeService } from 'vscode/vscode/vs/platform/theme/common/themeService.service';
|
37
|
+
import { ThemeIcon } from 'vscode/vscode/vs/base/common/themables';
|
38
|
+
import { ViewPane } from '@codingame/monaco-vscode-65619f8f-0eab-5d8b-855a-43b6353fe527-common/vscode/vs/workbench/browser/parts/views/viewPane';
|
39
|
+
import { URI } from 'vscode/vscode/vs/base/common/uri';
|
40
|
+
import { TunnelProtocol, TunnelPrivacyId, isLocalhost, isAllInterfaces } from 'vscode/vscode/vs/platform/tunnel/common/tunnel';
|
41
|
+
import { ITunnelService } from 'vscode/vscode/vs/platform/tunnel/common/tunnel.service';
|
42
|
+
import { SyncDescriptor } from 'vscode/vscode/vs/platform/instantiation/common/descriptors';
|
43
|
+
import { KeybindingsRegistry, KeybindingWeight } from 'vscode/vscode/vs/platform/keybinding/common/keybindingsRegistry';
|
44
|
+
import { ITelemetryService } from 'vscode/vscode/vs/platform/telemetry/common/telemetry.service';
|
45
|
+
import { ActionViewItem } from 'vscode/vscode/vs/base/browser/ui/actionbar/actionViewItems';
|
46
|
+
import { privatePortIcon, forwardedPortWithProcessIcon, forwardedPortWithoutProcessIcon, portsViewIcon, labelPortIcon, forwardPortIcon, stopForwardIcon, copyAddressIcon, openBrowserIcon, openPreviewIcon } from './remoteIcons.js';
|
47
|
+
import { IExternalUriOpenerService } from 'vscode/vscode/vs/workbench/contrib/externalUriOpener/common/externalUriOpenerService.service';
|
48
|
+
import { CancellationToken } from 'vscode/vscode/vs/base/common/cancellation';
|
49
|
+
import { isMacintosh } from 'vscode/vscode/vs/base/common/platform';
|
50
|
+
import { WorkbenchTable } from 'vscode/vscode/vs/platform/list/browser/listService';
|
51
|
+
import { Button } from 'vscode/vscode/vs/base/browser/ui/button/button';
|
52
|
+
import { registerColor } from 'vscode/vscode/vs/platform/theme/common/colorUtils';
|
53
|
+
import 'vscode/vscode/vs/platform/theme/common/colors/baseColors';
|
54
|
+
import 'vscode/vscode/vs/platform/theme/common/colors/chartsColors';
|
55
|
+
import 'vscode/vscode/vs/platform/theme/common/colors/editorColors';
|
56
|
+
import 'vscode/vscode/vs/platform/theme/common/colors/inputColors';
|
57
|
+
import 'vscode/vscode/vs/platform/theme/common/colors/listColors';
|
58
|
+
import 'vscode/vscode/vs/platform/theme/common/colors/menuColors';
|
59
|
+
import 'vscode/vscode/vs/platform/theme/common/colors/minimapColors';
|
60
|
+
import 'vscode/vscode/vs/platform/theme/common/colors/miscColors';
|
61
|
+
import 'vscode/vscode/vs/platform/theme/common/colors/quickpickColors';
|
62
|
+
import 'vscode/vscode/vs/platform/theme/common/colors/searchColors';
|
63
|
+
import { MarkdownString } from 'vscode/vscode/vs/base/common/htmlContent';
|
64
|
+
import { STATUS_BAR_REMOTE_ITEM_BACKGROUND } from 'vscode/vscode/vs/workbench/common/theme';
|
65
|
+
import { Codicon } from 'vscode/vscode/vs/base/common/codicons';
|
66
|
+
import { defaultButtonStyles, defaultInputBoxStyles } from 'vscode/vscode/vs/platform/theme/browser/defaultStyles';
|
67
|
+
import { TunnelSource, makeAddress, parseAddress, mapHasAddressLocalhostOrAllInterfaces, TunnelCloseReason, forwardedPortsViewEnabled } from 'vscode/vscode/vs/workbench/services/remote/common/tunnelModel';
|
68
|
+
import { getDefaultHoverDelegate } from 'vscode/vscode/vs/base/browser/ui/hover/hoverDelegateFactory';
|
69
|
+
import { IHoverService } from 'vscode/vscode/vs/platform/hover/browser/hover.service';
|
70
|
+
import Severity from 'vscode/vscode/vs/base/common/severity';
|
71
|
+
|
72
|
+
var TunnelPanel_1;
|
73
|
+
const openPreviewEnabledContext = ( new RawContextKey('openPreviewEnabled', false));
|
74
|
+
class TunnelTreeVirtualDelegate {
|
75
|
+
constructor(remoteExplorerService) {
|
76
|
+
this.remoteExplorerService = remoteExplorerService;
|
77
|
+
this.headerRowHeight = 22;
|
78
|
+
}
|
79
|
+
getHeight(row) {
|
80
|
+
return (row.tunnelType === TunnelType.Add && !this.remoteExplorerService.getEditableData(undefined)) ? 30 : 22;
|
81
|
+
}
|
82
|
+
}
|
83
|
+
let TunnelViewModel = class TunnelViewModel {
|
84
|
+
constructor(remoteExplorerService, tunnelService) {
|
85
|
+
this.remoteExplorerService = remoteExplorerService;
|
86
|
+
this.tunnelService = tunnelService;
|
87
|
+
this._candidates = ( new Map());
|
88
|
+
this.input = {
|
89
|
+
label: ( localize(8309, "Add Port")),
|
90
|
+
icon: undefined,
|
91
|
+
tunnelType: TunnelType.Add,
|
92
|
+
hasRunningProcess: false,
|
93
|
+
remoteHost: '',
|
94
|
+
remotePort: 0,
|
95
|
+
processDescription: '',
|
96
|
+
tooltipPostfix: '',
|
97
|
+
iconTooltip: '',
|
98
|
+
portTooltip: '',
|
99
|
+
processTooltip: '',
|
100
|
+
originTooltip: '',
|
101
|
+
privacyTooltip: '',
|
102
|
+
source: { source: TunnelSource.User, description: '' },
|
103
|
+
protocol: TunnelProtocol.Http,
|
104
|
+
privacy: {
|
105
|
+
id: TunnelPrivacyId.Private,
|
106
|
+
themeIcon: privatePortIcon.id,
|
107
|
+
label: ( localize(8310, "Private"))
|
108
|
+
},
|
109
|
+
strip: () => undefined
|
110
|
+
};
|
111
|
+
this.model = remoteExplorerService.tunnelModel;
|
112
|
+
this.onForwardedPortsChanged = Event.any(this.model.onForwardPort, this.model.onClosePort, this.model.onPortName, this.model.onCandidatesChanged);
|
113
|
+
}
|
114
|
+
get all() {
|
115
|
+
const result = [];
|
116
|
+
this._candidates = ( new Map());
|
117
|
+
this.model.candidates.forEach(candidate => {
|
118
|
+
this._candidates.set(makeAddress(candidate.host, candidate.port), candidate);
|
119
|
+
});
|
120
|
+
if ((this.model.forwarded.size > 0) || this.remoteExplorerService.getEditableData(undefined)) {
|
121
|
+
result.push(...this.forwarded);
|
122
|
+
}
|
123
|
+
if (this.model.detected.size > 0) {
|
124
|
+
result.push(...this.detected);
|
125
|
+
}
|
126
|
+
result.push(this.input);
|
127
|
+
return result;
|
128
|
+
}
|
129
|
+
addProcessInfoFromCandidate(tunnelItem) {
|
130
|
+
const key = makeAddress(tunnelItem.remoteHost, tunnelItem.remotePort);
|
131
|
+
if (( this._candidates.has(key))) {
|
132
|
+
tunnelItem.processDescription = this._candidates.get(key).detail;
|
133
|
+
}
|
134
|
+
}
|
135
|
+
get forwarded() {
|
136
|
+
const forwarded = ( Array.from(( this.model.forwarded.values())).map(tunnel => {
|
137
|
+
const tunnelItem = TunnelItem.createFromTunnel(this.remoteExplorerService, this.tunnelService, tunnel);
|
138
|
+
this.addProcessInfoFromCandidate(tunnelItem);
|
139
|
+
return tunnelItem;
|
140
|
+
})).sort((a, b) => {
|
141
|
+
if (a.remotePort === b.remotePort) {
|
142
|
+
return a.remoteHost < b.remoteHost ? -1 : 1;
|
143
|
+
}
|
144
|
+
else {
|
145
|
+
return a.remotePort < b.remotePort ? -1 : 1;
|
146
|
+
}
|
147
|
+
});
|
148
|
+
return forwarded;
|
149
|
+
}
|
150
|
+
get detected() {
|
151
|
+
return ( Array.from(( this.model.detected.values())).map(tunnel => {
|
152
|
+
const tunnelItem = TunnelItem.createFromTunnel(this.remoteExplorerService, this.tunnelService, tunnel, TunnelType.Detected, false);
|
153
|
+
this.addProcessInfoFromCandidate(tunnelItem);
|
154
|
+
return tunnelItem;
|
155
|
+
}));
|
156
|
+
}
|
157
|
+
isEmpty() {
|
158
|
+
return (this.detected.length === 0) &&
|
159
|
+
((this.forwarded.length === 0) || (this.forwarded.length === 1 &&
|
160
|
+
(this.forwarded[0].tunnelType === TunnelType.Add) && !this.remoteExplorerService.getEditableData(undefined)));
|
161
|
+
}
|
162
|
+
};
|
163
|
+
TunnelViewModel = ( __decorate([
|
164
|
+
( __param(0, IRemoteExplorerService)),
|
165
|
+
( __param(1, ITunnelService))
|
166
|
+
], TunnelViewModel));
|
167
|
+
function emptyCell(item) {
|
168
|
+
return { label: '', tunnel: item, editId: TunnelEditId.None, tooltip: '' };
|
169
|
+
}
|
170
|
+
class IconColumn {
|
171
|
+
constructor() {
|
172
|
+
this.label = '';
|
173
|
+
this.tooltip = '';
|
174
|
+
this.weight = 1;
|
175
|
+
this.minimumWidth = 40;
|
176
|
+
this.maximumWidth = 40;
|
177
|
+
this.templateId = 'actionbar';
|
178
|
+
}
|
179
|
+
project(row) {
|
180
|
+
if (row.tunnelType === TunnelType.Add) {
|
181
|
+
return emptyCell(row);
|
182
|
+
}
|
183
|
+
const icon = row.processDescription ? forwardedPortWithProcessIcon : forwardedPortWithoutProcessIcon;
|
184
|
+
let tooltip = '';
|
185
|
+
if (row instanceof TunnelItem) {
|
186
|
+
tooltip = `${row.iconTooltip} ${row.tooltipPostfix}`;
|
187
|
+
}
|
188
|
+
return {
|
189
|
+
label: '', icon, tunnel: row, editId: TunnelEditId.None, tooltip
|
190
|
+
};
|
191
|
+
}
|
192
|
+
}
|
193
|
+
class PortColumn {
|
194
|
+
constructor() {
|
195
|
+
this.label = ( localize(8311, "Port"));
|
196
|
+
this.tooltip = ( localize(8312, "The label and remote port number of the forwarded port."));
|
197
|
+
this.weight = 1;
|
198
|
+
this.templateId = 'actionbar';
|
199
|
+
}
|
200
|
+
project(row) {
|
201
|
+
const isAdd = row.tunnelType === TunnelType.Add;
|
202
|
+
const label = row.label;
|
203
|
+
let tooltip = '';
|
204
|
+
if (row instanceof TunnelItem && !isAdd) {
|
205
|
+
tooltip = `${row.portTooltip} ${row.tooltipPostfix}`;
|
206
|
+
}
|
207
|
+
else {
|
208
|
+
tooltip = label;
|
209
|
+
}
|
210
|
+
return {
|
211
|
+
label, tunnel: row, menuId: MenuId.TunnelPortInline,
|
212
|
+
editId: row.tunnelType === TunnelType.Add ? TunnelEditId.New : TunnelEditId.Label, tooltip
|
213
|
+
};
|
214
|
+
}
|
215
|
+
}
|
216
|
+
class LocalAddressColumn {
|
217
|
+
constructor() {
|
218
|
+
this.label = ( localize(8313, "Forwarded Address"));
|
219
|
+
this.tooltip = ( localize(8314, "The address that the forwarded port is available at."));
|
220
|
+
this.weight = 1;
|
221
|
+
this.templateId = 'actionbar';
|
222
|
+
}
|
223
|
+
project(row) {
|
224
|
+
if (row.tunnelType === TunnelType.Add) {
|
225
|
+
return emptyCell(row);
|
226
|
+
}
|
227
|
+
const label = row.localAddress ?? '';
|
228
|
+
let tooltip = label;
|
229
|
+
if (row instanceof TunnelItem) {
|
230
|
+
tooltip = row.tooltipPostfix;
|
231
|
+
}
|
232
|
+
return {
|
233
|
+
label,
|
234
|
+
menuId: MenuId.TunnelLocalAddressInline,
|
235
|
+
tunnel: row,
|
236
|
+
editId: TunnelEditId.LocalPort,
|
237
|
+
tooltip,
|
238
|
+
markdownTooltip: label ? LocalAddressColumn.getHoverText(label) : undefined
|
239
|
+
};
|
240
|
+
}
|
241
|
+
static getHoverText(localAddress) {
|
242
|
+
return function (configurationService) {
|
243
|
+
const editorConf = configurationService.getValue('editor');
|
244
|
+
let clickLabel = '';
|
245
|
+
if (editorConf.multiCursorModifier === 'ctrlCmd') {
|
246
|
+
if (isMacintosh) {
|
247
|
+
clickLabel = ( localize(8315, "option + click"));
|
248
|
+
}
|
249
|
+
else {
|
250
|
+
clickLabel = ( localize(8316, "alt + click"));
|
251
|
+
}
|
252
|
+
}
|
253
|
+
else {
|
254
|
+
if (isMacintosh) {
|
255
|
+
clickLabel = ( localize(8317, "cmd + click"));
|
256
|
+
}
|
257
|
+
else {
|
258
|
+
clickLabel = ( localize(8318, "ctrl + click"));
|
259
|
+
}
|
260
|
+
}
|
261
|
+
const markdown = ( new MarkdownString('', true));
|
262
|
+
const uri = localAddress.startsWith('http') ? localAddress : `http://${localAddress}`;
|
263
|
+
return markdown.appendLink(uri, 'Follow link').appendMarkdown(` (${clickLabel})`);
|
264
|
+
};
|
265
|
+
}
|
266
|
+
}
|
267
|
+
class RunningProcessColumn {
|
268
|
+
constructor() {
|
269
|
+
this.label = ( localize(8319, "Running Process"));
|
270
|
+
this.tooltip = ( localize(8320, "The command line of the process that is using the port."));
|
271
|
+
this.weight = 2;
|
272
|
+
this.templateId = 'actionbar';
|
273
|
+
}
|
274
|
+
project(row) {
|
275
|
+
if (row.tunnelType === TunnelType.Add) {
|
276
|
+
return emptyCell(row);
|
277
|
+
}
|
278
|
+
const label = row.processDescription ?? '';
|
279
|
+
return { label, tunnel: row, editId: TunnelEditId.None, tooltip: row instanceof TunnelItem ? row.processTooltip : '' };
|
280
|
+
}
|
281
|
+
}
|
282
|
+
class OriginColumn {
|
283
|
+
constructor() {
|
284
|
+
this.label = ( localize(8321, "Origin"));
|
285
|
+
this.tooltip = ( localize(
|
286
|
+
8322,
|
287
|
+
"The source that a forwarded port originates from. Can be an extension, user forwarded, statically forwarded, or automatically forwarded."
|
288
|
+
));
|
289
|
+
this.weight = 1;
|
290
|
+
this.templateId = 'actionbar';
|
291
|
+
}
|
292
|
+
project(row) {
|
293
|
+
if (row.tunnelType === TunnelType.Add) {
|
294
|
+
return emptyCell(row);
|
295
|
+
}
|
296
|
+
const label = row.source.description;
|
297
|
+
const tooltip = `${row instanceof TunnelItem ? row.originTooltip : ''}. ${row instanceof TunnelItem ? row.tooltipPostfix : ''}`;
|
298
|
+
return { label, menuId: MenuId.TunnelOriginInline, tunnel: row, editId: TunnelEditId.None, tooltip };
|
299
|
+
}
|
300
|
+
}
|
301
|
+
class PrivacyColumn {
|
302
|
+
constructor() {
|
303
|
+
this.label = ( localize(8323, "Visibility"));
|
304
|
+
this.tooltip = ( localize(8324, "The availability of the forwarded port."));
|
305
|
+
this.weight = 1;
|
306
|
+
this.templateId = 'actionbar';
|
307
|
+
}
|
308
|
+
project(row) {
|
309
|
+
if (row.tunnelType === TunnelType.Add) {
|
310
|
+
return emptyCell(row);
|
311
|
+
}
|
312
|
+
const label = row.privacy?.label;
|
313
|
+
let tooltip = '';
|
314
|
+
if (row instanceof TunnelItem) {
|
315
|
+
tooltip = `${row.privacy.label} ${row.tooltipPostfix}`;
|
316
|
+
}
|
317
|
+
return { label, tunnel: row, icon: { id: row.privacy.themeIcon }, editId: TunnelEditId.None, tooltip };
|
318
|
+
}
|
319
|
+
}
|
320
|
+
let ActionBarRenderer = class ActionBarRenderer extends Disposable {
|
321
|
+
constructor(instantiationService, contextKeyService, menuService, contextViewService, remoteExplorerService, commandService, configurationService) {
|
322
|
+
super();
|
323
|
+
this.instantiationService = instantiationService;
|
324
|
+
this.contextKeyService = contextKeyService;
|
325
|
+
this.menuService = menuService;
|
326
|
+
this.contextViewService = contextViewService;
|
327
|
+
this.remoteExplorerService = remoteExplorerService;
|
328
|
+
this.commandService = commandService;
|
329
|
+
this.configurationService = configurationService;
|
330
|
+
this.templateId = 'actionbar';
|
331
|
+
this._hoverDelegate = getDefaultHoverDelegate('mouse');
|
332
|
+
}
|
333
|
+
set actionRunner(actionRunner) {
|
334
|
+
this._actionRunner = actionRunner;
|
335
|
+
}
|
336
|
+
renderTemplate(container) {
|
337
|
+
const cell = append(container, $('.ports-view-actionbar-cell'));
|
338
|
+
const icon = append(cell, $('.ports-view-actionbar-cell-icon'));
|
339
|
+
const label = ( new IconLabel(cell, {
|
340
|
+
supportHighlights: true,
|
341
|
+
hoverDelegate: this._hoverDelegate
|
342
|
+
}));
|
343
|
+
const actionsContainer = append(cell, $('.actions'));
|
344
|
+
const actionBar = ( new ActionBar(actionsContainer, {
|
345
|
+
actionViewItemProvider: createActionViewItem.bind(undefined, this.instantiationService),
|
346
|
+
hoverDelegate: this._hoverDelegate
|
347
|
+
}));
|
348
|
+
return { label, icon, actionBar, container: cell, elementDisposable: Disposable.None };
|
349
|
+
}
|
350
|
+
renderElement(element, index, templateData) {
|
351
|
+
templateData.actionBar.clear();
|
352
|
+
templateData.icon.className = 'ports-view-actionbar-cell-icon';
|
353
|
+
templateData.icon.style.display = 'none';
|
354
|
+
templateData.label.setLabel('');
|
355
|
+
templateData.label.element.style.display = 'none';
|
356
|
+
templateData.container.style.height = '22px';
|
357
|
+
if (templateData.button) {
|
358
|
+
templateData.button.element.style.display = 'none';
|
359
|
+
templateData.button.dispose();
|
360
|
+
}
|
361
|
+
templateData.container.style.paddingLeft = '0px';
|
362
|
+
templateData.elementDisposable.dispose();
|
363
|
+
let editableData;
|
364
|
+
if (element.editId === TunnelEditId.New && (editableData = this.remoteExplorerService.getEditableData(undefined))) {
|
365
|
+
this.renderInputBox(templateData.container, editableData);
|
366
|
+
}
|
367
|
+
else {
|
368
|
+
editableData = this.remoteExplorerService.getEditableData(element.tunnel, element.editId);
|
369
|
+
if (editableData) {
|
370
|
+
this.renderInputBox(templateData.container, editableData);
|
371
|
+
}
|
372
|
+
else if ((element.tunnel.tunnelType === TunnelType.Add) && (element.menuId === MenuId.TunnelPortInline)) {
|
373
|
+
this.renderButton(element, templateData);
|
374
|
+
}
|
375
|
+
else {
|
376
|
+
this.renderActionBarItem(element, templateData);
|
377
|
+
}
|
378
|
+
}
|
379
|
+
}
|
380
|
+
renderButton(element, templateData) {
|
381
|
+
templateData.container.style.paddingLeft = '7px';
|
382
|
+
templateData.container.style.height = '28px';
|
383
|
+
templateData.button = this._register(( new Button(templateData.container, defaultButtonStyles)));
|
384
|
+
templateData.button.label = element.label;
|
385
|
+
templateData.button.element.title = element.tooltip;
|
386
|
+
this._register(templateData.button.onDidClick(() => {
|
387
|
+
this.commandService.executeCommand(ForwardPortAction.INLINE_ID);
|
388
|
+
}));
|
389
|
+
}
|
390
|
+
tunnelContext(tunnel) {
|
391
|
+
let context;
|
392
|
+
if (tunnel instanceof TunnelItem) {
|
393
|
+
context = tunnel.strip();
|
394
|
+
}
|
395
|
+
if (!context) {
|
396
|
+
context = {
|
397
|
+
tunnelType: tunnel.tunnelType,
|
398
|
+
remoteHost: tunnel.remoteHost,
|
399
|
+
remotePort: tunnel.remotePort,
|
400
|
+
localAddress: tunnel.localAddress,
|
401
|
+
protocol: tunnel.protocol,
|
402
|
+
localUri: tunnel.localUri,
|
403
|
+
localPort: tunnel.localPort,
|
404
|
+
name: tunnel.name,
|
405
|
+
closeable: tunnel.closeable,
|
406
|
+
source: tunnel.source,
|
407
|
+
privacy: tunnel.privacy,
|
408
|
+
processDescription: tunnel.processDescription,
|
409
|
+
label: tunnel.label
|
410
|
+
};
|
411
|
+
}
|
412
|
+
return context;
|
413
|
+
}
|
414
|
+
renderActionBarItem(element, templateData) {
|
415
|
+
templateData.label.element.style.display = 'flex';
|
416
|
+
templateData.label.setLabel(element.label, undefined, {
|
417
|
+
title: element.markdownTooltip ?
|
418
|
+
{ markdown: element.markdownTooltip(this.configurationService), markdownNotSupportedFallback: element.tooltip }
|
419
|
+
: element.tooltip,
|
420
|
+
extraClasses: element.menuId === MenuId.TunnelLocalAddressInline ? ['ports-view-actionbar-cell-localaddress'] : undefined
|
421
|
+
});
|
422
|
+
templateData.actionBar.context = this.tunnelContext(element.tunnel);
|
423
|
+
templateData.container.style.paddingLeft = '10px';
|
424
|
+
const context = [
|
425
|
+
['view', TUNNEL_VIEW_ID],
|
426
|
+
[TunnelTypeContextKey.key, element.tunnel.tunnelType],
|
427
|
+
[TunnelCloseableContextKey.key, element.tunnel.closeable],
|
428
|
+
[TunnelPrivacyContextKey.key, element.tunnel.privacy.id],
|
429
|
+
[TunnelProtocolContextKey.key, element.tunnel.protocol]
|
430
|
+
];
|
431
|
+
const contextKeyService = this.contextKeyService.createOverlay(context);
|
432
|
+
const disposableStore = ( new DisposableStore());
|
433
|
+
templateData.elementDisposable = disposableStore;
|
434
|
+
if (element.menuId) {
|
435
|
+
const menu = disposableStore.add(this.menuService.createMenu(element.menuId, contextKeyService));
|
436
|
+
let actions = getFlatActionBarActions(menu.getActions({ shouldForwardArgs: true }));
|
437
|
+
if (actions) {
|
438
|
+
const labelActions = actions.filter(action => action.id.toLowerCase().indexOf('label') >= 0);
|
439
|
+
if (labelActions.length > 1) {
|
440
|
+
labelActions.sort((a, b) => a.label.length - b.label.length);
|
441
|
+
labelActions.pop();
|
442
|
+
actions = actions.filter(action => labelActions.indexOf(action) < 0);
|
443
|
+
}
|
444
|
+
templateData.actionBar.push(actions, { icon: true, label: false });
|
445
|
+
if (this._actionRunner) {
|
446
|
+
templateData.actionBar.actionRunner = this._actionRunner;
|
447
|
+
}
|
448
|
+
}
|
449
|
+
}
|
450
|
+
if (element.icon) {
|
451
|
+
templateData.icon.className = `ports-view-actionbar-cell-icon ${ThemeIcon.asClassName(element.icon)}`;
|
452
|
+
templateData.icon.title = element.tooltip;
|
453
|
+
templateData.icon.style.display = 'inline';
|
454
|
+
}
|
455
|
+
}
|
456
|
+
renderInputBox(container, editableData) {
|
457
|
+
if (this.inputDone) {
|
458
|
+
this.inputDone(false, false);
|
459
|
+
this.inputDone = undefined;
|
460
|
+
}
|
461
|
+
container.style.paddingLeft = '5px';
|
462
|
+
const value = editableData.startingValue || '';
|
463
|
+
const inputBox = ( new InputBox(container, this.contextViewService, {
|
464
|
+
ariaLabel: ( localize(8325, "Press Enter to confirm or Escape to cancel.")),
|
465
|
+
validationOptions: {
|
466
|
+
validation: (value) => {
|
467
|
+
const message = editableData.validationMessage(value);
|
468
|
+
if (!message) {
|
469
|
+
return null;
|
470
|
+
}
|
471
|
+
return {
|
472
|
+
content: message.content,
|
473
|
+
formatContent: true,
|
474
|
+
type: message.severity === Severity.Error ? MessageType.ERROR : MessageType.INFO
|
475
|
+
};
|
476
|
+
}
|
477
|
+
},
|
478
|
+
placeholder: editableData.placeholder || '',
|
479
|
+
inputBoxStyles: defaultInputBoxStyles
|
480
|
+
}));
|
481
|
+
inputBox.value = value;
|
482
|
+
inputBox.focus();
|
483
|
+
inputBox.select({ start: 0, end: editableData.startingValue ? editableData.startingValue.length : 0 });
|
484
|
+
const done = createSingleCallFunction(async (success, finishEditing) => {
|
485
|
+
dispose(toDispose);
|
486
|
+
if (this.inputDone) {
|
487
|
+
this.inputDone = undefined;
|
488
|
+
}
|
489
|
+
inputBox.element.style.display = 'none';
|
490
|
+
const inputValue = inputBox.value;
|
491
|
+
if (finishEditing) {
|
492
|
+
return editableData.onFinish(inputValue, success);
|
493
|
+
}
|
494
|
+
});
|
495
|
+
this.inputDone = done;
|
496
|
+
const toDispose = [
|
497
|
+
inputBox,
|
498
|
+
addStandardDisposableListener(inputBox.inputElement, EventType.KEY_DOWN, async (e) => {
|
499
|
+
if (e.equals(KeyCode.Enter)) {
|
500
|
+
e.stopPropagation();
|
501
|
+
if (inputBox.validate() !== MessageType.ERROR) {
|
502
|
+
return done(true, true);
|
503
|
+
}
|
504
|
+
else {
|
505
|
+
return done(false, true);
|
506
|
+
}
|
507
|
+
}
|
508
|
+
else if (e.equals(KeyCode.Escape)) {
|
509
|
+
e.preventDefault();
|
510
|
+
e.stopPropagation();
|
511
|
+
return done(false, true);
|
512
|
+
}
|
513
|
+
}),
|
514
|
+
addDisposableListener(inputBox.inputElement, EventType.BLUR, () => {
|
515
|
+
return done(inputBox.validate() !== MessageType.ERROR, true);
|
516
|
+
})
|
517
|
+
];
|
518
|
+
return toDisposable(() => {
|
519
|
+
done(false, false);
|
520
|
+
});
|
521
|
+
}
|
522
|
+
disposeElement(element, index, templateData, height) {
|
523
|
+
templateData.elementDisposable.dispose();
|
524
|
+
}
|
525
|
+
disposeTemplate(templateData) {
|
526
|
+
templateData.label.dispose();
|
527
|
+
templateData.actionBar.dispose();
|
528
|
+
templateData.elementDisposable.dispose();
|
529
|
+
templateData.button?.dispose();
|
530
|
+
}
|
531
|
+
};
|
532
|
+
ActionBarRenderer = ( __decorate([
|
533
|
+
( __param(0, IInstantiationService)),
|
534
|
+
( __param(1, IContextKeyService)),
|
535
|
+
( __param(2, IMenuService)),
|
536
|
+
( __param(3, IContextViewService)),
|
537
|
+
( __param(4, IRemoteExplorerService)),
|
538
|
+
( __param(5, ICommandService)),
|
539
|
+
( __param(6, IConfigurationService))
|
540
|
+
], ActionBarRenderer));
|
541
|
+
class TunnelItem {
|
542
|
+
static createFromTunnel(remoteExplorerService, tunnelService, tunnel, type = TunnelType.Forwarded, closeable) {
|
543
|
+
return ( new TunnelItem(
|
544
|
+
type,
|
545
|
+
tunnel.remoteHost,
|
546
|
+
tunnel.remotePort,
|
547
|
+
tunnel.source,
|
548
|
+
!!tunnel.hasRunningProcess,
|
549
|
+
tunnel.protocol,
|
550
|
+
tunnel.localUri,
|
551
|
+
tunnel.localAddress,
|
552
|
+
tunnel.localPort,
|
553
|
+
closeable === undefined ? tunnel.closeable : closeable,
|
554
|
+
tunnel.name,
|
555
|
+
tunnel.runningProcess,
|
556
|
+
tunnel.pid,
|
557
|
+
tunnel.privacy,
|
558
|
+
remoteExplorerService,
|
559
|
+
tunnelService
|
560
|
+
));
|
561
|
+
}
|
562
|
+
strip() {
|
563
|
+
return ( new TunnelItem(
|
564
|
+
this.tunnelType,
|
565
|
+
this.remoteHost,
|
566
|
+
this.remotePort,
|
567
|
+
this.source,
|
568
|
+
this.hasRunningProcess,
|
569
|
+
this.protocol,
|
570
|
+
this.localUri,
|
571
|
+
this.localAddress,
|
572
|
+
this.localPort,
|
573
|
+
this.closeable,
|
574
|
+
this.name,
|
575
|
+
this.runningProcess,
|
576
|
+
this.pid,
|
577
|
+
this._privacy
|
578
|
+
));
|
579
|
+
}
|
580
|
+
constructor(tunnelType, remoteHost, remotePort, source, hasRunningProcess, protocol, localUri, localAddress, localPort, closeable, name, runningProcess, pid, _privacy, remoteExplorerService, tunnelService) {
|
581
|
+
this.tunnelType = tunnelType;
|
582
|
+
this.remoteHost = remoteHost;
|
583
|
+
this.remotePort = remotePort;
|
584
|
+
this.source = source;
|
585
|
+
this.hasRunningProcess = hasRunningProcess;
|
586
|
+
this.protocol = protocol;
|
587
|
+
this.localUri = localUri;
|
588
|
+
this.localAddress = localAddress;
|
589
|
+
this.localPort = localPort;
|
590
|
+
this.closeable = closeable;
|
591
|
+
this.name = name;
|
592
|
+
this.runningProcess = runningProcess;
|
593
|
+
this.pid = pid;
|
594
|
+
this._privacy = _privacy;
|
595
|
+
this.remoteExplorerService = remoteExplorerService;
|
596
|
+
this.tunnelService = tunnelService;
|
597
|
+
}
|
598
|
+
get label() {
|
599
|
+
if (this.tunnelType === TunnelType.Add && this.name) {
|
600
|
+
return this.name;
|
601
|
+
}
|
602
|
+
const portNumberLabel = (isLocalhost(this.remoteHost) || isAllInterfaces(this.remoteHost))
|
603
|
+
? `${this.remotePort}`
|
604
|
+
: `${this.remoteHost}:${this.remotePort}`;
|
605
|
+
if (this.name) {
|
606
|
+
return `${this.name} (${portNumberLabel})`;
|
607
|
+
}
|
608
|
+
else {
|
609
|
+
return portNumberLabel;
|
610
|
+
}
|
611
|
+
}
|
612
|
+
set processDescription(description) {
|
613
|
+
this.runningProcess = description;
|
614
|
+
}
|
615
|
+
get processDescription() {
|
616
|
+
let description = '';
|
617
|
+
if (this.runningProcess) {
|
618
|
+
if (this.pid && this.remoteExplorerService?.namedProcesses.has(this.pid)) {
|
619
|
+
description = this.remoteExplorerService.namedProcesses.get(this.pid);
|
620
|
+
}
|
621
|
+
else {
|
622
|
+
description = this.runningProcess.replace(/\0/g, ' ').trim();
|
623
|
+
}
|
624
|
+
if (this.pid) {
|
625
|
+
description += ` (${this.pid})`;
|
626
|
+
}
|
627
|
+
}
|
628
|
+
else if (this.hasRunningProcess) {
|
629
|
+
description = ( localize(8326, "Process information unavailable"));
|
630
|
+
}
|
631
|
+
return description;
|
632
|
+
}
|
633
|
+
get tooltipPostfix() {
|
634
|
+
let information;
|
635
|
+
if (this.localAddress) {
|
636
|
+
information = ( localize(
|
637
|
+
8327,
|
638
|
+
"Remote port {0}:{1} forwarded to local address {2}. ",
|
639
|
+
this.remoteHost,
|
640
|
+
this.remotePort,
|
641
|
+
this.localAddress
|
642
|
+
));
|
643
|
+
}
|
644
|
+
else {
|
645
|
+
information = ( localize(
|
646
|
+
8328,
|
647
|
+
"Remote port {0}:{1} not forwarded. ",
|
648
|
+
this.remoteHost,
|
649
|
+
this.remotePort
|
650
|
+
));
|
651
|
+
}
|
652
|
+
return information;
|
653
|
+
}
|
654
|
+
get iconTooltip() {
|
655
|
+
const isAdd = this.tunnelType === TunnelType.Add;
|
656
|
+
if (!isAdd) {
|
657
|
+
return `${this.processDescription ? ( localize(8329, "Port has running process.")) :
|
658
|
+
( localize(8330, "No running process."))}`;
|
659
|
+
}
|
660
|
+
else {
|
661
|
+
return this.label;
|
662
|
+
}
|
663
|
+
}
|
664
|
+
get portTooltip() {
|
665
|
+
const isAdd = this.tunnelType === TunnelType.Add;
|
666
|
+
if (!isAdd) {
|
667
|
+
return `${this.name ? ( localize(8331, "Port labeled {0}. ", this.name)) : ''}`;
|
668
|
+
}
|
669
|
+
else {
|
670
|
+
return '';
|
671
|
+
}
|
672
|
+
}
|
673
|
+
get processTooltip() {
|
674
|
+
return this.processDescription ?? '';
|
675
|
+
}
|
676
|
+
get originTooltip() {
|
677
|
+
return this.source.description;
|
678
|
+
}
|
679
|
+
get privacy() {
|
680
|
+
if (this.tunnelService?.privacyOptions) {
|
681
|
+
return this.tunnelService?.privacyOptions.find(element => element.id === this._privacy) ??
|
682
|
+
{
|
683
|
+
id: '',
|
684
|
+
themeIcon: Codicon.question.id,
|
685
|
+
label: ( localize(8332, "Unknown"))
|
686
|
+
};
|
687
|
+
}
|
688
|
+
else {
|
689
|
+
return {
|
690
|
+
id: TunnelPrivacyId.Private,
|
691
|
+
themeIcon: privatePortIcon.id,
|
692
|
+
label: ( localize(8310, "Private"))
|
693
|
+
};
|
694
|
+
}
|
695
|
+
}
|
696
|
+
}
|
697
|
+
const TunnelTypeContextKey = ( new RawContextKey('tunnelType', TunnelType.Add, true));
|
698
|
+
const TunnelCloseableContextKey = ( new RawContextKey('tunnelCloseable', false, true));
|
699
|
+
const TunnelPrivacyContextKey = ( new RawContextKey('tunnelPrivacy', undefined, true));
|
700
|
+
const TunnelPrivacyEnabledContextKey = ( new RawContextKey('tunnelPrivacyEnabled', false, true));
|
701
|
+
const TunnelProtocolContextKey = ( new RawContextKey('tunnelProtocol', TunnelProtocol.Http, true));
|
702
|
+
const TunnelViewFocusContextKey = ( new RawContextKey('tunnelViewFocus', false, ( localize(8333, "Whether the Ports view has focus."))));
|
703
|
+
const TunnelViewSelectionKeyName = 'tunnelViewSelection';
|
704
|
+
const TunnelViewSelectionContextKey = ( new RawContextKey(TunnelViewSelectionKeyName, undefined, true));
|
705
|
+
const TunnelViewMultiSelectionKeyName = 'tunnelViewMultiSelection';
|
706
|
+
const TunnelViewMultiSelectionContextKey = ( new RawContextKey(TunnelViewMultiSelectionKeyName, undefined, true));
|
707
|
+
const PortChangableContextKey = ( new RawContextKey('portChangable', false, true));
|
708
|
+
const ProtocolChangeableContextKey = ( new RawContextKey('protocolChangable', true, true));
|
709
|
+
let TunnelPanel = class TunnelPanel extends ViewPane {
|
710
|
+
static { TunnelPanel_1 = this; }
|
711
|
+
static { this.ID = TUNNEL_VIEW_ID; }
|
712
|
+
static { this.TITLE = ( localize2(8334, "Ports")); }
|
713
|
+
constructor(viewModel, options, keybindingService, contextMenuService, contextKeyService, configurationService, instantiationService, viewDescriptorService, openerService, quickInputService, commandService, menuService, themeService, remoteExplorerService, telemetryService, hoverService, tunnelService, contextViewService) {
|
714
|
+
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService, hoverService);
|
715
|
+
this.viewModel = viewModel;
|
716
|
+
this.quickInputService = quickInputService;
|
717
|
+
this.commandService = commandService;
|
718
|
+
this.menuService = menuService;
|
719
|
+
this.remoteExplorerService = remoteExplorerService;
|
720
|
+
this.tunnelService = tunnelService;
|
721
|
+
this.contextViewService = contextViewService;
|
722
|
+
this.tableDisposables = this._register(( new DisposableStore()));
|
723
|
+
this.isEditing = false;
|
724
|
+
this.titleActions = [];
|
725
|
+
this.lastFocus = [];
|
726
|
+
this.height = 0;
|
727
|
+
this.width = 0;
|
728
|
+
this.tunnelTypeContext = TunnelTypeContextKey.bindTo(contextKeyService);
|
729
|
+
this.tunnelCloseableContext = TunnelCloseableContextKey.bindTo(contextKeyService);
|
730
|
+
this.tunnelPrivacyContext = TunnelPrivacyContextKey.bindTo(contextKeyService);
|
731
|
+
this.tunnelPrivacyEnabledContext = TunnelPrivacyEnabledContextKey.bindTo(contextKeyService);
|
732
|
+
this.tunnelPrivacyEnabledContext.set(tunnelService.canChangePrivacy);
|
733
|
+
this.protocolChangableContextKey = ProtocolChangeableContextKey.bindTo(contextKeyService);
|
734
|
+
this.protocolChangableContextKey.set(tunnelService.canChangeProtocol);
|
735
|
+
this.tunnelProtocolContext = TunnelProtocolContextKey.bindTo(contextKeyService);
|
736
|
+
this.tunnelViewFocusContext = TunnelViewFocusContextKey.bindTo(contextKeyService);
|
737
|
+
this.tunnelViewSelectionContext = TunnelViewSelectionContextKey.bindTo(contextKeyService);
|
738
|
+
this.tunnelViewMultiSelectionContext = TunnelViewMultiSelectionContextKey.bindTo(contextKeyService);
|
739
|
+
this.portChangableContextKey = PortChangableContextKey.bindTo(contextKeyService);
|
740
|
+
const overlayContextKeyService = this.contextKeyService.createOverlay([['view', TunnelPanel_1.ID]]);
|
741
|
+
const titleMenu = this._register(this.menuService.createMenu(MenuId.TunnelTitle, overlayContextKeyService));
|
742
|
+
const updateActions = () => {
|
743
|
+
this.titleActions = getFlatActionBarActions(titleMenu.getActions());
|
744
|
+
this.updateActions();
|
745
|
+
};
|
746
|
+
this._register(titleMenu.onDidChange(updateActions));
|
747
|
+
updateActions();
|
748
|
+
this._register(toDisposable(() => {
|
749
|
+
this.titleActions = [];
|
750
|
+
}));
|
751
|
+
this.registerPrivacyActions();
|
752
|
+
this._register(Event.once(this.tunnelService.onAddedTunnelProvider)(() => {
|
753
|
+
let updated = false;
|
754
|
+
if (this.tunnelPrivacyEnabledContext.get() === false) {
|
755
|
+
this.tunnelPrivacyEnabledContext.set(tunnelService.canChangePrivacy);
|
756
|
+
updated = true;
|
757
|
+
}
|
758
|
+
if (this.protocolChangableContextKey.get() === true) {
|
759
|
+
this.protocolChangableContextKey.set(tunnelService.canChangeProtocol);
|
760
|
+
updated = true;
|
761
|
+
}
|
762
|
+
if (updated) {
|
763
|
+
updateActions();
|
764
|
+
this.registerPrivacyActions();
|
765
|
+
this.createTable();
|
766
|
+
this.table?.layout(this.height, this.width);
|
767
|
+
}
|
768
|
+
}));
|
769
|
+
}
|
770
|
+
registerPrivacyActions() {
|
771
|
+
for (const privacyOption of this.tunnelService.privacyOptions) {
|
772
|
+
const optionId = `remote.tunnel.privacy${privacyOption.id}`;
|
773
|
+
CommandsRegistry.registerCommand(optionId, ChangeTunnelPrivacyAction.handler(privacyOption.id));
|
774
|
+
MenuRegistry.appendMenuItem(MenuId.TunnelPrivacy, ({
|
775
|
+
order: 0,
|
776
|
+
command: {
|
777
|
+
id: optionId,
|
778
|
+
title: privacyOption.label,
|
779
|
+
toggled: ( TunnelPrivacyContextKey.isEqualTo(privacyOption.id))
|
780
|
+
}
|
781
|
+
}));
|
782
|
+
}
|
783
|
+
}
|
784
|
+
get portCount() {
|
785
|
+
return this.remoteExplorerService.tunnelModel.forwarded.size + this.remoteExplorerService.tunnelModel.detected.size;
|
786
|
+
}
|
787
|
+
createTable() {
|
788
|
+
if (!this.panelContainer) {
|
789
|
+
return;
|
790
|
+
}
|
791
|
+
this.tableDisposables.clear();
|
792
|
+
clearNode(this.panelContainer);
|
793
|
+
const widgetContainer = append(this.panelContainer, $('.customview-tree'));
|
794
|
+
widgetContainer.classList.add('ports-view');
|
795
|
+
widgetContainer.classList.add('file-icon-themable-tree', 'show-file-icons');
|
796
|
+
const actionBarRenderer = ( new ActionBarRenderer(
|
797
|
+
this.instantiationService,
|
798
|
+
this.contextKeyService,
|
799
|
+
this.menuService,
|
800
|
+
this.contextViewService,
|
801
|
+
this.remoteExplorerService,
|
802
|
+
this.commandService,
|
803
|
+
this.configurationService
|
804
|
+
));
|
805
|
+
const columns = [( new IconColumn()), ( new PortColumn()), ( new LocalAddressColumn()), ( new RunningProcessColumn())];
|
806
|
+
if (this.tunnelService.canChangePrivacy) {
|
807
|
+
columns.push(( new PrivacyColumn()));
|
808
|
+
}
|
809
|
+
columns.push(( new OriginColumn()));
|
810
|
+
this.table = this.instantiationService.createInstance(WorkbenchTable, 'RemoteTunnels', widgetContainer, ( new TunnelTreeVirtualDelegate(this.remoteExplorerService)), columns, [actionBarRenderer], {
|
811
|
+
keyboardNavigationLabelProvider: {
|
812
|
+
getKeyboardNavigationLabel: (item) => {
|
813
|
+
return item.label;
|
814
|
+
}
|
815
|
+
},
|
816
|
+
multipleSelectionSupport: true,
|
817
|
+
accessibilityProvider: {
|
818
|
+
getAriaLabel: (item) => {
|
819
|
+
if (item instanceof TunnelItem) {
|
820
|
+
return `${item.tooltipPostfix} ${item.portTooltip} ${item.iconTooltip} ${item.processTooltip} ${item.originTooltip} ${this.tunnelService.canChangePrivacy ? item.privacy.label : ''}`;
|
821
|
+
}
|
822
|
+
else {
|
823
|
+
return item.label;
|
824
|
+
}
|
825
|
+
},
|
826
|
+
getWidgetAriaLabel: () => ( localize(8335, "Tunnel View"))
|
827
|
+
},
|
828
|
+
openOnSingleClick: true
|
829
|
+
});
|
830
|
+
const actionRunner = ( new ActionRunner());
|
831
|
+
actionBarRenderer.actionRunner = actionRunner;
|
832
|
+
this.tableDisposables.add(this.table);
|
833
|
+
this.tableDisposables.add(this.table.onContextMenu(e => this.onContextMenu(e, actionRunner)));
|
834
|
+
this.tableDisposables.add(this.table.onMouseDblClick(e => this.onMouseDblClick(e)));
|
835
|
+
this.tableDisposables.add(this.table.onDidChangeFocus(e => this.onFocusChanged(e)));
|
836
|
+
this.tableDisposables.add(this.table.onDidChangeSelection(e => this.onSelectionChanged(e)));
|
837
|
+
this.tableDisposables.add(this.table.onDidFocus(() => this.tunnelViewFocusContext.set(true)));
|
838
|
+
this.tableDisposables.add(this.table.onDidBlur(() => this.tunnelViewFocusContext.set(false)));
|
839
|
+
const rerender = () => this.table?.splice(0, Number.POSITIVE_INFINITY, this.viewModel.all);
|
840
|
+
rerender();
|
841
|
+
let lastPortCount = this.portCount;
|
842
|
+
this.tableDisposables.add(Event.debounce(this.viewModel.onForwardedPortsChanged, (_last, e) => e, 50)(() => {
|
843
|
+
const newPortCount = this.portCount;
|
844
|
+
if (((lastPortCount === 0) || (newPortCount === 0)) && (lastPortCount !== newPortCount)) {
|
845
|
+
this._onDidChangeViewWelcomeState.fire();
|
846
|
+
}
|
847
|
+
lastPortCount = newPortCount;
|
848
|
+
rerender();
|
849
|
+
}));
|
850
|
+
this.tableDisposables.add(this.table.onMouseClick(e => {
|
851
|
+
if (this.hasOpenLinkModifier(e.browserEvent) && this.table) {
|
852
|
+
const selection = this.table.getSelectedElements();
|
853
|
+
if ((selection.length === 0) ||
|
854
|
+
((selection.length === 1) && (selection[0] === e.element))) {
|
855
|
+
this.commandService.executeCommand(OpenPortInBrowserAction.ID, e.element);
|
856
|
+
}
|
857
|
+
}
|
858
|
+
}));
|
859
|
+
this.tableDisposables.add(this.table.onDidOpen(e => {
|
860
|
+
if (!e.element || (e.element.tunnelType !== TunnelType.Forwarded)) {
|
861
|
+
return;
|
862
|
+
}
|
863
|
+
if (e.browserEvent?.type === 'dblclick') {
|
864
|
+
this.commandService.executeCommand(LabelTunnelAction.ID);
|
865
|
+
}
|
866
|
+
}));
|
867
|
+
this.tableDisposables.add(this.remoteExplorerService.onDidChangeEditable(e => {
|
868
|
+
this.isEditing = !!this.remoteExplorerService.getEditableData(e?.tunnel, e?.editId);
|
869
|
+
this._onDidChangeViewWelcomeState.fire();
|
870
|
+
if (!this.isEditing) {
|
871
|
+
widgetContainer.classList.remove('highlight');
|
872
|
+
}
|
873
|
+
rerender();
|
874
|
+
if (this.isEditing) {
|
875
|
+
widgetContainer.classList.add('highlight');
|
876
|
+
if (!e) {
|
877
|
+
this.table?.reveal(this.table.indexOf(this.viewModel.input));
|
878
|
+
}
|
879
|
+
}
|
880
|
+
else {
|
881
|
+
if (e && (e.tunnel.tunnelType !== TunnelType.Add)) {
|
882
|
+
this.table?.setFocus(this.lastFocus);
|
883
|
+
}
|
884
|
+
this.focus();
|
885
|
+
}
|
886
|
+
}));
|
887
|
+
}
|
888
|
+
renderBody(container) {
|
889
|
+
super.renderBody(container);
|
890
|
+
this.panelContainer = append(container, $('.tree-explorer-viewlet-tree-view'));
|
891
|
+
this.createTable();
|
892
|
+
}
|
893
|
+
shouldShowWelcome() {
|
894
|
+
return this.viewModel.isEmpty() && !this.isEditing;
|
895
|
+
}
|
896
|
+
focus() {
|
897
|
+
super.focus();
|
898
|
+
this.table?.domFocus();
|
899
|
+
}
|
900
|
+
onFocusChanged(event) {
|
901
|
+
if (event.indexes.length > 0 && event.elements.length > 0) {
|
902
|
+
this.lastFocus = [...event.indexes];
|
903
|
+
}
|
904
|
+
const elements = event.elements;
|
905
|
+
const item = elements && elements.length ? elements[0] : undefined;
|
906
|
+
if (item) {
|
907
|
+
this.tunnelViewSelectionContext.set(makeAddress(item.remoteHost, item.remotePort));
|
908
|
+
this.tunnelTypeContext.set(item.tunnelType);
|
909
|
+
this.tunnelCloseableContext.set(!!item.closeable);
|
910
|
+
this.tunnelPrivacyContext.set(item.privacy.id);
|
911
|
+
this.tunnelProtocolContext.set(item.protocol === TunnelProtocol.Https ? TunnelProtocol.Https : TunnelProtocol.Https);
|
912
|
+
this.portChangableContextKey.set(!!item.localPort);
|
913
|
+
}
|
914
|
+
else {
|
915
|
+
this.tunnelTypeContext.reset();
|
916
|
+
this.tunnelViewSelectionContext.reset();
|
917
|
+
this.tunnelCloseableContext.reset();
|
918
|
+
this.tunnelPrivacyContext.reset();
|
919
|
+
this.tunnelProtocolContext.reset();
|
920
|
+
this.portChangableContextKey.reset();
|
921
|
+
}
|
922
|
+
}
|
923
|
+
hasOpenLinkModifier(e) {
|
924
|
+
const editorConf = this.configurationService.getValue('editor');
|
925
|
+
let modifierKey = false;
|
926
|
+
if (editorConf.multiCursorModifier === 'ctrlCmd') {
|
927
|
+
modifierKey = e.altKey;
|
928
|
+
}
|
929
|
+
else {
|
930
|
+
if (isMacintosh) {
|
931
|
+
modifierKey = e.metaKey;
|
932
|
+
}
|
933
|
+
else {
|
934
|
+
modifierKey = e.ctrlKey;
|
935
|
+
}
|
936
|
+
}
|
937
|
+
return modifierKey;
|
938
|
+
}
|
939
|
+
onSelectionChanged(event) {
|
940
|
+
const elements = event.elements;
|
941
|
+
if (elements.length > 1) {
|
942
|
+
this.tunnelViewMultiSelectionContext.set(( elements.map(element => makeAddress(element.remoteHost, element.remotePort))));
|
943
|
+
}
|
944
|
+
else {
|
945
|
+
this.tunnelViewMultiSelectionContext.set(undefined);
|
946
|
+
}
|
947
|
+
}
|
948
|
+
onContextMenu(event, actionRunner) {
|
949
|
+
if ((event.element !== undefined) && !(event.element instanceof TunnelItem)) {
|
950
|
+
return;
|
951
|
+
}
|
952
|
+
event.browserEvent.preventDefault();
|
953
|
+
event.browserEvent.stopPropagation();
|
954
|
+
const node = event.element;
|
955
|
+
if (node) {
|
956
|
+
this.table?.setFocus([this.table.indexOf(node)]);
|
957
|
+
this.tunnelTypeContext.set(node.tunnelType);
|
958
|
+
this.tunnelCloseableContext.set(!!node.closeable);
|
959
|
+
this.tunnelPrivacyContext.set(node.privacy.id);
|
960
|
+
this.tunnelProtocolContext.set(node.protocol);
|
961
|
+
this.portChangableContextKey.set(!!node.localPort);
|
962
|
+
}
|
963
|
+
else {
|
964
|
+
this.tunnelTypeContext.set(TunnelType.Add);
|
965
|
+
this.tunnelCloseableContext.set(false);
|
966
|
+
this.tunnelPrivacyContext.set(undefined);
|
967
|
+
this.tunnelProtocolContext.set(undefined);
|
968
|
+
this.portChangableContextKey.set(false);
|
969
|
+
}
|
970
|
+
this.contextMenuService.showContextMenu({
|
971
|
+
menuId: MenuId.TunnelContext,
|
972
|
+
menuActionOptions: { shouldForwardArgs: true },
|
973
|
+
contextKeyService: this.table?.contextKeyService,
|
974
|
+
getAnchor: () => event.anchor,
|
975
|
+
getActionViewItem: (action) => {
|
976
|
+
const keybinding = this.keybindingService.lookupKeybinding(action.id);
|
977
|
+
if (keybinding) {
|
978
|
+
return ( new ActionViewItem(action, action, { label: true, keybinding: keybinding.getLabel() }));
|
979
|
+
}
|
980
|
+
return undefined;
|
981
|
+
},
|
982
|
+
onHide: (wasCancelled) => {
|
983
|
+
if (wasCancelled) {
|
984
|
+
this.table?.domFocus();
|
985
|
+
}
|
986
|
+
},
|
987
|
+
getActionsContext: () => node?.strip(),
|
988
|
+
actionRunner
|
989
|
+
});
|
990
|
+
}
|
991
|
+
onMouseDblClick(e) {
|
992
|
+
if (!e.element) {
|
993
|
+
this.commandService.executeCommand(ForwardPortAction.INLINE_ID);
|
994
|
+
}
|
995
|
+
}
|
996
|
+
layoutBody(height, width) {
|
997
|
+
this.height = height;
|
998
|
+
this.width = width;
|
999
|
+
super.layoutBody(height, width);
|
1000
|
+
this.table?.layout(height, width);
|
1001
|
+
}
|
1002
|
+
};
|
1003
|
+
TunnelPanel = TunnelPanel_1 = ( __decorate([
|
1004
|
+
( __param(2, IKeybindingService)),
|
1005
|
+
( __param(3, IContextMenuService)),
|
1006
|
+
( __param(4, IContextKeyService)),
|
1007
|
+
( __param(5, IConfigurationService)),
|
1008
|
+
( __param(6, IInstantiationService)),
|
1009
|
+
( __param(7, IViewDescriptorService)),
|
1010
|
+
( __param(8, IOpenerService)),
|
1011
|
+
( __param(9, IQuickInputService)),
|
1012
|
+
( __param(10, ICommandService)),
|
1013
|
+
( __param(11, IMenuService)),
|
1014
|
+
( __param(12, IThemeService)),
|
1015
|
+
( __param(13, IRemoteExplorerService)),
|
1016
|
+
( __param(14, ITelemetryService)),
|
1017
|
+
( __param(15, IHoverService)),
|
1018
|
+
( __param(16, ITunnelService)),
|
1019
|
+
( __param(17, IContextViewService))
|
1020
|
+
], TunnelPanel));
|
1021
|
+
class TunnelPanelDescriptor {
|
1022
|
+
constructor(viewModel, environmentService) {
|
1023
|
+
this.id = TunnelPanel.ID;
|
1024
|
+
this.name = TunnelPanel.TITLE;
|
1025
|
+
this.canToggleVisibility = true;
|
1026
|
+
this.hideByDefault = false;
|
1027
|
+
this.group = 'details@0';
|
1028
|
+
this.order = -500;
|
1029
|
+
this.canMoveView = true;
|
1030
|
+
this.containerIcon = portsViewIcon;
|
1031
|
+
this.ctorDescriptor = ( new SyncDescriptor(TunnelPanel, [viewModel]));
|
1032
|
+
this.remoteAuthority = environmentService.remoteAuthority ? environmentService.remoteAuthority.split('+')[0] : undefined;
|
1033
|
+
}
|
1034
|
+
}
|
1035
|
+
function isITunnelItem(item) {
|
1036
|
+
return item && item.tunnelType && item.remoteHost && item.source;
|
1037
|
+
}
|
1038
|
+
var LabelTunnelAction;
|
1039
|
+
(function (LabelTunnelAction) {
|
1040
|
+
LabelTunnelAction.ID = 'remote.tunnel.label';
|
1041
|
+
LabelTunnelAction.LABEL = ( localize(8336, "Set Port Label"));
|
1042
|
+
LabelTunnelAction.COMMAND_ID_KEYWORD = 'label';
|
1043
|
+
function handler() {
|
1044
|
+
return async (accessor, arg) => {
|
1045
|
+
const remoteExplorerService = accessor.get(IRemoteExplorerService);
|
1046
|
+
let tunnelContext;
|
1047
|
+
if (isITunnelItem(arg)) {
|
1048
|
+
tunnelContext = arg;
|
1049
|
+
}
|
1050
|
+
else {
|
1051
|
+
const context = accessor.get(IContextKeyService).getContextKeyValue(TunnelViewSelectionKeyName);
|
1052
|
+
const tunnel = context ? remoteExplorerService.tunnelModel.forwarded.get(context) : undefined;
|
1053
|
+
if (tunnel) {
|
1054
|
+
const tunnelService = accessor.get(ITunnelService);
|
1055
|
+
tunnelContext = TunnelItem.createFromTunnel(remoteExplorerService, tunnelService, tunnel);
|
1056
|
+
}
|
1057
|
+
}
|
1058
|
+
if (tunnelContext) {
|
1059
|
+
const tunnelItem = tunnelContext;
|
1060
|
+
return (new Promise(resolve => {
|
1061
|
+
const startingValue = tunnelItem.name ? tunnelItem.name : `${tunnelItem.remotePort}`;
|
1062
|
+
remoteExplorerService.setEditable(tunnelItem, TunnelEditId.Label, {
|
1063
|
+
onFinish: async (value, success) => {
|
1064
|
+
value = value.trim();
|
1065
|
+
remoteExplorerService.setEditable(tunnelItem, TunnelEditId.Label, null);
|
1066
|
+
const changed = success && (value !== startingValue);
|
1067
|
+
if (changed) {
|
1068
|
+
await remoteExplorerService.tunnelModel.name(tunnelItem.remoteHost, tunnelItem.remotePort, value);
|
1069
|
+
}
|
1070
|
+
resolve(changed ? { port: tunnelItem.remotePort, label: value } : undefined);
|
1071
|
+
},
|
1072
|
+
validationMessage: () => null,
|
1073
|
+
placeholder: ( localize(8337, "Port label")),
|
1074
|
+
startingValue
|
1075
|
+
});
|
1076
|
+
}));
|
1077
|
+
}
|
1078
|
+
return undefined;
|
1079
|
+
};
|
1080
|
+
}
|
1081
|
+
LabelTunnelAction.handler = handler;
|
1082
|
+
})(LabelTunnelAction || (LabelTunnelAction = {}));
|
1083
|
+
const invalidPortString = ( localize(8338, "Forwarded port should be a number or a host:port."));
|
1084
|
+
const maxPortNumber = 65536;
|
1085
|
+
const invalidPortNumberString = ( localize(8339, "Port number must be \u2265 0 and < {0}.", maxPortNumber));
|
1086
|
+
const requiresSudoString = ( localize(8340, "May Require Sudo"));
|
1087
|
+
const alreadyForwarded = ( localize(8341, "Port is already forwarded"));
|
1088
|
+
var ForwardPortAction;
|
1089
|
+
(function (ForwardPortAction) {
|
1090
|
+
ForwardPortAction.INLINE_ID = 'remote.tunnel.forwardInline';
|
1091
|
+
ForwardPortAction.COMMANDPALETTE_ID = 'remote.tunnel.forwardCommandPalette';
|
1092
|
+
ForwardPortAction.LABEL = ( localize2(8342, "Forward a Port"));
|
1093
|
+
ForwardPortAction.TREEITEM_LABEL = ( localize(8343, "Forward Port"));
|
1094
|
+
const forwardPrompt = ( localize(8344, "Port number or address (eg. 3000 or 10.10.10.10:2000)."));
|
1095
|
+
function validateInput(remoteExplorerService, tunnelService, value, canElevate) {
|
1096
|
+
const parsed = parseAddress(value);
|
1097
|
+
if (!parsed) {
|
1098
|
+
return { content: invalidPortString, severity: Severity.Error };
|
1099
|
+
}
|
1100
|
+
else if (parsed.port >= maxPortNumber) {
|
1101
|
+
return { content: invalidPortNumberString, severity: Severity.Error };
|
1102
|
+
}
|
1103
|
+
else if (canElevate && tunnelService.isPortPrivileged(parsed.port)) {
|
1104
|
+
return { content: requiresSudoString, severity: Severity.Info };
|
1105
|
+
}
|
1106
|
+
else if (mapHasAddressLocalhostOrAllInterfaces(remoteExplorerService.tunnelModel.forwarded, parsed.host, parsed.port)) {
|
1107
|
+
return { content: alreadyForwarded, severity: Severity.Error };
|
1108
|
+
}
|
1109
|
+
return null;
|
1110
|
+
}
|
1111
|
+
function error(notificationService, tunnelOrError, host, port) {
|
1112
|
+
if (!tunnelOrError) {
|
1113
|
+
notificationService.warn(( localize(
|
1114
|
+
8345,
|
1115
|
+
"Unable to forward {0}:{1}. The host may not be available or that remote port may already be forwarded",
|
1116
|
+
host,
|
1117
|
+
port
|
1118
|
+
)));
|
1119
|
+
}
|
1120
|
+
else if (typeof tunnelOrError === 'string') {
|
1121
|
+
notificationService.warn(( localize(8346, "Unable to forward {0}:{1}. {2}", host, port, tunnelOrError)));
|
1122
|
+
}
|
1123
|
+
}
|
1124
|
+
function inlineHandler() {
|
1125
|
+
return async (accessor, arg) => {
|
1126
|
+
const remoteExplorerService = accessor.get(IRemoteExplorerService);
|
1127
|
+
const notificationService = accessor.get(INotificationService);
|
1128
|
+
const tunnelService = accessor.get(ITunnelService);
|
1129
|
+
remoteExplorerService.setEditable(undefined, TunnelEditId.New, {
|
1130
|
+
onFinish: async (value, success) => {
|
1131
|
+
remoteExplorerService.setEditable(undefined, TunnelEditId.New, null);
|
1132
|
+
let parsed;
|
1133
|
+
if (success && (parsed = parseAddress(value))) {
|
1134
|
+
remoteExplorerService.forward({
|
1135
|
+
remote: { host: parsed.host, port: parsed.port },
|
1136
|
+
elevateIfNeeded: true
|
1137
|
+
}).then(tunnelOrError => error(notificationService, tunnelOrError, parsed.host, parsed.port));
|
1138
|
+
}
|
1139
|
+
},
|
1140
|
+
validationMessage: (value) => validateInput(remoteExplorerService, tunnelService, value, tunnelService.canElevate),
|
1141
|
+
placeholder: forwardPrompt
|
1142
|
+
});
|
1143
|
+
};
|
1144
|
+
}
|
1145
|
+
ForwardPortAction.inlineHandler = inlineHandler;
|
1146
|
+
function commandPaletteHandler() {
|
1147
|
+
return async (accessor, arg) => {
|
1148
|
+
const remoteExplorerService = accessor.get(IRemoteExplorerService);
|
1149
|
+
const notificationService = accessor.get(INotificationService);
|
1150
|
+
const viewsService = accessor.get(IViewsService);
|
1151
|
+
const quickInputService = accessor.get(IQuickInputService);
|
1152
|
+
const tunnelService = accessor.get(ITunnelService);
|
1153
|
+
await viewsService.openView(TunnelPanel.ID, true);
|
1154
|
+
const value = await quickInputService.input({
|
1155
|
+
prompt: forwardPrompt,
|
1156
|
+
validateInput: (value) => Promise.resolve(validateInput(remoteExplorerService, tunnelService, value, tunnelService.canElevate))
|
1157
|
+
});
|
1158
|
+
let parsed;
|
1159
|
+
if (value && (parsed = parseAddress(value))) {
|
1160
|
+
remoteExplorerService.forward({
|
1161
|
+
remote: { host: parsed.host, port: parsed.port },
|
1162
|
+
elevateIfNeeded: true
|
1163
|
+
}).then(tunnel => error(notificationService, tunnel, parsed.host, parsed.port));
|
1164
|
+
}
|
1165
|
+
};
|
1166
|
+
}
|
1167
|
+
ForwardPortAction.commandPaletteHandler = commandPaletteHandler;
|
1168
|
+
})(ForwardPortAction || (ForwardPortAction = {}));
|
1169
|
+
function makeTunnelPicks(tunnels, remoteExplorerService, tunnelService) {
|
1170
|
+
const picks = ( tunnels.map(forwarded => {
|
1171
|
+
const item = TunnelItem.createFromTunnel(remoteExplorerService, tunnelService, forwarded);
|
1172
|
+
return {
|
1173
|
+
label: item.label,
|
1174
|
+
description: item.processDescription,
|
1175
|
+
tunnel: item
|
1176
|
+
};
|
1177
|
+
}));
|
1178
|
+
if (picks.length === 0) {
|
1179
|
+
picks.push({
|
1180
|
+
label: ( localize(
|
1181
|
+
8347,
|
1182
|
+
"No ports currently forwarded. Try running the {0} command",
|
1183
|
+
ForwardPortAction.LABEL.value
|
1184
|
+
))
|
1185
|
+
});
|
1186
|
+
}
|
1187
|
+
return picks;
|
1188
|
+
}
|
1189
|
+
var ClosePortAction;
|
1190
|
+
(function (ClosePortAction) {
|
1191
|
+
ClosePortAction.INLINE_ID = 'remote.tunnel.closeInline';
|
1192
|
+
ClosePortAction.COMMANDPALETTE_ID = 'remote.tunnel.closeCommandPalette';
|
1193
|
+
ClosePortAction.LABEL = ( localize2(8348, "Stop Forwarding Port"));
|
1194
|
+
function inlineHandler() {
|
1195
|
+
return async (accessor, arg) => {
|
1196
|
+
const contextKeyService = accessor.get(IContextKeyService);
|
1197
|
+
const remoteExplorerService = accessor.get(IRemoteExplorerService);
|
1198
|
+
let ports = [];
|
1199
|
+
const multiSelectContext = contextKeyService.getContextKeyValue(TunnelViewMultiSelectionKeyName);
|
1200
|
+
if (multiSelectContext) {
|
1201
|
+
multiSelectContext.forEach(context => {
|
1202
|
+
const tunnel = remoteExplorerService.tunnelModel.forwarded.get(context);
|
1203
|
+
if (tunnel) {
|
1204
|
+
ports?.push(tunnel);
|
1205
|
+
}
|
1206
|
+
});
|
1207
|
+
}
|
1208
|
+
else if (isITunnelItem(arg)) {
|
1209
|
+
ports = [arg];
|
1210
|
+
}
|
1211
|
+
else {
|
1212
|
+
const context = contextKeyService.getContextKeyValue(TunnelViewSelectionKeyName);
|
1213
|
+
const tunnel = context ? remoteExplorerService.tunnelModel.forwarded.get(context) : undefined;
|
1214
|
+
if (tunnel) {
|
1215
|
+
ports = [tunnel];
|
1216
|
+
}
|
1217
|
+
}
|
1218
|
+
if (!ports || ports.length === 0) {
|
1219
|
+
return;
|
1220
|
+
}
|
1221
|
+
return Promise.all(( ports.map(
|
1222
|
+
port => remoteExplorerService.close({ host: port.remoteHost, port: port.remotePort }, TunnelCloseReason.User)
|
1223
|
+
)));
|
1224
|
+
};
|
1225
|
+
}
|
1226
|
+
ClosePortAction.inlineHandler = inlineHandler;
|
1227
|
+
function commandPaletteHandler() {
|
1228
|
+
return async (accessor) => {
|
1229
|
+
const quickInputService = accessor.get(IQuickInputService);
|
1230
|
+
const remoteExplorerService = accessor.get(IRemoteExplorerService);
|
1231
|
+
const tunnelService = accessor.get(ITunnelService);
|
1232
|
+
const commandService = accessor.get(ICommandService);
|
1233
|
+
const picks = makeTunnelPicks(Array.from(( remoteExplorerService.tunnelModel.forwarded.values())).filter(tunnel => tunnel.closeable), remoteExplorerService, tunnelService);
|
1234
|
+
const result = await quickInputService.pick(picks, { placeHolder: ( localize(8349, "Choose a port to stop forwarding")) });
|
1235
|
+
if (result && result.tunnel) {
|
1236
|
+
await remoteExplorerService.close({ host: result.tunnel.remoteHost, port: result.tunnel.remotePort }, TunnelCloseReason.User);
|
1237
|
+
}
|
1238
|
+
else if (result) {
|
1239
|
+
await commandService.executeCommand(ForwardPortAction.COMMANDPALETTE_ID);
|
1240
|
+
}
|
1241
|
+
};
|
1242
|
+
}
|
1243
|
+
ClosePortAction.commandPaletteHandler = commandPaletteHandler;
|
1244
|
+
})(ClosePortAction || (ClosePortAction = {}));
|
1245
|
+
var OpenPortInBrowserAction;
|
1246
|
+
(function (OpenPortInBrowserAction) {
|
1247
|
+
OpenPortInBrowserAction.ID = 'remote.tunnel.open';
|
1248
|
+
OpenPortInBrowserAction.LABEL = ( localize(8350, "Open in Browser"));
|
1249
|
+
function handler() {
|
1250
|
+
return async (accessor, arg) => {
|
1251
|
+
let key;
|
1252
|
+
if (isITunnelItem(arg)) {
|
1253
|
+
key = makeAddress(arg.remoteHost, arg.remotePort);
|
1254
|
+
}
|
1255
|
+
else if (arg.tunnelRemoteHost && arg.tunnelRemotePort) {
|
1256
|
+
key = makeAddress(arg.tunnelRemoteHost, arg.tunnelRemotePort);
|
1257
|
+
}
|
1258
|
+
if (key) {
|
1259
|
+
const model = accessor.get(IRemoteExplorerService).tunnelModel;
|
1260
|
+
const openerService = accessor.get(IOpenerService);
|
1261
|
+
return run(model, openerService, key);
|
1262
|
+
}
|
1263
|
+
};
|
1264
|
+
}
|
1265
|
+
OpenPortInBrowserAction.handler = handler;
|
1266
|
+
function run(model, openerService, key) {
|
1267
|
+
const tunnel = model.forwarded.get(key) || model.detected.get(key);
|
1268
|
+
if (tunnel) {
|
1269
|
+
return openerService.open(tunnel.localUri, { allowContributedOpeners: false });
|
1270
|
+
}
|
1271
|
+
return Promise.resolve();
|
1272
|
+
}
|
1273
|
+
OpenPortInBrowserAction.run = run;
|
1274
|
+
})(OpenPortInBrowserAction || (OpenPortInBrowserAction = {}));
|
1275
|
+
var OpenPortInPreviewAction;
|
1276
|
+
(function (OpenPortInPreviewAction) {
|
1277
|
+
OpenPortInPreviewAction.ID = 'remote.tunnel.openPreview';
|
1278
|
+
OpenPortInPreviewAction.LABEL = ( localize(8351, "Preview in Editor"));
|
1279
|
+
function handler() {
|
1280
|
+
return async (accessor, arg) => {
|
1281
|
+
let key;
|
1282
|
+
if (isITunnelItem(arg)) {
|
1283
|
+
key = makeAddress(arg.remoteHost, arg.remotePort);
|
1284
|
+
}
|
1285
|
+
else if (arg.tunnelRemoteHost && arg.tunnelRemotePort) {
|
1286
|
+
key = makeAddress(arg.tunnelRemoteHost, arg.tunnelRemotePort);
|
1287
|
+
}
|
1288
|
+
if (key) {
|
1289
|
+
const model = accessor.get(IRemoteExplorerService).tunnelModel;
|
1290
|
+
const openerService = accessor.get(IOpenerService);
|
1291
|
+
const externalOpenerService = accessor.get(IExternalUriOpenerService);
|
1292
|
+
return run(model, openerService, externalOpenerService, key);
|
1293
|
+
}
|
1294
|
+
};
|
1295
|
+
}
|
1296
|
+
OpenPortInPreviewAction.handler = handler;
|
1297
|
+
async function run(model, openerService, externalOpenerService, key) {
|
1298
|
+
const tunnel = model.forwarded.get(key) || model.detected.get(key);
|
1299
|
+
if (tunnel) {
|
1300
|
+
const remoteHost = tunnel.remoteHost.includes(':') ? `[${tunnel.remoteHost}]` : tunnel.remoteHost;
|
1301
|
+
const sourceUri = ( URI.parse(`http://${remoteHost}:${tunnel.remotePort}`));
|
1302
|
+
const opener = await externalOpenerService.getOpener(tunnel.localUri, { sourceUri }, CancellationToken.None);
|
1303
|
+
if (opener) {
|
1304
|
+
return opener.openExternalUri(tunnel.localUri, { sourceUri }, CancellationToken.None);
|
1305
|
+
}
|
1306
|
+
return openerService.open(tunnel.localUri);
|
1307
|
+
}
|
1308
|
+
return Promise.resolve();
|
1309
|
+
}
|
1310
|
+
OpenPortInPreviewAction.run = run;
|
1311
|
+
})(OpenPortInPreviewAction || (OpenPortInPreviewAction = {}));
|
1312
|
+
var OpenPortInBrowserCommandPaletteAction;
|
1313
|
+
(function (OpenPortInBrowserCommandPaletteAction) {
|
1314
|
+
OpenPortInBrowserCommandPaletteAction.ID = 'remote.tunnel.openCommandPalette';
|
1315
|
+
OpenPortInBrowserCommandPaletteAction.LABEL = ( localize(8352, "Open Port in Browser"));
|
1316
|
+
function handler() {
|
1317
|
+
return async (accessor, arg) => {
|
1318
|
+
const remoteExplorerService = accessor.get(IRemoteExplorerService);
|
1319
|
+
const tunnelService = accessor.get(ITunnelService);
|
1320
|
+
const model = remoteExplorerService.tunnelModel;
|
1321
|
+
const quickPickService = accessor.get(IQuickInputService);
|
1322
|
+
const openerService = accessor.get(IOpenerService);
|
1323
|
+
const commandService = accessor.get(ICommandService);
|
1324
|
+
const options = ( [...model.forwarded, ...model.detected].map(value => {
|
1325
|
+
const tunnelItem = TunnelItem.createFromTunnel(remoteExplorerService, tunnelService, value[1]);
|
1326
|
+
return {
|
1327
|
+
label: tunnelItem.label,
|
1328
|
+
description: tunnelItem.processDescription,
|
1329
|
+
tunnel: tunnelItem
|
1330
|
+
};
|
1331
|
+
}));
|
1332
|
+
if (options.length === 0) {
|
1333
|
+
options.push({
|
1334
|
+
label: ( localize(8353, "No ports currently forwarded. Open the Ports view to get started."))
|
1335
|
+
});
|
1336
|
+
}
|
1337
|
+
else {
|
1338
|
+
options.push({
|
1339
|
+
label: ( localize(8354, "Open the Ports view..."))
|
1340
|
+
});
|
1341
|
+
}
|
1342
|
+
const picked = await quickPickService.pick(options, { placeHolder: ( localize(8355, "Choose the port to open")) });
|
1343
|
+
if (picked && picked.tunnel) {
|
1344
|
+
return OpenPortInBrowserAction.run(model, openerService, makeAddress(picked.tunnel.remoteHost, picked.tunnel.remotePort));
|
1345
|
+
}
|
1346
|
+
else if (picked) {
|
1347
|
+
return commandService.executeCommand(`${TUNNEL_VIEW_ID}.focus`);
|
1348
|
+
}
|
1349
|
+
};
|
1350
|
+
}
|
1351
|
+
OpenPortInBrowserCommandPaletteAction.handler = handler;
|
1352
|
+
})(OpenPortInBrowserCommandPaletteAction || (OpenPortInBrowserCommandPaletteAction = {}));
|
1353
|
+
var CopyAddressAction;
|
1354
|
+
(function (CopyAddressAction) {
|
1355
|
+
CopyAddressAction.INLINE_ID = 'remote.tunnel.copyAddressInline';
|
1356
|
+
CopyAddressAction.COMMANDPALETTE_ID = 'remote.tunnel.copyAddressCommandPalette';
|
1357
|
+
CopyAddressAction.INLINE_LABEL = ( localize(8356, "Copy Local Address"));
|
1358
|
+
CopyAddressAction.COMMANDPALETTE_LABEL = ( localize(8357, "Copy Forwarded Port Address"));
|
1359
|
+
async function copyAddress(remoteExplorerService, clipboardService, tunnelItem) {
|
1360
|
+
const address = remoteExplorerService.tunnelModel.address(tunnelItem.remoteHost, tunnelItem.remotePort);
|
1361
|
+
if (address) {
|
1362
|
+
await clipboardService.writeText(( address.toString()));
|
1363
|
+
}
|
1364
|
+
}
|
1365
|
+
function inlineHandler() {
|
1366
|
+
return async (accessor, arg) => {
|
1367
|
+
const remoteExplorerService = accessor.get(IRemoteExplorerService);
|
1368
|
+
let tunnelItem;
|
1369
|
+
if (isITunnelItem(arg)) {
|
1370
|
+
tunnelItem = arg;
|
1371
|
+
}
|
1372
|
+
else {
|
1373
|
+
const context = accessor.get(IContextKeyService).getContextKeyValue(TunnelViewSelectionKeyName);
|
1374
|
+
tunnelItem = context ? remoteExplorerService.tunnelModel.forwarded.get(context) : undefined;
|
1375
|
+
}
|
1376
|
+
if (tunnelItem) {
|
1377
|
+
return copyAddress(remoteExplorerService, accessor.get(IClipboardService), tunnelItem);
|
1378
|
+
}
|
1379
|
+
};
|
1380
|
+
}
|
1381
|
+
CopyAddressAction.inlineHandler = inlineHandler;
|
1382
|
+
function commandPaletteHandler() {
|
1383
|
+
return async (accessor, arg) => {
|
1384
|
+
const quickInputService = accessor.get(IQuickInputService);
|
1385
|
+
const remoteExplorerService = accessor.get(IRemoteExplorerService);
|
1386
|
+
const tunnelService = accessor.get(ITunnelService);
|
1387
|
+
const commandService = accessor.get(ICommandService);
|
1388
|
+
const clipboardService = accessor.get(IClipboardService);
|
1389
|
+
const tunnels = Array.from(( remoteExplorerService.tunnelModel.forwarded.values())).concat(Array.from(( remoteExplorerService.tunnelModel.detected.values())));
|
1390
|
+
const result = await quickInputService.pick(makeTunnelPicks(tunnels, remoteExplorerService, tunnelService), { placeHolder: ( localize(8358, "Choose a forwarded port")) });
|
1391
|
+
if (result && result.tunnel) {
|
1392
|
+
await copyAddress(remoteExplorerService, clipboardService, result.tunnel);
|
1393
|
+
}
|
1394
|
+
else if (result) {
|
1395
|
+
await commandService.executeCommand(ForwardPortAction.COMMANDPALETTE_ID);
|
1396
|
+
}
|
1397
|
+
};
|
1398
|
+
}
|
1399
|
+
CopyAddressAction.commandPaletteHandler = commandPaletteHandler;
|
1400
|
+
})(CopyAddressAction || (CopyAddressAction = {}));
|
1401
|
+
var ChangeLocalPortAction;
|
1402
|
+
(function (ChangeLocalPortAction) {
|
1403
|
+
ChangeLocalPortAction.ID = 'remote.tunnel.changeLocalPort';
|
1404
|
+
ChangeLocalPortAction.LABEL = ( localize(8359, "Change Local Address Port"));
|
1405
|
+
function validateInput(tunnelService, value, canElevate) {
|
1406
|
+
if (!value.match(/^[0-9]+$/)) {
|
1407
|
+
return { content: ( localize(8360, "Local port should be a number.")), severity: Severity.Error };
|
1408
|
+
}
|
1409
|
+
else if (Number(value) >= maxPortNumber) {
|
1410
|
+
return { content: invalidPortNumberString, severity: Severity.Error };
|
1411
|
+
}
|
1412
|
+
else if (canElevate && tunnelService.isPortPrivileged(Number(value))) {
|
1413
|
+
return { content: requiresSudoString, severity: Severity.Info };
|
1414
|
+
}
|
1415
|
+
return null;
|
1416
|
+
}
|
1417
|
+
function handler() {
|
1418
|
+
return async (accessor, arg) => {
|
1419
|
+
const remoteExplorerService = accessor.get(IRemoteExplorerService);
|
1420
|
+
const notificationService = accessor.get(INotificationService);
|
1421
|
+
const tunnelService = accessor.get(ITunnelService);
|
1422
|
+
let tunnelContext;
|
1423
|
+
if (isITunnelItem(arg)) {
|
1424
|
+
tunnelContext = arg;
|
1425
|
+
}
|
1426
|
+
else {
|
1427
|
+
const context = accessor.get(IContextKeyService).getContextKeyValue(TunnelViewSelectionKeyName);
|
1428
|
+
const tunnel = context ? remoteExplorerService.tunnelModel.forwarded.get(context) : undefined;
|
1429
|
+
if (tunnel) {
|
1430
|
+
const tunnelService = accessor.get(ITunnelService);
|
1431
|
+
tunnelContext = TunnelItem.createFromTunnel(remoteExplorerService, tunnelService, tunnel);
|
1432
|
+
}
|
1433
|
+
}
|
1434
|
+
if (tunnelContext) {
|
1435
|
+
const tunnelItem = tunnelContext;
|
1436
|
+
remoteExplorerService.setEditable(tunnelItem, TunnelEditId.LocalPort, {
|
1437
|
+
onFinish: async (value, success) => {
|
1438
|
+
remoteExplorerService.setEditable(tunnelItem, TunnelEditId.LocalPort, null);
|
1439
|
+
if (success) {
|
1440
|
+
await remoteExplorerService.close({ host: tunnelItem.remoteHost, port: tunnelItem.remotePort }, TunnelCloseReason.Other);
|
1441
|
+
const numberValue = Number(value);
|
1442
|
+
const newForward = await remoteExplorerService.forward({
|
1443
|
+
remote: { host: tunnelItem.remoteHost, port: tunnelItem.remotePort },
|
1444
|
+
local: numberValue,
|
1445
|
+
name: tunnelItem.name,
|
1446
|
+
elevateIfNeeded: true,
|
1447
|
+
source: tunnelItem.source
|
1448
|
+
});
|
1449
|
+
if (newForward && (typeof newForward !== 'string') && newForward.tunnelLocalPort !== numberValue) {
|
1450
|
+
notificationService.warn(( localize(
|
1451
|
+
8361,
|
1452
|
+
"The local port {0} is not available. Port number {1} has been used instead",
|
1453
|
+
value,
|
1454
|
+
newForward.tunnelLocalPort ?? newForward.localAddress
|
1455
|
+
)));
|
1456
|
+
}
|
1457
|
+
}
|
1458
|
+
},
|
1459
|
+
validationMessage: (value) => validateInput(tunnelService, value, tunnelService.canElevate),
|
1460
|
+
placeholder: ( localize(8362, "New local port"))
|
1461
|
+
});
|
1462
|
+
}
|
1463
|
+
};
|
1464
|
+
}
|
1465
|
+
ChangeLocalPortAction.handler = handler;
|
1466
|
+
})(ChangeLocalPortAction || (ChangeLocalPortAction = {}));
|
1467
|
+
var ChangeTunnelPrivacyAction;
|
1468
|
+
(function (ChangeTunnelPrivacyAction) {
|
1469
|
+
function handler(privacyId) {
|
1470
|
+
return async (accessor, arg) => {
|
1471
|
+
if (isITunnelItem(arg)) {
|
1472
|
+
const remoteExplorerService = accessor.get(IRemoteExplorerService);
|
1473
|
+
await remoteExplorerService.close({ host: arg.remoteHost, port: arg.remotePort }, TunnelCloseReason.Other);
|
1474
|
+
return remoteExplorerService.forward({
|
1475
|
+
remote: { host: arg.remoteHost, port: arg.remotePort },
|
1476
|
+
local: arg.localPort,
|
1477
|
+
name: arg.name,
|
1478
|
+
elevateIfNeeded: true,
|
1479
|
+
privacy: privacyId,
|
1480
|
+
source: arg.source
|
1481
|
+
});
|
1482
|
+
}
|
1483
|
+
return undefined;
|
1484
|
+
};
|
1485
|
+
}
|
1486
|
+
ChangeTunnelPrivacyAction.handler = handler;
|
1487
|
+
})(ChangeTunnelPrivacyAction || (ChangeTunnelPrivacyAction = {}));
|
1488
|
+
var SetTunnelProtocolAction;
|
1489
|
+
(function (SetTunnelProtocolAction) {
|
1490
|
+
SetTunnelProtocolAction.ID_HTTP = 'remote.tunnel.setProtocolHttp';
|
1491
|
+
SetTunnelProtocolAction.ID_HTTPS = 'remote.tunnel.setProtocolHttps';
|
1492
|
+
SetTunnelProtocolAction.LABEL_HTTP = ( localize(8363, "HTTP"));
|
1493
|
+
SetTunnelProtocolAction.LABEL_HTTPS = ( localize(8364, "HTTPS"));
|
1494
|
+
async function handler(arg, protocol, remoteExplorerService, environmentService) {
|
1495
|
+
if (isITunnelItem(arg)) {
|
1496
|
+
const attributes = {
|
1497
|
+
protocol
|
1498
|
+
};
|
1499
|
+
const target = environmentService.remoteAuthority ? ConfigurationTarget.USER_REMOTE : ConfigurationTarget.USER_LOCAL;
|
1500
|
+
return remoteExplorerService.tunnelModel.configPortsAttributes.addAttributes(arg.remotePort, attributes, target);
|
1501
|
+
}
|
1502
|
+
}
|
1503
|
+
function handlerHttp() {
|
1504
|
+
return async (accessor, arg) => {
|
1505
|
+
return handler(arg, TunnelProtocol.Http, accessor.get(IRemoteExplorerService), accessor.get(IWorkbenchEnvironmentService));
|
1506
|
+
};
|
1507
|
+
}
|
1508
|
+
SetTunnelProtocolAction.handlerHttp = handlerHttp;
|
1509
|
+
function handlerHttps() {
|
1510
|
+
return async (accessor, arg) => {
|
1511
|
+
return handler(arg, TunnelProtocol.Https, accessor.get(IRemoteExplorerService), accessor.get(IWorkbenchEnvironmentService));
|
1512
|
+
};
|
1513
|
+
}
|
1514
|
+
SetTunnelProtocolAction.handlerHttps = handlerHttps;
|
1515
|
+
})(SetTunnelProtocolAction || (SetTunnelProtocolAction = {}));
|
1516
|
+
const tunnelViewCommandsWeightBonus = 10;
|
1517
|
+
const isForwardedExpr = ( TunnelTypeContextKey.isEqualTo(TunnelType.Forwarded));
|
1518
|
+
const isForwardedOrDetectedExpr = ( ContextKeyExpr.or(isForwardedExpr, ( TunnelTypeContextKey.isEqualTo(TunnelType.Detected))));
|
1519
|
+
const isNotMultiSelectionExpr = ( TunnelViewMultiSelectionContextKey.isEqualTo(undefined));
|
1520
|
+
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
1521
|
+
id: LabelTunnelAction.ID,
|
1522
|
+
weight: KeybindingWeight.WorkbenchContrib + tunnelViewCommandsWeightBonus,
|
1523
|
+
when: ( ContextKeyExpr.and(TunnelViewFocusContextKey, isForwardedExpr, isNotMultiSelectionExpr)),
|
1524
|
+
primary: KeyCode.F2,
|
1525
|
+
mac: {
|
1526
|
+
primary: KeyCode.Enter
|
1527
|
+
},
|
1528
|
+
handler: LabelTunnelAction.handler()
|
1529
|
+
});
|
1530
|
+
CommandsRegistry.registerCommand(ForwardPortAction.INLINE_ID, ForwardPortAction.inlineHandler());
|
1531
|
+
CommandsRegistry.registerCommand(ForwardPortAction.COMMANDPALETTE_ID, ForwardPortAction.commandPaletteHandler());
|
1532
|
+
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
1533
|
+
id: ClosePortAction.INLINE_ID,
|
1534
|
+
weight: KeybindingWeight.WorkbenchContrib + tunnelViewCommandsWeightBonus,
|
1535
|
+
when: ( ContextKeyExpr.and(TunnelCloseableContextKey, TunnelViewFocusContextKey)),
|
1536
|
+
primary: KeyCode.Delete,
|
1537
|
+
mac: {
|
1538
|
+
primary: KeyMod.CtrlCmd | KeyCode.Backspace,
|
1539
|
+
secondary: [KeyCode.Delete]
|
1540
|
+
},
|
1541
|
+
handler: ClosePortAction.inlineHandler()
|
1542
|
+
});
|
1543
|
+
CommandsRegistry.registerCommand(ClosePortAction.COMMANDPALETTE_ID, ClosePortAction.commandPaletteHandler());
|
1544
|
+
CommandsRegistry.registerCommand(OpenPortInBrowserAction.ID, OpenPortInBrowserAction.handler());
|
1545
|
+
CommandsRegistry.registerCommand(OpenPortInPreviewAction.ID, OpenPortInPreviewAction.handler());
|
1546
|
+
CommandsRegistry.registerCommand(OpenPortInBrowserCommandPaletteAction.ID, OpenPortInBrowserCommandPaletteAction.handler());
|
1547
|
+
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
1548
|
+
id: CopyAddressAction.INLINE_ID,
|
1549
|
+
weight: KeybindingWeight.WorkbenchContrib + tunnelViewCommandsWeightBonus,
|
1550
|
+
when: ( ContextKeyExpr.and(
|
1551
|
+
TunnelViewFocusContextKey,
|
1552
|
+
isForwardedOrDetectedExpr,
|
1553
|
+
isNotMultiSelectionExpr
|
1554
|
+
)),
|
1555
|
+
primary: KeyMod.CtrlCmd | KeyCode.KeyC,
|
1556
|
+
handler: CopyAddressAction.inlineHandler()
|
1557
|
+
});
|
1558
|
+
CommandsRegistry.registerCommand(CopyAddressAction.COMMANDPALETTE_ID, CopyAddressAction.commandPaletteHandler());
|
1559
|
+
CommandsRegistry.registerCommand(ChangeLocalPortAction.ID, ChangeLocalPortAction.handler());
|
1560
|
+
CommandsRegistry.registerCommand(SetTunnelProtocolAction.ID_HTTP, SetTunnelProtocolAction.handlerHttp());
|
1561
|
+
CommandsRegistry.registerCommand(SetTunnelProtocolAction.ID_HTTPS, SetTunnelProtocolAction.handlerHttps());
|
1562
|
+
MenuRegistry.appendMenuItem(MenuId.CommandPalette, ({
|
1563
|
+
command: {
|
1564
|
+
id: ClosePortAction.COMMANDPALETTE_ID,
|
1565
|
+
title: ClosePortAction.LABEL
|
1566
|
+
},
|
1567
|
+
when: forwardedPortsViewEnabled
|
1568
|
+
}));
|
1569
|
+
MenuRegistry.appendMenuItem(MenuId.CommandPalette, ({
|
1570
|
+
command: {
|
1571
|
+
id: ForwardPortAction.COMMANDPALETTE_ID,
|
1572
|
+
title: ForwardPortAction.LABEL
|
1573
|
+
},
|
1574
|
+
when: forwardedPortsViewEnabled
|
1575
|
+
}));
|
1576
|
+
MenuRegistry.appendMenuItem(MenuId.CommandPalette, ({
|
1577
|
+
command: {
|
1578
|
+
id: CopyAddressAction.COMMANDPALETTE_ID,
|
1579
|
+
title: CopyAddressAction.COMMANDPALETTE_LABEL
|
1580
|
+
},
|
1581
|
+
when: forwardedPortsViewEnabled
|
1582
|
+
}));
|
1583
|
+
MenuRegistry.appendMenuItem(MenuId.CommandPalette, ({
|
1584
|
+
command: {
|
1585
|
+
id: OpenPortInBrowserCommandPaletteAction.ID,
|
1586
|
+
title: OpenPortInBrowserCommandPaletteAction.LABEL
|
1587
|
+
},
|
1588
|
+
when: forwardedPortsViewEnabled
|
1589
|
+
}));
|
1590
|
+
MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({
|
1591
|
+
group: '._open',
|
1592
|
+
order: 0,
|
1593
|
+
command: {
|
1594
|
+
id: OpenPortInBrowserAction.ID,
|
1595
|
+
title: OpenPortInBrowserAction.LABEL,
|
1596
|
+
},
|
1597
|
+
when: ( ContextKeyExpr.and(isForwardedOrDetectedExpr, isNotMultiSelectionExpr))
|
1598
|
+
}));
|
1599
|
+
MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({
|
1600
|
+
group: '._open',
|
1601
|
+
order: 1,
|
1602
|
+
command: {
|
1603
|
+
id: OpenPortInPreviewAction.ID,
|
1604
|
+
title: OpenPortInPreviewAction.LABEL,
|
1605
|
+
},
|
1606
|
+
when: ( ContextKeyExpr.and(isForwardedOrDetectedExpr, isNotMultiSelectionExpr))
|
1607
|
+
}));
|
1608
|
+
MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({
|
1609
|
+
group: '0_manage',
|
1610
|
+
order: 1,
|
1611
|
+
command: {
|
1612
|
+
id: LabelTunnelAction.ID,
|
1613
|
+
title: LabelTunnelAction.LABEL,
|
1614
|
+
icon: labelPortIcon
|
1615
|
+
},
|
1616
|
+
when: ( ContextKeyExpr.and(isForwardedExpr, isNotMultiSelectionExpr))
|
1617
|
+
}));
|
1618
|
+
MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({
|
1619
|
+
group: '2_localaddress',
|
1620
|
+
order: 0,
|
1621
|
+
command: {
|
1622
|
+
id: CopyAddressAction.INLINE_ID,
|
1623
|
+
title: CopyAddressAction.INLINE_LABEL,
|
1624
|
+
},
|
1625
|
+
when: ( ContextKeyExpr.and(isForwardedOrDetectedExpr, isNotMultiSelectionExpr))
|
1626
|
+
}));
|
1627
|
+
MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({
|
1628
|
+
group: '2_localaddress',
|
1629
|
+
order: 1,
|
1630
|
+
command: {
|
1631
|
+
id: ChangeLocalPortAction.ID,
|
1632
|
+
title: ChangeLocalPortAction.LABEL,
|
1633
|
+
},
|
1634
|
+
when: ( ContextKeyExpr.and(isForwardedExpr, PortChangableContextKey, isNotMultiSelectionExpr))
|
1635
|
+
}));
|
1636
|
+
MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({
|
1637
|
+
group: '2_localaddress',
|
1638
|
+
order: 2,
|
1639
|
+
submenu: MenuId.TunnelPrivacy,
|
1640
|
+
title: ( localize(8365, "Port Visibility")),
|
1641
|
+
when: ( ContextKeyExpr.and(isForwardedExpr, TunnelPrivacyEnabledContextKey))
|
1642
|
+
}));
|
1643
|
+
MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({
|
1644
|
+
group: '2_localaddress',
|
1645
|
+
order: 3,
|
1646
|
+
submenu: MenuId.TunnelProtocol,
|
1647
|
+
title: ( localize(8366, "Change Port Protocol")),
|
1648
|
+
when: ( ContextKeyExpr.and(isForwardedExpr, isNotMultiSelectionExpr, ProtocolChangeableContextKey))
|
1649
|
+
}));
|
1650
|
+
MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({
|
1651
|
+
group: '3_forward',
|
1652
|
+
order: 0,
|
1653
|
+
command: {
|
1654
|
+
id: ClosePortAction.INLINE_ID,
|
1655
|
+
title: ClosePortAction.LABEL,
|
1656
|
+
},
|
1657
|
+
when: TunnelCloseableContextKey
|
1658
|
+
}));
|
1659
|
+
MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({
|
1660
|
+
group: '3_forward',
|
1661
|
+
order: 1,
|
1662
|
+
command: {
|
1663
|
+
id: ForwardPortAction.INLINE_ID,
|
1664
|
+
title: ForwardPortAction.LABEL,
|
1665
|
+
},
|
1666
|
+
}));
|
1667
|
+
MenuRegistry.appendMenuItem(MenuId.TunnelProtocol, ({
|
1668
|
+
order: 0,
|
1669
|
+
command: {
|
1670
|
+
id: SetTunnelProtocolAction.ID_HTTP,
|
1671
|
+
title: SetTunnelProtocolAction.LABEL_HTTP,
|
1672
|
+
toggled: ( TunnelProtocolContextKey.isEqualTo(TunnelProtocol.Http))
|
1673
|
+
}
|
1674
|
+
}));
|
1675
|
+
MenuRegistry.appendMenuItem(MenuId.TunnelProtocol, ({
|
1676
|
+
order: 1,
|
1677
|
+
command: {
|
1678
|
+
id: SetTunnelProtocolAction.ID_HTTPS,
|
1679
|
+
title: SetTunnelProtocolAction.LABEL_HTTPS,
|
1680
|
+
toggled: ( TunnelProtocolContextKey.isEqualTo(TunnelProtocol.Https))
|
1681
|
+
}
|
1682
|
+
}));
|
1683
|
+
MenuRegistry.appendMenuItem(MenuId.TunnelPortInline, ({
|
1684
|
+
group: '0_manage',
|
1685
|
+
order: 0,
|
1686
|
+
command: {
|
1687
|
+
id: ForwardPortAction.INLINE_ID,
|
1688
|
+
title: ForwardPortAction.TREEITEM_LABEL,
|
1689
|
+
icon: forwardPortIcon
|
1690
|
+
},
|
1691
|
+
when: ( TunnelTypeContextKey.isEqualTo(TunnelType.Candidate))
|
1692
|
+
}));
|
1693
|
+
MenuRegistry.appendMenuItem(MenuId.TunnelPortInline, ({
|
1694
|
+
group: '0_manage',
|
1695
|
+
order: 4,
|
1696
|
+
command: {
|
1697
|
+
id: LabelTunnelAction.ID,
|
1698
|
+
title: LabelTunnelAction.LABEL,
|
1699
|
+
icon: labelPortIcon
|
1700
|
+
},
|
1701
|
+
when: isForwardedExpr
|
1702
|
+
}));
|
1703
|
+
MenuRegistry.appendMenuItem(MenuId.TunnelPortInline, ({
|
1704
|
+
group: '0_manage',
|
1705
|
+
order: 5,
|
1706
|
+
command: {
|
1707
|
+
id: ClosePortAction.INLINE_ID,
|
1708
|
+
title: ClosePortAction.LABEL,
|
1709
|
+
icon: stopForwardIcon
|
1710
|
+
},
|
1711
|
+
when: TunnelCloseableContextKey
|
1712
|
+
}));
|
1713
|
+
MenuRegistry.appendMenuItem(MenuId.TunnelLocalAddressInline, ({
|
1714
|
+
order: -1,
|
1715
|
+
command: {
|
1716
|
+
id: CopyAddressAction.INLINE_ID,
|
1717
|
+
title: CopyAddressAction.INLINE_LABEL,
|
1718
|
+
icon: copyAddressIcon
|
1719
|
+
},
|
1720
|
+
when: isForwardedOrDetectedExpr
|
1721
|
+
}));
|
1722
|
+
MenuRegistry.appendMenuItem(MenuId.TunnelLocalAddressInline, ({
|
1723
|
+
order: 0,
|
1724
|
+
command: {
|
1725
|
+
id: OpenPortInBrowserAction.ID,
|
1726
|
+
title: OpenPortInBrowserAction.LABEL,
|
1727
|
+
icon: openBrowserIcon
|
1728
|
+
},
|
1729
|
+
when: isForwardedOrDetectedExpr
|
1730
|
+
}));
|
1731
|
+
MenuRegistry.appendMenuItem(MenuId.TunnelLocalAddressInline, ({
|
1732
|
+
order: 1,
|
1733
|
+
command: {
|
1734
|
+
id: OpenPortInPreviewAction.ID,
|
1735
|
+
title: OpenPortInPreviewAction.LABEL,
|
1736
|
+
icon: openPreviewIcon
|
1737
|
+
},
|
1738
|
+
when: isForwardedOrDetectedExpr
|
1739
|
+
}));
|
1740
|
+
registerColor('ports.iconRunningProcessForeground', STATUS_BAR_REMOTE_ITEM_BACKGROUND, ( localize(
|
1741
|
+
8367,
|
1742
|
+
"The color of the icon for a port that has an associated running process."
|
1743
|
+
)));
|
1744
|
+
|
1745
|
+
export { ForwardPortAction, OpenPortInBrowserAction, OpenPortInPreviewAction, TunnelPanel, TunnelPanelDescriptor, TunnelViewModel, openPreviewEnabledContext };
|