mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-10 16:58:55 -05:00
recommend remote extension (#167419)
* recommend remote extension * some fixes
This commit is contained in:
committed by
GitHub
parent
a127b73dae
commit
08c4ffadd6
@@ -25,6 +25,8 @@ export interface IRemoteTunnelService {
|
||||
readonly onDidChangeAccount: Event<IRemoteTunnelAccount | undefined>;
|
||||
updateAccount(account: IRemoteTunnelAccount | undefined): Promise<TunnelStatus>;
|
||||
|
||||
getHostName(): Promise<string | undefined>;
|
||||
|
||||
}
|
||||
|
||||
export type TunnelStatus = TunnelStates.Connected | TunnelStates.Disconnected | TunnelStates.Connecting | TunnelStates.Uninitialized;
|
||||
|
||||
@@ -171,7 +171,7 @@ export class RemoteTunnelService extends Disposable implements IRemoteTunnelServ
|
||||
return;
|
||||
}
|
||||
|
||||
const hostName = this.getHostName();
|
||||
const hostName = this._getHostName();
|
||||
if (hostName) {
|
||||
this.setTunnelStatus(TunnelStates.connecting(localize({ key: 'remoteTunnelService.openTunnelWithName', comment: ['{0} is a host name'] }, 'Opening tunnel for {0}', hostName)));
|
||||
} else {
|
||||
@@ -279,7 +279,11 @@ export class RemoteTunnelService extends Disposable implements IRemoteTunnelServ
|
||||
});
|
||||
}
|
||||
|
||||
private getHostName() {
|
||||
public async getHostName(): Promise<string | undefined> {
|
||||
return this._getHostName();
|
||||
}
|
||||
|
||||
private _getHostName(): string | undefined {
|
||||
let name = this.configurationService.getValue<string>(CONFIGURATION_KEY_HOST_NAME) || hostname();
|
||||
name = name.replace(/[^\w-]/g, '').substring(0, 20);
|
||||
return name || undefined;
|
||||
|
||||
@@ -51,6 +51,9 @@ export const REMOTE_TUNNEL_CONNECTION_STATE = new RawContextKey<CONTEXT_KEY_STAT
|
||||
|
||||
const SESSION_ID_STORAGE_KEY = 'remoteTunnelAccountPreference';
|
||||
|
||||
const REMOTE_TUNNEL_USED_STORAGE_KEY = 'remoteTunnelServiceUsed';
|
||||
const REMOTE_TUNNEL_EXTENSION_RECOMMENDED_KEY = 'remoteTunnelExtensionRecommended';
|
||||
|
||||
type ExistingSessionItem = { session: AuthenticationSession; providerId: string; label: string; description: string };
|
||||
type IAuthenticationProvider = { id: string; scopes: string[] };
|
||||
type AuthenticationProviderOption = IQuickPickItem & { provider: IAuthenticationProvider };
|
||||
@@ -103,6 +106,7 @@ export class RemoteTunnelWorkbenchContribution extends Disposable implements IWo
|
||||
@ICommandService private commandService: ICommandService,
|
||||
@IWorkspaceContextService private workspaceContextService: IWorkspaceContextService,
|
||||
@IProgressService private progressService: IProgressService,
|
||||
@INotificationService private notificationService: INotificationService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -148,6 +152,8 @@ export class RemoteTunnelWorkbenchContribution extends Disposable implements IWo
|
||||
registerLogChannel(LOG_CHANNEL_ID, localize('remoteTunnelLog', "Remote Tunnel Service"), remoteTunnelServiceLogResource, fileService, logService);
|
||||
|
||||
this.initialize();
|
||||
|
||||
this.recommendRemoteExtensionIfNeeded();
|
||||
}
|
||||
|
||||
private get existingSessionId() {
|
||||
@@ -163,6 +169,68 @@ export class RemoteTunnelWorkbenchContribution extends Disposable implements IWo
|
||||
}
|
||||
}
|
||||
|
||||
private async recommendRemoteExtensionIfNeeded() {
|
||||
const remoteExtension = this.serverConfiguration.extension;
|
||||
const shouldRecommend = async () => {
|
||||
if (this.storageService.getBoolean(REMOTE_TUNNEL_EXTENSION_RECOMMENDED_KEY, StorageScope.APPLICATION)) {
|
||||
return false;
|
||||
}
|
||||
if (await this.extensionService.getExtension(remoteExtension.extensionId)) {
|
||||
return false;
|
||||
}
|
||||
const usedOnHost = this.storageService.get(REMOTE_TUNNEL_USED_STORAGE_KEY, StorageScope.APPLICATION);
|
||||
if (!usedOnHost) {
|
||||
return false;
|
||||
}
|
||||
const currentHostName = await this.remoteTunnelService.getHostName();
|
||||
if (!currentHostName || currentHostName === usedOnHost) {
|
||||
return false;
|
||||
}
|
||||
return usedOnHost;
|
||||
};
|
||||
const recommed = async () => {
|
||||
const usedOnHost = await shouldRecommend();
|
||||
if (!usedOnHost) {
|
||||
return false;
|
||||
}
|
||||
this.notificationService.notify({
|
||||
severity: Severity.Info,
|
||||
message:
|
||||
localize(
|
||||
{
|
||||
key: 'recommend.remoteExtension',
|
||||
comment: ['{0} will be a host name, {1} will the link address to the web UI, {6} an extension name. [label](command:commandId) is a markdown link. Only translate the label, do not modify the format']
|
||||
},
|
||||
"'{0}' has turned on remote access. The {1} extension can be used to connect to it.",
|
||||
usedOnHost, remoteExtension.friendlyName
|
||||
),
|
||||
actions: {
|
||||
primary: [
|
||||
new Action('showExtension', localize('action.showExtension', "Show Extension"), undefined, true, () => {
|
||||
return this.commandService.executeCommand('workbench.extensions.action.showExtensionsWithIds', [remoteExtension.extensionId]);
|
||||
}),
|
||||
new Action('doNotShowAgain', localize('action.doNotShowAgain', "Do not show again"), undefined, true, () => {
|
||||
this.storageService.store(REMOTE_TUNNEL_EXTENSION_RECOMMENDED_KEY, true, StorageScope.APPLICATION, StorageTarget.USER);
|
||||
}),
|
||||
]
|
||||
}
|
||||
});
|
||||
return true;
|
||||
};
|
||||
if (await shouldRecommend()) {
|
||||
const storageListener = this.storageService.onDidChangeValue(async e => {
|
||||
if (e.key === REMOTE_TUNNEL_USED_STORAGE_KEY) {
|
||||
const success = await recommed();
|
||||
if (success) {
|
||||
storageListener.dispose();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async initialize(): Promise<void> {
|
||||
const status = await this.remoteTunnelService.getTunnelStatus();
|
||||
if (status.type === 'connected') {
|
||||
@@ -418,6 +486,7 @@ export class RemoteTunnelWorkbenchContribution extends Disposable implements IWo
|
||||
const notificationService = accessor.get(INotificationService);
|
||||
const clipboardService = accessor.get(IClipboardService);
|
||||
const commandService = accessor.get(ICommandService);
|
||||
const storageService = accessor.get(IStorageService);
|
||||
|
||||
const connectionInfo = await that.startTunnel(false);
|
||||
if (connectionInfo) {
|
||||
@@ -443,6 +512,7 @@ export class RemoteTunnelWorkbenchContribution extends Disposable implements IWo
|
||||
]
|
||||
}
|
||||
});
|
||||
storageService.store(REMOTE_TUNNEL_USED_STORAGE_KEY, connectionInfo.hostName, StorageScope.APPLICATION, StorageTarget.USER);
|
||||
} else {
|
||||
await notificationService.notify({
|
||||
severity: Severity.Info,
|
||||
@@ -667,7 +737,7 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).regis
|
||||
[CONFIGURATION_KEY_HOST_NAME]: {
|
||||
description: localize('remoteTunnelAccess.machineName', "The name under which the remote tunnel access is registered. If not set, the host name is used."),
|
||||
type: 'string',
|
||||
scope: ConfigurationScope.APPLICATION,
|
||||
scope: ConfigurationScope.MACHINE,
|
||||
pattern: '^[\\w-]*$',
|
||||
patternErrorMessage: localize('remoteTunnelAccess.machineNameRegex', "The name can only consist of letters, numbers, underscore and minus."),
|
||||
maxLength: 20,
|
||||
|
||||
Reference in New Issue
Block a user