未验证 提交 95d85ec7 编写于 作者: S Sandeep Somavarapu 提交者: GitHub

Merge pull request #106953 from microsoft/sandy081/sync/switchService

Add selecting settings sync service in turn on flow
......@@ -114,10 +114,23 @@ export class UserDataAutoSyncService extends UserDataAutoSyncEnablementService i
) {
super(storageService, environmentService, userDataSyncStoreManagementService);
this.syncTriggerDelayer = this._register(new Delayer<void>(0));
this.lastSyncUrl = this.syncUrl;
this.syncUrl = userDataSyncStoreManagementService.userDataSyncStore?.url;
if (userDataSyncStoreManagementService.userDataSyncStore) {
if (this.syncUrl) {
this.logService.info('Using settings sync service', this.syncUrl.toString());
this._register(userDataSyncStoreManagementService.onDidChangeUserDataSyncStore(() => {
if (!isEqual(this.syncUrl, userDataSyncStoreManagementService.userDataSyncStore?.url)) {
this.lastSyncUrl = this.syncUrl;
this.syncUrl = userDataSyncStoreManagementService.userDataSyncStore?.url;
if (this.syncUrl) {
this.logService.info('Using settings sync service', this.syncUrl.toString());
}
}
}));
if (this.isEnabled()) {
this.logService.info('Auto Sync is enabled.');
} else {
......
......@@ -158,6 +158,7 @@ export type UserDataSyncStoreType = 'insiders' | 'stable';
export const IUserDataSyncStoreManagementService = createDecorator<IUserDataSyncStoreManagementService>('IUserDataSyncStoreManagementService');
export interface IUserDataSyncStoreManagementService {
readonly _serviceBrand: undefined;
readonly onDidChangeUserDataSyncStore: Event<void>;
readonly userDataSyncStore: IUserDataSyncStore | undefined;
switch(type: UserDataSyncStoreType): Promise<void>;
getPreviousUserDataSyncStore(): Promise<IUserDataSyncStore | undefined>;
......
......@@ -271,6 +271,9 @@ export class UserDataSyncStoreManagementServiceChannel implements IServerChannel
constructor(private readonly service: IUserDataSyncStoreManagementService) { }
listen(_: unknown, event: string): Event<any> {
switch (event) {
case 'onDidChangeUserDataSyncStore': return this.service.onDidChangeUserDataSyncStore;
}
throw new Error(`Event not found: ${event}`);
}
......
......@@ -36,7 +36,10 @@ export abstract class AbstractUserDataSyncStoreManagementService extends Disposa
_serviceBrand: any;
readonly userDataSyncStore: UserDataSyncStore | undefined;
private readonly _onDidChangeUserDataSyncStore = this._register(new Emitter<void>());
readonly onDidChangeUserDataSyncStore = this._onDidChangeUserDataSyncStore.event;
private _userDataSyncStore: UserDataSyncStore | undefined;
get userDataSyncStore(): UserDataSyncStore | undefined { return this._userDataSyncStore; }
constructor(
@IProductService protected readonly productService: IProductService,
......@@ -44,7 +47,12 @@ export abstract class AbstractUserDataSyncStoreManagementService extends Disposa
@IStorageService protected readonly storageService: IStorageService,
) {
super();
this.userDataSyncStore = this.toUserDataSyncStore(productService[CONFIGURATION_SYNC_STORE_KEY], configurationService.getValue<ConfigurationSyncStore>(CONFIGURATION_SYNC_STORE_KEY));
this.updateUserDataSyncStore();
}
protected updateUserDataSyncStore(): void {
this._userDataSyncStore = this.toUserDataSyncStore(this.productService[CONFIGURATION_SYNC_STORE_KEY], this.configurationService.getValue<ConfigurationSyncStore>(CONFIGURATION_SYNC_STORE_KEY));
this._onDidChangeUserDataSyncStore.fire();
}
protected toUserDataSyncStore(productStore: ConfigurationSyncStore | undefined, configuredStore?: ConfigurationSyncStore): UserDataSyncStore | undefined {
......@@ -69,7 +77,7 @@ export abstract class AbstractUserDataSyncStoreManagementService extends Disposa
defaultUrl: URI.parse(syncStore.url),
stableUrl: URI.parse(syncStore.stableUrl),
insidersUrl: URI.parse(syncStore.insidersUrl),
canSwitch: !!syncStore.canSwitch,
canSwitch: !!syncStore.canSwitch && !configuredStore?.url,
authenticationProviders: Object.keys(syncStore.authenticationProviders).reduce<IAuthenticationProvider[]>((result, id) => {
result.push({ id, scopes: syncStore!.authenticationProviders[id].scopes });
return result;
......@@ -92,7 +100,6 @@ export class UserDataSyncStoreManagementService extends AbstractUserDataSyncStor
@IProductService productService: IProductService,
@IConfigurationService configurationService: IConfigurationService,
@IStorageService storageService: IStorageService,
@IUserDataSyncLogService logService: IUserDataSyncLogService,
) {
super(productService, configurationService, storageService);
......@@ -107,10 +114,6 @@ export class UserDataSyncStoreManagementService extends AbstractUserDataSyncStor
} else {
this.storageService.remove(SYNC_PREVIOUS_STORE, StorageScope.GLOBAL);
}
if (this.userDataSyncStore) {
logService.info('Using settings sync service', this.userDataSyncStore.url.toString());
}
}
async switch(type: UserDataSyncStoreType): Promise<void> {
......@@ -120,6 +123,7 @@ export class UserDataSyncStoreManagementService extends AbstractUserDataSyncStor
} else {
this.storageService.store(SYNC_SERVICE_URL_TYPE, type, StorageScope.GLOBAL);
}
this.updateUserDataSyncStore();
}
}
......@@ -130,7 +134,7 @@ export class UserDataSyncStoreManagementService extends AbstractUserDataSyncStor
export class UserDataSyncStoreClient extends Disposable implements IUserDataSyncStoreClient {
private readonly userDataSyncStoreUrl: URI | undefined;
private userDataSyncStoreUrl: URI | undefined;
private authToken: { token: string, type: string } | undefined;
private readonly commonHeadersPromise: Promise<{ [key: string]: string; }>;
......@@ -157,7 +161,7 @@ export class UserDataSyncStoreClient extends Disposable implements IUserDataSync
@IStorageService private readonly storageService: IStorageService,
) {
super();
this.userDataSyncStoreUrl = userDataSyncStoreUrl ? joinPath(userDataSyncStoreUrl, 'v1') : undefined;
this.updateUserDataSyncStoreUrl(userDataSyncStoreUrl);
this.commonHeadersPromise = getServiceMachineId(environmentService, fileService, storageService)
.then(uuid => {
const headers: IHeaders = {
......@@ -180,6 +184,10 @@ export class UserDataSyncStoreClient extends Disposable implements IUserDataSync
this.authToken = { token, type };
}
protected updateUserDataSyncStoreUrl(userDataSyncStoreUrl: URI | undefined): void {
this.userDataSyncStoreUrl = userDataSyncStoreUrl ? joinPath(userDataSyncStoreUrl, 'v1') : undefined;
}
private initDonotMakeRequestsUntil(): void {
const donotMakeRequestsUntil = this.storageService.getNumber(DONOT_MAKE_REQUESTS_UNTIL_KEY, StorageScope.GLOBAL);
if (donotMakeRequestsUntil && Date.now() < donotMakeRequestsUntil) {
......@@ -465,6 +473,7 @@ export class UserDataSyncStoreService extends UserDataSyncStoreClient implements
@IStorageService storageService: IStorageService,
) {
super(userDataSyncStoreManagementService.userDataSyncStore?.url, productService, requestService, logService, environmentService, fileService, storageService);
this._register(userDataSyncStoreManagementService.onDidChangeUserDataSyncStore(() => this.updateUserDataSyncStoreUrl(userDataSyncStoreManagementService.userDataSyncStore?.url)));
}
}
......
......@@ -30,7 +30,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import {
IUserDataAutoSyncService, IUserDataSyncService, registerConfiguration,
SyncResource, SyncStatus, UserDataSyncError, UserDataSyncErrorCode, USER_DATA_SYNC_SCHEME, IUserDataSyncResourceEnablementService,
getSyncResourceFromLocalPreview, IResourcePreview, IUserDataSyncStoreManagementService, UserDataSyncStoreType
getSyncResourceFromLocalPreview, IResourcePreview, IUserDataSyncStoreManagementService, UserDataSyncStoreType, IUserDataSyncStore
} from 'vs/platform/userDataSync/common/userDataSync';
import { FloatingClickWidget } from 'vs/workbench/browser/parts/editor/editorWidgets';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
......@@ -54,7 +54,6 @@ import { Codicon } from 'vs/base/common/codicons';
import { ViewContainerLocation, IViewContainersRegistry, Extensions, ViewContainer } from 'vs/workbench/common/views';
import { UserDataSyncViewPaneContainer, UserDataSyncDataViews } from 'vs/workbench/contrib/userDataSync/browser/userDataSyncViews';
import { IUserDataSyncWorkbenchService, getSyncAreaLabel, AccountStatus, CONTEXT_SYNC_STATE, CONTEXT_SYNC_ENABLEMENT, CONTEXT_ACCOUNT_STATE, CONFIGURE_SYNC_COMMAND_ID, SHOW_SYNC_LOG_COMMAND_ID, SYNC_VIEW_CONTAINER_ID, SYNC_TITLE } from 'vs/workbench/services/userDataSync/common/userDataSync';
import { isNative } from 'vs/base/common/platform';
const CONTEXT_CONFLICTS_SOURCES = new RawContextKey<string>('conflictsSources', '');
......@@ -443,6 +442,9 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
if (!turnOn) {
return;
}
if (this.userDataSyncStoreManagementService.userDataSyncStore?.canSwitch) {
await this.selectSettingsSyncService(this.userDataSyncStoreManagementService.userDataSyncStore);
}
await this.userDataSyncWorkbenchService.turnOn();
this.storageService.store('sync.donotAskPreviewConfirmation', true, StorageScope.GLOBAL);
} catch (e) {
......@@ -674,52 +676,46 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
return this.outputService.showChannel(Constants.userDataSyncLogChannelId);
}
private async switchSyncService(): Promise<void> {
const userDataSyncStore = this.userDataSyncStoreManagementService.userDataSyncStore;
if (userDataSyncStore?.canSwitch && ![userDataSyncStore.insidersUrl, userDataSyncStore.stableUrl].includes(userDataSyncStore.url)) {
return new Promise<void>((c, e) => {
const disposables: DisposableStore = new DisposableStore();
const quickPick = disposables.add(this.quickInputService.createQuickPick<{ id: UserDataSyncStoreType, label: string, description?: string }>());
quickPick.title = localize('switchSyncService.title', "Select Settings Sync Service...");
quickPick.placeholder = localize('choose sync service', "Choose settings sync Service to use");
quickPick.description = isNative ?
localize('choose sync service description', "Switching settings sync service requires restarting {0}", this.productService.nameLong) :
localize('choose sync service description web', "Switching settings sync service requires reloading {0}", this.productService.nameLong);
quickPick.hideInput = true;
const getDescription = (url: URI): string | undefined => {
const isCurrent = isEqual(url, userDataSyncStore.url);
const isDefault = isEqual(url, userDataSyncStore.defaultUrl);
if (isCurrent && isDefault) {
return localize('default and current', "Default & Current");
}
if (isDefault) {
return localize('default', "Default");
}
if (isCurrent) {
return localize('current', "Current");
}
return undefined;
};
quickPick.items = [
{
id: 'insiders',
label: localize('insiders', "Insiders"),
description: getDescription(userDataSyncStore.insidersUrl!)
},
{
id: 'stable',
label: localize('stable', "Stable"),
description: getDescription(userDataSyncStore.stableUrl!)
}
];
disposables.add(quickPick.onDidAccept(() => {
this.userDataSyncWorkbenchService.switchSyncService(quickPick.selectedItems[0].id);
private async selectSettingsSyncService(userDataSyncStore: IUserDataSyncStore): Promise<void> {
return new Promise<void>((c, e) => {
const disposables: DisposableStore = new DisposableStore();
const quickPick = disposables.add(this.quickInputService.createQuickPick<{ id: UserDataSyncStoreType, label: string, description?: string }>());
quickPick.title = localize('switchSyncService.title', "{0}: Select Service", SYNC_TITLE);
quickPick.description = localize('switchSyncService.description', "Ensure you are using the same settings sync service when syncing with multiple environments");
quickPick.hideInput = true;
quickPick.ignoreFocusOut = true;
const getDescription = (url: URI): string | undefined => {
const isDefault = isEqual(url, userDataSyncStore.defaultUrl);
if (isDefault) {
return localize('default', "Default");
}
return undefined;
};
quickPick.items = [
{
id: 'insiders',
label: localize('insiders', "Insiders"),
description: getDescription(userDataSyncStore.insidersUrl)
},
{
id: 'stable',
label: localize('stable', "Stable"),
description: getDescription(userDataSyncStore.stableUrl)
}
];
disposables.add(quickPick.onDidAccept(async () => {
try {
await this.userDataSyncStoreManagementService.switch(quickPick.selectedItems[0].id);
c();
} catch (error) {
e(error);
} finally {
quickPick.hide();
}));
disposables.add(quickPick.onDidHide(() => disposables.dispose()));
quickPick.show();
});
}
}
}));
disposables.add(quickPick.onDidHide(() => disposables.dispose()));
quickPick.show();
});
}
private registerActions(): void {
......@@ -738,7 +734,6 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
this.registerSyncNowAction();
this.registerConfigureSyncAction();
this.registerShowSettingsAction();
this.registerSwitchSyncServiceAction();
this.registerShowLogAction();
}
......@@ -1117,28 +1112,6 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
}));
}
private registerSwitchSyncServiceAction(): void {
const that = this;
const userDataSyncStore = this.userDataSyncStoreManagementService.userDataSyncStore;
if (userDataSyncStore?.canSwitch && ![userDataSyncStore.insidersUrl, userDataSyncStore.stableUrl].includes(userDataSyncStore.url)) {
this._register(registerAction2(class ShowSyncSettingsAction extends Action2 {
constructor() {
super({
id: 'workbench.userDataSync.actions.switchSyncService',
title: { value: localize('workbench.userDataSync.actions.switchSyncService', "{0}: Select Service...", SYNC_TITLE), original: 'Settings Sync: Select Service...' },
menu: {
id: MenuId.CommandPalette,
when: ContextKeyExpr.and(CONTEXT_SYNC_STATE.notEqualsTo(SyncStatus.Uninitialized)),
},
});
}
run(accessor: ServicesAccessor): any {
return that.switchSyncService();
}
}));
}
}
private registerViews(): void {
const container = this.registerViewContainer();
this.registerDataViews(container);
......
......@@ -752,6 +752,8 @@ class SimpleIUserDataSyncStoreManagementService implements IUserDataSyncStoreMan
declare readonly _serviceBrand: undefined;
onDidChangeUserDataSyncStore = Event.None;
userDataSyncStore: IUserDataSyncStore | undefined = undefined;
async switch(type: UserDataSyncStoreType): Promise<void> { }
......
......@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IUserDataSyncService, IAuthenticationProvider, isAuthenticationProvider, IUserDataAutoSyncService, SyncResource, IResourcePreview, ISyncResourcePreview, Change, IManualSyncTask, IUserDataSyncStoreManagementService, UserDataSyncStoreType, SyncStatus } from 'vs/platform/userDataSync/common/userDataSync';
import { IUserDataSyncService, IAuthenticationProvider, isAuthenticationProvider, IUserDataAutoSyncService, SyncResource, IResourcePreview, ISyncResourcePreview, Change, IManualSyncTask, IUserDataSyncStoreManagementService, SyncStatus } from 'vs/platform/userDataSync/common/userDataSync';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IUserDataSyncWorkbenchService, IUserDataSyncAccount, AccountStatus, CONTEXT_SYNC_ENABLEMENT, CONTEXT_SYNC_STATE, CONTEXT_ACCOUNT_STATE, SHOW_SYNC_LOG_COMMAND_ID, getSyncAreaLabel, IUserDataSyncPreview, IUserDataSyncResource, CONTEXT_ENABLE_SYNC_MERGES_VIEW, SYNC_MERGES_VIEW_ID, CONTEXT_ENABLE_ACTIVITY_VIEWS, SYNC_VIEW_CONTAINER_ID, SYNC_TITLE } from 'vs/workbench/services/userDataSync/common/userDataSync';
......@@ -29,8 +29,6 @@ import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/
import { isEqual } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
import { IViewsService, ViewContainerLocation, IViewDescriptorService } from 'vs/workbench/common/views';
import { isNative } from 'vs/base/common/platform';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
type UserAccountClassification = {
......@@ -108,7 +106,6 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat
@IViewsService private readonly viewsService: IViewsService,
@IViewDescriptorService private readonly viewDescriptorService: IViewDescriptorService,
@IUserDataSyncStoreManagementService private readonly userDataSyncStoreManagementService: IUserDataSyncStoreManagementService,
@IHostService private readonly hostService: IHostService,
@ILifecycleService private readonly lifecycleService: ILifecycleService,
) {
super();
......@@ -444,29 +441,6 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat
await this.viewsService.openViewContainer(SYNC_VIEW_CONTAINER_ID);
}
async switchSyncService(type: UserDataSyncStoreType): Promise<void> {
if (!this.userDataSyncStoreManagementService.userDataSyncStore
|| !this.userDataSyncStoreManagementService.userDataSyncStore.canSwitch) {
return;
}
await this.userDataSyncStoreManagementService.switch(type);
const res = await this.dialogService.confirm({
type: 'info',
message: isNative ?
localize('relaunchMessage', "Switching settings sync service requires a restart to take effect.") :
localize('relaunchMessageWeb', "Switching settings sync service requires a reload to take effect."),
detail: isNative ?
localize('relaunchDetail', "Press the restart button to restart {0} and switch.", this.productService.nameLong) :
localize('relaunchDetailWeb', "Press the reload button to reload {0} and switch.", this.productService.nameLong),
primaryButton: isNative ?
localize('restart', "&&Restart") :
localize('restartWeb', "&&Reload"),
});
if (res.confirmed) {
this.hostService.restart();
}
}
private async waitForActiveSyncViews(): Promise<void> {
const viewContainer = this.viewDescriptorService.getViewContainerById(SYNC_VIEW_CONTAINER_ID);
if (viewContainer) {
......
......@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IAuthenticationProvider, SyncStatus, SyncResource, Change, MergeState, UserDataSyncStoreType } from 'vs/platform/userDataSync/common/userDataSync';
import { IAuthenticationProvider, SyncStatus, SyncResource, Change, MergeState } from 'vs/platform/userDataSync/common/userDataSync';
import { Event } from 'vs/base/common/event';
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { localize } from 'vs/nls';
......@@ -58,7 +58,6 @@ export interface IUserDataSyncWorkbenchService {
turnOn(): Promise<void>;
turnoff(everyWhere: boolean): Promise<void>;
signIn(): Promise<void>;
switchSyncService(type: UserDataSyncStoreType): Promise<void>;
resetSyncedData(): Promise<void>;
showSyncActivity(): Promise<void>;
......
......@@ -25,6 +25,7 @@ class UserDataSyncStoreManagementService extends AbstractUserDataSyncStoreManage
) {
super(productService, configurationService, storageService);
this.channel = sharedProcessService.getChannel('userDataSyncStoreManagement');
this._register(this.channel.listen('onDidChangeUserDataSyncStore')(() => this.updateUserDataSyncStore()));
}
async switch(type: UserDataSyncStoreType): Promise<void> {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册