mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-22 14:55:55 +01:00
Add badge for remote explorer
Fixes microsoft/vscode-remote-release#3824
This commit is contained in:
@@ -19,7 +19,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
||||
import { VIEWLET_ID as EXPLORER } from 'vs/workbench/contrib/files/common/files';
|
||||
import { VIEWLET_ID as SCM } from 'vs/workbench/contrib/scm/common/scm';
|
||||
import { VIEWLET_ID as DEBUG } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { VIEWLET_ID as REMOTE } from 'vs/workbench/contrib/remote/common/remote.contribution';
|
||||
import { VIEWLET_ID as REMOTE } from 'vs/workbench/contrib/remote/browser/remoteExplorer';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ViewletRegistry, Extensions as ViewletExtensions, ShowViewletAction } from 'vs/workbench/browser/viewlet';
|
||||
|
||||
@@ -17,9 +17,9 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { FilterViewPaneContainer } from 'vs/workbench/browser/parts/views/viewsViewlet';
|
||||
import { VIEWLET_ID } from 'vs/workbench/contrib/remote/common/remote.contribution';
|
||||
import { ForwardedPortsView, VIEWLET_ID } from 'vs/workbench/contrib/remote/browser/remoteExplorer';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IViewDescriptor, IViewsRegistry, Extensions, ViewContainerLocation, IViewContainersRegistry, IViewDescriptorService, IAddedViewDescriptorRef, IViewsService } from 'vs/workbench/common/views';
|
||||
import { IViewDescriptor, IViewsRegistry, Extensions, ViewContainerLocation, IViewContainersRegistry, IViewDescriptorService, IViewsService } from 'vs/workbench/common/views';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
@@ -44,7 +44,7 @@ import { Action, IActionViewItem, IAction } from 'vs/base/common/actions';
|
||||
import { isStringArray } from 'vs/base/common/types';
|
||||
import { IRemoteExplorerService, MakeAddress, mapHasTunnelLocalhostOrAllInterfaces } from 'vs/workbench/services/remote/common/remoteExplorerService';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { TunnelPanelDescriptor, TunnelViewModel, forwardedPortsViewEnabled, OpenPortInBrowserAction } from 'vs/workbench/contrib/remote/browser/tunnelView';
|
||||
import { forwardedPortsViewEnabled, OpenPortInBrowserAction } from 'vs/workbench/contrib/remote/browser/tunnelView';
|
||||
import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
|
||||
import { ITreeRenderer, ITreeNode, IAsyncDataSource } from 'vs/base/browser/ui/tree/tree';
|
||||
@@ -471,7 +471,6 @@ export class RemoteViewPaneContainer extends FilterViewPaneContainer implements
|
||||
private helpPanelDescriptor = new HelpPanelDescriptor(this);
|
||||
helpInformation: HelpInformation[] = [];
|
||||
private actions: IAction[] | undefined;
|
||||
private tunnelPanelDescriptor: TunnelPanelDescriptor | undefined;
|
||||
|
||||
constructor(
|
||||
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
|
||||
@@ -483,8 +482,8 @@ export class RemoteViewPaneContainer extends FilterViewPaneContainer implements
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IContextMenuService contextMenuService: IContextMenuService,
|
||||
@IExtensionService extensionService: IExtensionService,
|
||||
@IRemoteExplorerService private readonly remoteExplorerService: IRemoteExplorerService,
|
||||
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
|
||||
@IRemoteExplorerService readonly remoteExplorerService: IRemoteExplorerService,
|
||||
@IWorkbenchEnvironmentService readonly environmentService: IWorkbenchEnvironmentService,
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IViewDescriptorService viewDescriptorService: IViewDescriptorService
|
||||
) {
|
||||
@@ -555,18 +554,6 @@ export class RemoteViewPaneContainer extends FilterViewPaneContainer implements
|
||||
return title;
|
||||
}
|
||||
|
||||
onDidAddViewDescriptors(added: IAddedViewDescriptorRef[]): ViewPane[] {
|
||||
// Call to super MUST be first, since registering the additional view will cause this to be called again.
|
||||
const panels: ViewPane[] = super.onDidAddViewDescriptors(added);
|
||||
// This context key is set to false in the constructor, but is expected to be changed by resolver extensions to enable the forwarded ports view.
|
||||
const viewEnabled: boolean = !!forwardedPortsViewEnabled.getValue(this.contextKeyService);
|
||||
if (this.environmentService.remoteAuthority && !this.tunnelPanelDescriptor && viewEnabled) {
|
||||
this.tunnelPanelDescriptor = new TunnelPanelDescriptor(new TunnelViewModel(this.remoteExplorerService), this.environmentService);
|
||||
const viewsRegistry = Registry.as<IViewsRegistry>(Extensions.ViewsRegistry);
|
||||
viewsRegistry.registerViews([this.tunnelPanelDescriptor!], this.viewContainer);
|
||||
}
|
||||
return panels;
|
||||
}
|
||||
}
|
||||
|
||||
Registry.as<IViewContainersRegistry>(Extensions.ViewContainersRegistry).registerViewContainer(
|
||||
@@ -928,4 +915,5 @@ class AutomaticPortForwarding extends Disposable implements IWorkbenchContributi
|
||||
const workbenchContributionsRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
|
||||
workbenchContributionsRegistry.registerWorkbenchContribution(RemoteAgentConnectionStatusListener, LifecyclePhase.Eventually);
|
||||
workbenchContributionsRegistry.registerWorkbenchContribution(RemoteStatusIndicator, LifecyclePhase.Starting);
|
||||
workbenchContributionsRegistry.registerWorkbenchContribution(ForwardedPortsView, LifecyclePhase.Eventually);
|
||||
workbenchContributionsRegistry.registerWorkbenchContribution(AutomaticPortForwarding, LifecyclePhase.Eventually);
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as nls from 'vs/nls';
|
||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { Extensions, IViewDescriptorService, IViewsRegistry } from 'vs/workbench/common/views';
|
||||
import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity';
|
||||
import { IRemoteExplorerService, TUNNEL_VIEW_ID } from 'vs/workbench/services/remote/common/remoteExplorerService';
|
||||
import { forwardedPortsViewEnabled, TunnelPanelDescriptor, TunnelViewModel } from 'vs/workbench/contrib/remote/browser/tunnelView';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
|
||||
export const VIEWLET_ID = 'workbench.view.remote';
|
||||
|
||||
export class ForwardedPortsView extends Disposable implements IWorkbenchContribution {
|
||||
private contextKeyListener?: IDisposable;
|
||||
private _activityBadge?: IDisposable;
|
||||
|
||||
constructor(
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
|
||||
@IRemoteExplorerService private readonly remoteExplorerService: IRemoteExplorerService,
|
||||
@IViewDescriptorService private readonly viewDescriptorService: IViewDescriptorService,
|
||||
@IActivityService private readonly activityService: IActivityService
|
||||
) {
|
||||
super();
|
||||
this.enableForwardedPortsView();
|
||||
this.enableBadge();
|
||||
}
|
||||
|
||||
private enableForwardedPortsView() {
|
||||
if (this.contextKeyListener) {
|
||||
this.contextKeyListener.dispose();
|
||||
this.contextKeyListener = undefined;
|
||||
}
|
||||
|
||||
const viewEnabled: boolean = !!forwardedPortsViewEnabled.getValue(this.contextKeyService);
|
||||
if (this.environmentService.remoteAuthority && viewEnabled) {
|
||||
const tunnelPanelDescriptor = new TunnelPanelDescriptor(new TunnelViewModel(this.remoteExplorerService), this.environmentService);
|
||||
const viewsRegistry = Registry.as<IViewsRegistry>(Extensions.ViewsRegistry);
|
||||
const viewContainer = this.viewDescriptorService.getViewContainerById(VIEWLET_ID);
|
||||
if (viewContainer) {
|
||||
viewsRegistry.registerViews([tunnelPanelDescriptor!], viewContainer);
|
||||
}
|
||||
} else if (this.environmentService.remoteAuthority) {
|
||||
this.contextKeyListener = this.contextKeyService.onDidChangeContext(e => {
|
||||
if (e.affectsSome(new Set(forwardedPortsViewEnabled.keys()))) {
|
||||
this.enableForwardedPortsView();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private enableBadge() {
|
||||
this._register(this.remoteExplorerService.tunnelModel.onForwardPort(() => this.updateActivityBadge()));
|
||||
this._register(this.remoteExplorerService.tunnelModel.onClosePort(() => this.updateActivityBadge()));
|
||||
const disposable = Registry.as<IViewsRegistry>(Extensions.ViewsRegistry).onViewsRegistered(e => {
|
||||
if (e.find(view => view.views.find(viewDescriptor => viewDescriptor.id === TUNNEL_VIEW_ID))) {
|
||||
this.updateActivityBadge();
|
||||
disposable.dispose();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private updateActivityBadge() {
|
||||
if (this._activityBadge) {
|
||||
this._activityBadge.dispose();
|
||||
}
|
||||
if (this.remoteExplorerService.tunnelModel.forwarded.size > 0) {
|
||||
const viewContainer = this.viewDescriptorService.getViewContainerByViewId(TUNNEL_VIEW_ID);
|
||||
if (viewContainer) {
|
||||
this._activityBadge = this.activityService.showViewContainerActivity(viewContainer.id, {
|
||||
badge: new NumberBadge(this.remoteExplorerService.tunnelModel.forwarded.size, n => n === 1 ? nls.localize('1forwardedPort', "1 forwarded port") : nls.localize('nForwardedPorts', "{0} forwarded ports", n))
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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, ILocalizedString, SubmenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { createAndFillInContextMenuActions, createAndFillInActionBarActions, MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { IRemoteExplorerService, TunnelModel, MakeAddress, TunnelType, ITunnelItem, Tunnel, mapHasTunnelLocalhostOrAllInterfaces } from 'vs/workbench/services/remote/common/remoteExplorerService';
|
||||
import { IRemoteExplorerService, TunnelModel, MakeAddress, TunnelType, ITunnelItem, Tunnel, mapHasTunnelLocalhostOrAllInterfaces, TUNNEL_VIEW_ID } from 'vs/workbench/services/remote/common/remoteExplorerService';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { InputBox, MessageType } from 'vs/base/browser/ui/inputbox/inputBox';
|
||||
@@ -438,7 +438,7 @@ const PortChangableContextKey = new RawContextKey<boolean>('portChangable', fals
|
||||
class TunnelDataTree extends WorkbenchAsyncDataTree<any, any, any> { }
|
||||
|
||||
export class TunnelPanel extends ViewPane {
|
||||
static readonly ID = '~remote.forwardedPorts';
|
||||
static readonly ID = TUNNEL_VIEW_ID;
|
||||
static readonly TITLE = nls.localize('remote.tunnel', "Forwarded Ports");
|
||||
private tree!: TunnelDataTree;
|
||||
private tunnelTypeContext: IContextKey<TunnelType>;
|
||||
|
||||
@@ -21,8 +21,6 @@ import { ShowCandidateContribution } from 'vs/workbench/contrib/remote/common/sh
|
||||
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
|
||||
export const VIEWLET_ID = 'workbench.view.remote';
|
||||
|
||||
export class LabelContribution implements IWorkbenchContribution {
|
||||
constructor(
|
||||
@ILabelService private readonly labelService: ILabelService,
|
||||
|
||||
@@ -18,6 +18,7 @@ import { IAddressProvider } from 'vs/platform/remote/common/remoteAgentConnectio
|
||||
export const IRemoteExplorerService = createDecorator<IRemoteExplorerService>('remoteExplorerService');
|
||||
export const REMOTE_EXPLORER_TYPE_KEY: string = 'remote.explorerType';
|
||||
const TUNNELS_TO_RESTORE = 'remote.tunnels.toRestore';
|
||||
export const TUNNEL_VIEW_ID = '~remote.forwardedPorts';
|
||||
|
||||
export enum TunnelType {
|
||||
Candidate = 'Candidate',
|
||||
|
||||
Reference in New Issue
Block a user