Custom tooltip on the remote indicator. Fixes #126494

上级 99f4201e
......@@ -45,7 +45,8 @@
"label": "${path}",
"separator": "/",
"tildify": true,
"workspaceSuffix": "TestResolver"
"workspaceSuffix": "TestResolver",
"workspaceTooltip": "Remote running on the same machine"
}
}
],
......
......@@ -768,6 +768,10 @@ export class SimpleUriLabelService implements ILabelService {
public getHostLabel(): string {
return '';
}
public getHostTooltip(): string | undefined {
return undefined;
}
}
export class SimpleLayoutService implements ILayoutService {
......
......@@ -25,6 +25,7 @@ export interface ILabelService {
getUriBasenameLabel(resource: URI): string;
getWorkspaceLabel(workspace: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI | IWorkspace), options?: { verbose: boolean }): string;
getHostLabel(scheme: string, authority?: string): string;
getHostTooltip(scheme: string, authority?: string): string | undefined;
getSeparator(scheme: string, authority?: string): '/' | '\\';
registerFormatter(formatter: ResourceLabelFormatter): IDisposable;
......@@ -48,6 +49,7 @@ export interface ResourceLabelFormatting {
tildify?: boolean;
normalizeDriveLetter?: boolean;
workspaceSuffix?: string;
workspaceTooltip?: string;
authorityPrefix?: string;
stripPathStartingSeparator?: boolean;
}
......@@ -226,6 +226,7 @@ declare module 'vscode' {
tildify?: boolean;
normalizeDriveLetter?: boolean;
workspaceSuffix?: string;
workspaceTooltip?: string;
authorityPrefix?: string;
stripPathStartingSeparator?: boolean;
}
......
......@@ -25,7 +25,7 @@ import { isWeb } from 'vs/base/common/platform';
import { once } from 'vs/base/common/functional';
import { truncate } from 'vs/base/common/strings';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { getRemoteName, getVirtualWorkspaceLocation, getVirtualWorkspaceScheme } from 'vs/platform/remote/common/remoteHosts';
import { getRemoteName, getVirtualWorkspaceLocation } from 'vs/platform/remote/common/remoteHosts';
import { getCodiconAriaLabel } from 'vs/base/common/codicons';
import { ILogService } from 'vs/platform/log/common/log';
import { ReloadWindowAction } from 'vs/workbench/browser/actions/windowActions';
......@@ -33,7 +33,7 @@ import { IExtensionGalleryService } from 'vs/platform/extensionManagement/common
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { IExtensionsViewPaneContainer, LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID, VIEWLET_ID } from 'vs/workbench/contrib/extensions/common/extensions';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IMarkdownString } from 'vs/base/common/htmlContent';
import { IMarkdownString, MarkdownString } from 'vs/base/common/htmlContent';
import { RemoteNameContext, VirtualWorkspaceContext } from 'vs/workbench/browser/contextkeys';
......@@ -56,7 +56,7 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr
private readonly remoteAuthority = this.environmentService.remoteAuthority;
private virtualWorkspaceScheme: string | undefined = undefined;
private virtualWorkspaceLocation: { scheme: string; authority: string } | undefined = undefined;
private connectionState: 'initializing' | 'connected' | 'reconnecting' | 'disconnected' | undefined = undefined;
private readonly connectionStateContextKey = new RawContextKey<'' | 'initializing' | 'disconnected' | 'connected'>('remoteConnectionState', '').bindTo(this.contextKeyService);
......@@ -86,7 +86,7 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr
this.connectionState = 'initializing';
this.connectionStateContextKey.set(this.connectionState);
} else {
this.updateVirtualWorkspaceScheme();
this.updateVirtualWorkspaceLocation();
}
this.registerActions();
......@@ -206,14 +206,14 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr
}
} else {
this._register(this.workspaceContextService.onDidChangeWorkbenchState(() => {
this.updateVirtualWorkspaceScheme();
this.updateVirtualWorkspaceLocation();
this.updateRemoteStatusIndicator();
}));
}
}
private updateVirtualWorkspaceScheme() {
this.virtualWorkspaceScheme = getVirtualWorkspaceScheme(this.workspaceContextService.getWorkspace());
private updateVirtualWorkspaceLocation() {
this.virtualWorkspaceLocation = getVirtualWorkspaceLocation(this.workspaceContextService.getWorkspace());
}
private async updateWhenInstalledExtensionsRegistered(): Promise<void> {
......@@ -287,28 +287,42 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr
this.renderRemoteStatusIndicator(nls.localize('host.open', "Opening Remote..."), nls.localize('host.open', "Opening Remote..."), undefined, true /* progress */);
break;
case 'reconnecting':
this.renderRemoteStatusIndicator(`${nls.localize('host.reconnecting', "Reconnecting to {0}...", truncate(hostLabel, RemoteStatusIndicator.REMOTE_STATUS_LABEL_MAX_LENGTH))}`, nls.localize('host.tooltipReconnecting', "Reconnecting to {0}...", hostLabel), undefined, true);
this.renderRemoteStatusIndicator(`${nls.localize('host.reconnecting', "Reconnecting to {0}...", truncate(hostLabel, RemoteStatusIndicator.REMOTE_STATUS_LABEL_MAX_LENGTH))}`, undefined, undefined, true);
break;
case 'disconnected':
this.renderRemoteStatusIndicator(`$(alert) ${nls.localize('disconnectedFrom', "Disconnected from {0}", truncate(hostLabel, RemoteStatusIndicator.REMOTE_STATUS_LABEL_MAX_LENGTH))}`, nls.localize('host.tooltipDisconnected', "Disconnected from {0}", hostLabel));
this.renderRemoteStatusIndicator(`$(alert) ${nls.localize('disconnectedFrom', "Disconnected from {0}", truncate(hostLabel, RemoteStatusIndicator.REMOTE_STATUS_LABEL_MAX_LENGTH))}`);
break;
default:
this.renderRemoteStatusIndicator(`$(remote) ${truncate(hostLabel, RemoteStatusIndicator.REMOTE_STATUS_LABEL_MAX_LENGTH)}`, nls.localize('host.tooltip', "Editing on {0}", hostLabel));
const tooltip = new MarkdownString('', { isTrusted: true, supportThemeIcons: true });
const hostNameTooltip = this.labelService.getHostTooltip(Schemas.vscodeRemote, this.remoteAuthority);
if (hostNameTooltip) {
tooltip.appendMarkdown(hostNameTooltip);
} else {
tooltip.appendText(nls.localize({ key: 'host.tooltip', comment: ['{0} is a remote host name, e.g. Dev Container'] }, "Editing on {0}", hostLabel));
}
this.renderRemoteStatusIndicator(`$(remote) ${truncate(hostLabel, RemoteStatusIndicator.REMOTE_STATUS_LABEL_MAX_LENGTH)}`, tooltip);
}
return;
} else if (this.virtualWorkspaceScheme) {
} else if (this.virtualWorkspaceLocation) {
// Workspace with label: indicate editing source
const workspaceLabel = this.getWorkspaceLabel();
const workspaceLabel = this.labelService.getHostLabel(this.virtualWorkspaceLocation.scheme, this.virtualWorkspaceLocation.authority);
if (workspaceLabel) {
const toolTip: IMarkdownString = {
value: nls.localize(
{ key: 'workspace.tooltip2', comment: ['{0} is a remote location name, e.g. GitHub', '[Some features]({1}) is a link. Only translate `Some features`. Do not change brackets and parentheses or {1}'] },
"Virtual workspace on {0}\n\n[Some features]({1}) are not available for resources located on a virtual file system.",
workspaceLabel, `command:${LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID}`
),
isTrusted: true
};
this.renderRemoteStatusIndicator(`$(remote) ${truncate(workspaceLabel, RemoteStatusIndicator.REMOTE_STATUS_LABEL_MAX_LENGTH)}`, toolTip);
const tooltip = new MarkdownString('', { isTrusted: true, supportThemeIcons: true });
const hostNameTooltip = this.labelService.getHostTooltip(this.virtualWorkspaceLocation.scheme, this.virtualWorkspaceLocation.authority);
if (hostNameTooltip) {
tooltip.appendMarkdown(hostNameTooltip);
} else {
tooltip.appendText(nls.localize({ key: 'workspace.tooltip', comment: ['{0} is a remote workspace name, e.g. GitHub'] }, "Editing on {0}", workspaceLabel));
}
if (!isWeb) {
tooltip.appendMarkdown('\n\n');
tooltip.appendMarkdown(nls.localize(
{ key: 'workspace.tooltip2', comment: ['[features are not available]({1}) is a link. Only translate `features are not available`. Do not change brackets and parentheses or {0}'] },
"Some [features are not available]({0}) for resources located on a virtual file system.",
`command:${LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID}`
));
}
this.renderRemoteStatusIndicator(`$(remote) ${truncate(workspaceLabel, RemoteStatusIndicator.REMOTE_STATUS_LABEL_MAX_LENGTH)}`, tooltip);
return;
}
}
......@@ -323,15 +337,6 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr
this.remoteStatusEntry = undefined;
}
private getWorkspaceLabel() {
const workspace = this.workspaceContextService.getWorkspace();
const workspaceLocation = getVirtualWorkspaceLocation(workspace);
if (workspaceLocation) {
return this.labelService.getHostLabel(workspaceLocation.scheme, workspaceLocation.authority);
}
return undefined;
}
private renderRemoteStatusIndicator(text: string, tooltip?: string | IMarkdownString, command?: string, showProgress?: boolean): void {
const name = nls.localize('remoteHost', "Remote Host");
if (typeof command !== 'string' && this.getRemoteMenuActions().length > 0) {
......@@ -368,8 +373,8 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr
const matchCurrentRemote = () => {
if (this.remoteAuthority) {
return new RegExp(`^remote_\\d\\d_${getRemoteName(this.remoteAuthority)}_`);
} else if (this.virtualWorkspaceScheme) {
return new RegExp(`^virtualfs_\\d\\d_${this.virtualWorkspaceScheme}_`);
} else if (this.virtualWorkspaceLocation) {
return new RegExp(`^virtualfs_\\d\\d_${this.virtualWorkspaceLocation.scheme}_`);
}
return undefined;
};
......@@ -437,7 +442,7 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr
label: nls.localize('reloadWindow', 'Reload Window')
});
}
} else if (this.virtualWorkspaceScheme) {
} else if (this.virtualWorkspaceLocation) {
items.push({
type: 'item',
id: RemoteStatusIndicator.CLOSE_REMOTE_COMMAND_ID,
......@@ -446,7 +451,7 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr
}
}
if (!this.remoteAuthority && !this.virtualWorkspaceScheme && this.extensionGalleryService.isEnabled()) {
if (!this.remoteAuthority && !this.virtualWorkspaceLocation && this.extensionGalleryService.isEnabled()) {
items.push({
id: RemoteStatusIndicator.INSTALL_REMOTE_EXTENSIONS_ID,
label: nls.localize('installRemotes', "Install Additional Remote Extensions..."),
......
......@@ -670,6 +670,9 @@ class MockLabelService implements ILabelService {
getHostLabel(scheme: string, authority?: string): string {
throw new Error('Method not implemented.');
}
public getHostTooltip(): string | undefined {
throw new Error('Method not implemented.');
}
getSeparator(scheme: string, authority?: string): '/' | '\\' {
throw new Error('Method not implemented.');
}
......
......@@ -83,6 +83,10 @@ class ResourceLabelFormattersHandler implements IWorkbenchContribution {
constructor(@ILabelService labelService: ILabelService) {
resourceLabelFormattersExtPoint.setHandler((extensions, delta) => {
delta.added.forEach(added => added.value.forEach(formatter => {
if (!added.description.enableProposedApi && formatter.formatting.workspaceTooltip) {
// workspaceTooltip is only proposed
formatter.formatting.workspaceTooltip = undefined;
}
this.formattersDisposables.set(formatter, labelService.registerFormatter(formatter));
}));
delta.removed.forEach(removed => removed.value.forEach(formatter => {
......@@ -249,6 +253,11 @@ export class LabelService extends Disposable implements ILabelService {
return formatter?.workspaceSuffix || '';
}
getHostTooltip(scheme: string, authority?: string): string | undefined {
const formatter = this.findFormatting(URI.from({ scheme, authority }));
return formatter?.workspaceTooltip;
}
registerFormatter(formatter: ResourceLabelFormatter): IDisposable {
this.formatters.push(formatter);
this._onDidChangeFormatters.fire({ scheme: formatter.scheme });
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册