/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { IUserDataSyncService, SyncStatus, ISynchroniser, USER_DATA_PREVIEW_SCHEME, IUserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSync'; import { Disposable } from 'vs/base/common/lifecycle'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { SettingsSynchroniser } from 'vs/workbench/services/userData/common/settingsSync'; import { Emitter, Event } from 'vs/base/common/event'; import { IFileService } from 'vs/platform/files/common/files'; import { InMemoryFileSystemProvider } from 'vs/workbench/services/userData/common/inMemoryUserDataProvider'; import { URI } from 'vs/base/common/uri'; export class UserDataSyncService extends Disposable implements IUserDataSyncService { _serviceBrand: any; private readonly synchronisers: ISynchroniser[]; private _status: SyncStatus = SyncStatus.Uninitialized; get status(): SyncStatus { return this._status; } private _onDidChangStatus: Emitter = this._register(new Emitter()); readonly onDidChangeStatus: Event = this._onDidChangStatus.event; readonly onDidChangeLocal: Event; constructor( @IFileService fileService: IFileService, @IUserDataSyncStoreService private readonly userDataSyncStoreService: IUserDataSyncStoreService, @IInstantiationService private readonly instantiationService: IInstantiationService, ) { super(); this._register(fileService.registerProvider(USER_DATA_PREVIEW_SCHEME, new InMemoryFileSystemProvider())); this.synchronisers = [ this.instantiationService.createInstance(SettingsSynchroniser) ]; this.updateStatus(); this._register(Event.any(this.userDataSyncStoreService.onDidChangeEnablement, ...this.synchronisers.map(s => Event.map(s.onDidChangeStatus, () => undefined)))(() => this.updateStatus())); this.onDidChangeLocal = Event.any(...this.synchronisers.map(s => s.onDidChangeLocal)); } get conflicts(): URI | null { const synchroniser = this.synchronisers.filter(s => s.status === SyncStatus.HasConflicts)[0]; return synchroniser ? synchroniser.conflicts : null; } async sync(): Promise { if (!this.userDataSyncStoreService.enabled) { throw new Error('Not enabled'); } for (const synchroniser of this.synchronisers) { if (!await synchroniser.sync()) { return false; } } return true; } async continueSync(): Promise { if (!this.userDataSyncStoreService.enabled) { throw new Error('Not enabled'); } for (const synchroniser of this.synchronisers) { if (await synchroniser.continueSync()) { return true; } } return false; } private updateStatus(): void { this.setStatus(this.computeStatus()); } private setStatus(status: SyncStatus): void { if (this._status !== status) { this._status = status; this._onDidChangStatus.fire(status); } } private computeStatus(): SyncStatus { if (!this.userDataSyncStoreService.enabled) { return SyncStatus.Uninitialized; } if (this.synchronisers.some(s => s.status === SyncStatus.HasConflicts)) { return SyncStatus.HasConflicts; } if (this.synchronisers.some(s => s.status === SyncStatus.Syncing)) { return SyncStatus.Syncing; } return SyncStatus.Idle; } } registerSingleton(IUserDataSyncService, UserDataSyncService);