mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-26 03:29:00 +01:00
#100346 Introduce manual sync view
This commit is contained in:
@@ -3,14 +3,14 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IUserDataSyncService, IAuthenticationProvider, getUserDataSyncStore, isAuthenticationProvider, IUserDataAutoSyncService, Change } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { IUserDataSyncService, IAuthenticationProvider, getUserDataSyncStore, isAuthenticationProvider, IUserDataAutoSyncService, SyncResource, IResourcePreview, ISyncResourcePreview, Change, IManualSyncTask } 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_SYNCED_DATA_COMMAND_ID, SHOW_SYNC_LOG_COMMAND_ID, getSyncAreaLabel } from 'vs/workbench/services/userDataSync/common/userDataSync';
|
||||
import { IUserDataSyncWorkbenchService, IUserDataSyncAccount, AccountStatus, CONTEXT_SYNC_ENABLEMENT, CONTEXT_SYNC_STATE, CONTEXT_ACCOUNT_STATE, SHOW_SYNC_LOG_COMMAND_ID, getSyncAreaLabel, IUserDataSyncPreview, IUserDataSyncResourceGroup, CONTEXT_SHOW_MANUAL_SYNC_VIEW, SHOW_SYNCED_DATA_COMMAND_ID, MANUAL_SYNC_VIEW_ID } from 'vs/workbench/services/userDataSync/common/userDataSync';
|
||||
import { AuthenticationSession, AuthenticationSessionsChangeEvent } from 'vs/editor/common/modes';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { flatten } from 'vs/base/common/arrays';
|
||||
import { flatten, equals } from 'vs/base/common/arrays';
|
||||
import { IAuthenticationService } from 'vs/workbench/services/authentication/browser/authenticationService';
|
||||
import { IUserDataSyncAccountService } from 'vs/platform/userDataSync/common/userDataSyncAccount';
|
||||
import { IQuickInputService, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
|
||||
@@ -21,13 +21,17 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { localize } from 'vs/nls';
|
||||
import { canceled, isPromiseCanceledError } from 'vs/base/common/errors';
|
||||
import { canceled } from 'vs/base/common/errors';
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { IProgressService, ProgressLocation, IProgressStep, IProgress } from 'vs/platform/progress/common/progress';
|
||||
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
|
||||
import { isEqual } from 'vs/base/common/resources';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IViewsService, ViewContainerLocation, IViewDescriptorService } from 'vs/workbench/common/views';
|
||||
import { IDecorationsProvider, IDecorationData, IDecorationsService } from 'vs/workbench/services/decorations/browser/decorations';
|
||||
|
||||
type UserAccountClassification = {
|
||||
id: { classification: 'EndUserPseudonymizedInformation', purpose: 'BusinessInsight' };
|
||||
@@ -41,6 +45,8 @@ type UserAccountEvent = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
type FirstTimeSyncAction = 'pull' | 'push' | 'merge' | 'manual';
|
||||
|
||||
type AccountQuickPickItem = { label: string, authenticationProvider: IAuthenticationProvider, account?: UserDataSyncAccount, description?: string };
|
||||
|
||||
class UserDataSyncAccount implements IUserDataSyncAccount {
|
||||
@@ -75,6 +81,9 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat
|
||||
private readonly syncEnablementContext: IContextKey<boolean>;
|
||||
private readonly syncStatusContext: IContextKey<string>;
|
||||
private readonly accountStatusContext: IContextKey<string>;
|
||||
private readonly showManualSyncViewContext: IContextKey<boolean>;
|
||||
|
||||
readonly userDataSyncPreview: UserDataSyncPreview = this._register(new UserDataSyncPreview(this.userDataSyncService));
|
||||
|
||||
constructor(
|
||||
@IUserDataSyncService private readonly userDataSyncService: IUserDataSyncService,
|
||||
@@ -94,12 +103,18 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat
|
||||
@IDialogService private readonly dialogService: IDialogService,
|
||||
@ICommandService private readonly commandService: ICommandService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IViewsService private readonly viewsService: IViewsService,
|
||||
@IViewDescriptorService private readonly viewDescriptorService: IViewDescriptorService,
|
||||
@IDecorationsService decorationsService: IDecorationsService,
|
||||
) {
|
||||
super();
|
||||
this.authenticationProviders = getUserDataSyncStore(productService, configurationService)?.authenticationProviders || [];
|
||||
this.syncEnablementContext = CONTEXT_SYNC_ENABLEMENT.bindTo(contextKeyService);
|
||||
this.syncStatusContext = CONTEXT_SYNC_STATE.bindTo(contextKeyService);
|
||||
this.accountStatusContext = CONTEXT_ACCOUNT_STATE.bindTo(contextKeyService);
|
||||
this.showManualSyncViewContext = CONTEXT_SHOW_MANUAL_SYNC_VIEW.bindTo(contextKeyService);
|
||||
|
||||
decorationsService.registerDecorationsProvider(this.userDataSyncPreview);
|
||||
|
||||
if (this.authenticationProviders.length) {
|
||||
|
||||
@@ -222,12 +237,8 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat
|
||||
|
||||
const preferencesSyncTitle = localize('preferences sync', "Preferences Sync");
|
||||
const title = `${preferencesSyncTitle} [(${localize('details', "details")})](command:${SHOW_SYNC_LOG_COMMAND_ID})`;
|
||||
await this.progressService.withProgress({
|
||||
location: ProgressLocation.Notification,
|
||||
title,
|
||||
delay: 500,
|
||||
}, (progress) => this.turnOnWithProgress(progress));
|
||||
|
||||
await this.syncBeforeTurningOn(title);
|
||||
await this.userDataAutoSyncService.turnOn();
|
||||
this.notificationService.info(localize('sync turned on', "{0} is turned on", title));
|
||||
}
|
||||
|
||||
@@ -235,53 +246,69 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat
|
||||
return this.userDataAutoSyncService.turnOff(everywhere);
|
||||
}
|
||||
|
||||
private async turnOnWithProgress(progress: IProgress<IProgressStep>): Promise<void> {
|
||||
progress.report({ message: localize('turning on', "Turning on...") });
|
||||
private async syncBeforeTurningOn(title: string): Promise<void> {
|
||||
|
||||
/* Make sure sync started on clean local state */
|
||||
await this.userDataSyncService.resetLocal();
|
||||
|
||||
const manualSyncTask = await this.userDataSyncService.createManualSyncTask();
|
||||
const preview = await manualSyncTask.preview();
|
||||
|
||||
const hasRemoteData = manualSyncTask.manifest !== null;
|
||||
const hasLocalData = await this.userDataSyncService.hasLocalData();
|
||||
const isLastSyncFromCurrentMachine = preview.every(([, { isLastSyncFromCurrentMachine }]) => isLastSyncFromCurrentMachine);
|
||||
const hasChanges = preview.some(([, { resourcePreviews }]) => resourcePreviews.some(r => r.localChange !== Change.None || r.remoteChange !== Change.None));
|
||||
|
||||
const progressDisposable = manualSyncTask.onSynchronizeResources(synchronizingResources =>
|
||||
synchronizingResources.length ? progress.report({ message: localize('syncing resource', "Syncing {0}...", getSyncAreaLabel(synchronizingResources[0][0])) }) : undefined);
|
||||
|
||||
try {
|
||||
if (!hasLocalData /* no data on local */
|
||||
|| !hasRemoteData /* no data on remote */
|
||||
|| !hasChanges /* no changes */
|
||||
|| isLastSyncFromCurrentMachine /* has changes but last sync is from current machine */
|
||||
) {
|
||||
await manualSyncTask.merge();
|
||||
} else {
|
||||
const pull = await this.askForPullOrMerge();
|
||||
if (pull) {
|
||||
await manualSyncTask.pull();
|
||||
} else {
|
||||
await manualSyncTask.merge();
|
||||
let action: FirstTimeSyncAction = 'manual';
|
||||
let preview: [SyncResource, ISyncResourcePreview][] = [];
|
||||
|
||||
await this.progressService.withProgress({
|
||||
location: ProgressLocation.Notification,
|
||||
title,
|
||||
delay: 500,
|
||||
}, async progress => {
|
||||
progress.report({ message: localize('turning on', "Turning on...") });
|
||||
|
||||
preview = await manualSyncTask.preview();
|
||||
const hasRemoteData = manualSyncTask.manifest !== null;
|
||||
const hasLocalData = await this.userDataSyncService.hasLocalData();
|
||||
const hasChanges = preview.some(([, { resourcePreviews }]) => resourcePreviews.some(r => r.localChange !== Change.None || r.remoteChange !== Change.None));
|
||||
const isLastSyncFromCurrentMachine = preview.every(([, { isLastSyncFromCurrentMachine }]) => isLastSyncFromCurrentMachine);
|
||||
|
||||
action = await this.getFirstTimeSyncAction(hasRemoteData, hasLocalData, hasChanges, isLastSyncFromCurrentMachine);
|
||||
const progressDisposable = manualSyncTask.onSynchronizeResources(synchronizingResources =>
|
||||
synchronizingResources.length ? progress.report({ message: localize('syncing resource', "Syncing {0}...", getSyncAreaLabel(synchronizingResources[0][0])) }) : undefined);
|
||||
try {
|
||||
switch (action) {
|
||||
case 'merge': return await manualSyncTask.merge();
|
||||
case 'pull': return await manualSyncTask.pull();
|
||||
case 'push': return await manualSyncTask.push();
|
||||
case 'manual': return;
|
||||
}
|
||||
} finally {
|
||||
progressDisposable.dispose();
|
||||
}
|
||||
});
|
||||
if (action === 'manual') {
|
||||
await this.syncManually(manualSyncTask, preview);
|
||||
}
|
||||
await this.userDataAutoSyncService.turnOn();
|
||||
} catch (error) {
|
||||
if (isPromiseCanceledError(error)) {
|
||||
await manualSyncTask.stop();
|
||||
}
|
||||
await manualSyncTask.stop();
|
||||
throw error;
|
||||
} finally {
|
||||
manualSyncTask.dispose();
|
||||
progressDisposable.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private async askForPullOrMerge(): Promise<boolean> {
|
||||
private async getFirstTimeSyncAction(hasRemoteData: boolean, hasLocalData: boolean, hasChanges: boolean, isLastSyncFromCurrentMachine: boolean): Promise<FirstTimeSyncAction> {
|
||||
|
||||
if (!hasLocalData /* no data on local */
|
||||
|| !hasRemoteData /* no data on remote */
|
||||
|| !hasChanges /* no changes */
|
||||
|| isLastSyncFromCurrentMachine /* has changes but last sync is from current machine */
|
||||
) {
|
||||
return 'merge';
|
||||
}
|
||||
|
||||
const result = await this.dialogService.show(
|
||||
Severity.Info,
|
||||
localize('Replace or Merge', "Replace or Merge"),
|
||||
[
|
||||
localize('show synced data', "Show Synced Data"),
|
||||
localize('sync manually', "Sync Manually"),
|
||||
localize('merge', "Merge"),
|
||||
localize('replace local', "Replace Local"),
|
||||
localize('cancel', "Cancel"),
|
||||
@@ -293,20 +320,41 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat
|
||||
);
|
||||
switch (result.choice) {
|
||||
case 0:
|
||||
this.telemetryService.publicLog2<{ action: string }, FirstTimeSyncClassification>('sync/firstTimeSync', { action: 'showSyncedData' });
|
||||
await this.commandService.executeCommand(SHOW_SYNCED_DATA_COMMAND_ID);
|
||||
throw canceled();
|
||||
this.telemetryService.publicLog2<{ action: string }, FirstTimeSyncClassification>('sync/firstTimeSync', { action: 'manual' });
|
||||
return 'manual';
|
||||
case 1:
|
||||
this.telemetryService.publicLog2<{ action: string }, FirstTimeSyncClassification>('sync/firstTimeSync', { action: 'merge' });
|
||||
return false;
|
||||
return 'merge';
|
||||
case 2:
|
||||
this.telemetryService.publicLog2<{ action: string }, FirstTimeSyncClassification>('sync/firstTimeSync', { action: 'replace-local' });
|
||||
return true;
|
||||
case 3:
|
||||
this.telemetryService.publicLog2<{ action: string }, FirstTimeSyncClassification>('sync/firstTimeSync', { action: 'cancelled' });
|
||||
throw canceled();
|
||||
this.telemetryService.publicLog2<{ action: string }, FirstTimeSyncClassification>('sync/firstTimeSync', { action: 'pull' });
|
||||
return 'pull';
|
||||
}
|
||||
this.telemetryService.publicLog2<{ action: string }, FirstTimeSyncClassification>('sync/firstTimeSync', { action: 'cancelled' });
|
||||
throw canceled();
|
||||
}
|
||||
|
||||
private async syncManually(task: IManualSyncTask, preview: [SyncResource, ISyncResourcePreview][]): Promise<void> {
|
||||
const visibleViewContainer = this.viewsService.getVisibleViewContainer(ViewContainerLocation.Sidebar);
|
||||
this.userDataSyncPreview.setManualSyncPreview(task, preview);
|
||||
|
||||
this.showManualSyncViewContext.set(true);
|
||||
await this.commandService.executeCommand(SHOW_SYNCED_DATA_COMMAND_ID);
|
||||
await this.viewsService.openView(MANUAL_SYNC_VIEW_ID);
|
||||
|
||||
await Event.toPromise(Event.filter(this.userDataSyncPreview.onDidChangeChanges, e => e.length === 0));
|
||||
if (this.userDataSyncPreview.conflicts.length) {
|
||||
await Event.toPromise(Event.filter(this.userDataSyncPreview.onDidChangeConflicts, e => e.length === 0));
|
||||
}
|
||||
|
||||
/* Merge to sync globalState changes */
|
||||
await task.merge();
|
||||
|
||||
if (visibleViewContainer) {
|
||||
this.viewsService.openViewContainer(visibleViewContainer.id);
|
||||
} else {
|
||||
const viewContainer = this.viewDescriptorService.getViewContainerByViewId(MANUAL_SYNC_VIEW_ID);
|
||||
this.viewsService.closeViewContainer(viewContainer!.id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private isSupportedAuthenticationProviderId(authenticationProviderId: string): boolean {
|
||||
@@ -483,4 +531,137 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat
|
||||
|
||||
}
|
||||
|
||||
class UserDataSyncPreview extends Disposable implements IUserDataSyncPreview, IDecorationsProvider {
|
||||
|
||||
readonly label: string = localize('label', "UserDataSyncResources");
|
||||
|
||||
private readonly _onDidChange = this._register(new Emitter<URI[]>());
|
||||
readonly onDidChange = this._onDidChange.event;
|
||||
|
||||
private _onDidChangeChanges = this._register(new Emitter<ReadonlyArray<IUserDataSyncResourceGroup>>());
|
||||
readonly onDidChangeChanges = this._onDidChangeChanges.event;
|
||||
|
||||
private _onDidChangeConflicts = this._register(new Emitter<ReadonlyArray<IUserDataSyncResourceGroup>>());
|
||||
readonly onDidChangeConflicts = this._onDidChangeConflicts.event;
|
||||
|
||||
private _changes: ReadonlyArray<IUserDataSyncResourceGroup> = [];
|
||||
get changes() { return Object.freeze(this._changes); }
|
||||
|
||||
private _conflicts: ReadonlyArray<IUserDataSyncResourceGroup> = [];
|
||||
get conflicts() { return Object.freeze(this._conflicts); }
|
||||
|
||||
private manualSync: { preview: [SyncResource, ISyncResourcePreview][], task: IManualSyncTask } | undefined;
|
||||
|
||||
constructor(
|
||||
private readonly userDataSyncService: IUserDataSyncService
|
||||
) {
|
||||
super();
|
||||
this.updateConflicts(userDataSyncService.conflicts);
|
||||
this._register(userDataSyncService.onDidChangeConflicts(conflicts => this.updateConflicts(conflicts)));
|
||||
}
|
||||
|
||||
setManualSyncPreview(task: IManualSyncTask, preview: [SyncResource, ISyncResourcePreview][]): void {
|
||||
this.manualSync = { task, preview };
|
||||
this.updateChanges();
|
||||
}
|
||||
|
||||
async accept(syncResource: SyncResource, resource: URI, content: string): Promise<void> {
|
||||
if (this.manualSync) {
|
||||
const syncPreview = await this.manualSync.task.accept(resource, content);
|
||||
this.updatePreview(syncPreview);
|
||||
} else {
|
||||
await this.userDataSyncService.acceptPreviewContent(syncResource, resource, content);
|
||||
}
|
||||
}
|
||||
|
||||
async merge(resource?: URI): Promise<void> {
|
||||
if (!this.manualSync) {
|
||||
throw new Error('Can merge only while syncing manually');
|
||||
}
|
||||
const syncPreview = await this.manualSync.task.merge(resource);
|
||||
this.updatePreview(syncPreview);
|
||||
}
|
||||
|
||||
async pull(): Promise<void> {
|
||||
if (!this.manualSync) {
|
||||
throw new Error('Can pull only while syncing manually');
|
||||
}
|
||||
await this.manualSync.task.pull();
|
||||
this.updatePreview([]);
|
||||
}
|
||||
|
||||
async push(): Promise<void> {
|
||||
if (!this.manualSync) {
|
||||
throw new Error('Can push only while syncing manually');
|
||||
}
|
||||
await this.manualSync.task.push();
|
||||
this.updatePreview([]);
|
||||
}
|
||||
|
||||
provideDecorations(resource: URI): IDecorationData | undefined {
|
||||
const changeResource = this.changes.find(c => isEqual(c.remote, resource)) || this.conflicts.find(c => isEqual(c.remote, resource));
|
||||
if (changeResource) {
|
||||
if (changeResource.localChange === Change.Modified || changeResource.remoteChange === Change.Modified) {
|
||||
return {
|
||||
letter: 'M',
|
||||
};
|
||||
}
|
||||
if (changeResource.localChange === Change.Added
|
||||
|| changeResource.localChange === Change.Deleted
|
||||
|| changeResource.remoteChange === Change.Added
|
||||
|| changeResource.remoteChange === Change.Deleted) {
|
||||
return {
|
||||
letter: 'A',
|
||||
};
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private updatePreview(preview: [SyncResource, ISyncResourcePreview][]) {
|
||||
if (this.manualSync) {
|
||||
this.manualSync.preview = preview;
|
||||
this.updateChanges();
|
||||
}
|
||||
}
|
||||
|
||||
private updateConflicts(conflicts: [SyncResource, IResourcePreview[]][]): void {
|
||||
const newConflicts = this.toUserDataSyncResourceGroups(conflicts);
|
||||
if (!equals(newConflicts, this._conflicts, (a, b) => isEqual(a.local, b.local))) {
|
||||
this._conflicts = newConflicts;
|
||||
this._onDidChangeConflicts.fire(this.conflicts);
|
||||
}
|
||||
this.updateChanges();
|
||||
}
|
||||
|
||||
private updateChanges(): void {
|
||||
const newChanges = this.toUserDataSyncResourceGroups(
|
||||
(this.manualSync?.preview || [])
|
||||
.filter(([syncResource]) => syncResource !== SyncResource.GlobalState) /* Filter Global State Changes */
|
||||
.map(([syncResource, syncResourcePreview]) =>
|
||||
([
|
||||
syncResource,
|
||||
/* remove merged previews and conflicts and with no changes and conflicts */
|
||||
syncResourcePreview.resourcePreviews.filter(r =>
|
||||
!r.merged
|
||||
&& (r.localChange !== Change.None || r.remoteChange !== Change.None)
|
||||
&& !this._conflicts.some(c => c.syncResource === syncResource && isEqual(c.local, r.localResource)))
|
||||
]))
|
||||
);
|
||||
if (!equals(newChanges, this._changes, (a, b) => isEqual(a.local, b.local))) {
|
||||
this._changes = newChanges;
|
||||
this._onDidChangeChanges.fire(this.changes);
|
||||
}
|
||||
}
|
||||
|
||||
private toUserDataSyncResourceGroups(syncResourcePreviews: [SyncResource, IResourcePreview[]][]): IUserDataSyncResourceGroup[] {
|
||||
return flatten(
|
||||
syncResourcePreviews.map(([syncResource, resourcePreviews]) =>
|
||||
resourcePreviews.map<IUserDataSyncResourceGroup>(({ localResource, remoteResource, previewResource, localChange, remoteChange }) =>
|
||||
({ syncResource, local: localResource, remote: remoteResource, preview: previewResource, localChange, remoteChange })))
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
registerSingleton(IUserDataSyncWorkbenchService, UserDataSyncWorkbenchService);
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IAuthenticationProvider, SyncStatus, SyncResource } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { IAuthenticationProvider, SyncStatus, SyncResource, Change } 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';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
||||
export interface IUserDataSyncAccount {
|
||||
readonly authenticationProviderId: string;
|
||||
@@ -15,6 +16,28 @@ export interface IUserDataSyncAccount {
|
||||
readonly accountId: string;
|
||||
}
|
||||
|
||||
export interface IUserDataSyncPreview {
|
||||
readonly onDidChangeChanges: Event<ReadonlyArray<IUserDataSyncResourceGroup>>;
|
||||
readonly changes: ReadonlyArray<IUserDataSyncResourceGroup>;
|
||||
|
||||
onDidChangeConflicts: Event<ReadonlyArray<IUserDataSyncResourceGroup>>;
|
||||
readonly conflicts: ReadonlyArray<IUserDataSyncResourceGroup>;
|
||||
|
||||
accept(syncResource: SyncResource, resource: URI, content: string): Promise<void>;
|
||||
merge(resource?: URI): Promise<void>;
|
||||
pull(): Promise<void>;
|
||||
push(): Promise<void>;
|
||||
}
|
||||
|
||||
export interface IUserDataSyncResourceGroup {
|
||||
readonly syncResource: SyncResource;
|
||||
readonly local: URI;
|
||||
readonly remote: URI;
|
||||
readonly preview: URI;
|
||||
readonly localChange: Change;
|
||||
readonly remoteChange: Change;
|
||||
}
|
||||
|
||||
export const IUserDataSyncWorkbenchService = createDecorator<IUserDataSyncWorkbenchService>('IUserDataSyncWorkbenchService');
|
||||
export interface IUserDataSyncWorkbenchService {
|
||||
_serviceBrand: any;
|
||||
@@ -26,6 +49,8 @@ export interface IUserDataSyncWorkbenchService {
|
||||
readonly accountStatus: AccountStatus;
|
||||
readonly onDidChangeAccountStatus: Event<AccountStatus>;
|
||||
|
||||
readonly userDataSyncPreview: IUserDataSyncPreview;
|
||||
|
||||
turnOn(): Promise<void>;
|
||||
turnoff(everyWhere: boolean): Promise<void>;
|
||||
signIn(): Promise<void>;
|
||||
@@ -52,9 +77,12 @@ export const CONTEXT_SYNC_STATE = new RawContextKey<string>('syncStatus', SyncSt
|
||||
export const CONTEXT_SYNC_ENABLEMENT = new RawContextKey<boolean>('syncEnabled', false);
|
||||
export const CONTEXT_ACCOUNT_STATE = new RawContextKey<string>('userDataSyncAccountStatus', AccountStatus.Uninitialized);
|
||||
export const CONTEXT_ENABLE_VIEWS = new RawContextKey<boolean>(`showUserDataSyncViews`, false);
|
||||
export const CONTEXT_SHOW_MANUAL_SYNC_VIEW = new RawContextKey<boolean>(`showManualSyncView`, false);
|
||||
|
||||
// Commands
|
||||
export const ENABLE_SYNC_VIEWS_COMMAND_ID = 'workbench.userDataSync.actions.enableViews';
|
||||
export const CONFIGURE_SYNC_COMMAND_ID = 'workbench.userDataSync.actions.configure';
|
||||
export const SHOW_SYNC_LOG_COMMAND_ID = 'workbench.userDataSync.actions.showLog';
|
||||
export const SHOW_SYNCED_DATA_COMMAND_ID = 'workbench.userDataSync.actions.showSyncedData';
|
||||
|
||||
// VIEWS
|
||||
export const MANUAL_SYNC_VIEW_ID = 'workbench.views.manualSyncView';
|
||||
|
||||
Reference in New Issue
Block a user