Merge from vscode 2cd495805cf99b31b6926f08ff4348124b2cf73d

This commit is contained in:
ADS Merger
2020-06-30 04:40:21 +00:00
committed by AzureDataStudio
parent a8a7559229
commit 1388493cc1
602 changed files with 16375 additions and 12940 deletions

View File

@@ -53,7 +53,7 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
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, CONTEXT_ENABLE_VIEWS, getSyncAreaLabel, AccountStatus, CONTEXT_SYNC_STATE, CONTEXT_SYNC_ENABLEMENT, CONTEXT_ACCOUNT_STATE, CONFIGURE_SYNC_COMMAND_ID, ENABLE_SYNC_VIEWS_COMMAND_ID, SHOW_SYNC_LOG_COMMAND_ID } from 'vs/workbench/services/userDataSync/common/userDataSync';
import { IUserDataSyncWorkbenchService, CONTEXT_ENABLE_VIEWS, getSyncAreaLabel, AccountStatus, CONTEXT_SYNC_STATE, CONTEXT_SYNC_ENABLEMENT, CONTEXT_ACCOUNT_STATE, CONFIGURE_SYNC_COMMAND_ID, ENABLE_SYNC_VIEWS_COMMAND_ID, SHOW_SYNC_LOG_COMMAND_ID, SHOW_SYNCED_DATA_COMMAND_ID } from 'vs/workbench/services/userDataSync/common/userDataSync';
const CONTEXT_CONFLICTS_SOURCES = new RawContextKey<string>('conflictsSources', '');
@@ -143,6 +143,8 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
this._register(userDataSyncService.onDidChangeConflicts(() => this.onDidChangeConflicts(this.userDataSyncService.conflicts)));
this._register(userDataSyncService.onSyncErrors(errors => this.onSynchronizerErrors(errors)));
this._register(userDataAutoSyncService.onError(error => this.onAutoSyncError(error)));
this._register(userDataAutoSyncService.onTurnOnSync(() => this.turningOnSync = true));
this._register(userDataAutoSyncService.onDidTurnOnSync(() => this.turningOnSync = false));
this.registerActions();
this.registerViews();
@@ -176,7 +178,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
// close stale conflicts editor previews
if (conflictsEditorInputs.length) {
conflictsEditorInputs.forEach(input => {
if (!conflicts.some(({ local }) => isEqual(local, input.master.resource))) {
if (!conflicts.some(({ local }) => isEqual(local, input.primary.resource))) {
input.dispose();
}
});
@@ -338,7 +340,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
return;
}
const resource = source === SyncResource.Settings ? this.workbenchEnvironmentService.settingsResource : this.workbenchEnvironmentService.keybindingsResource;
if (isEqual(resource, toResource(this.editorService.activeEditor, { supportSideBySide: SideBySideEditor.MASTER }))) {
if (isEqual(resource, toResource(this.editorService.activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY }))) {
// Do not show notification if the file in error is active
return;
}
@@ -402,7 +404,6 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
}
private async turnOn(): Promise<void> {
this.turningOnSync = true;
try {
if (!this.storageService.getBoolean('sync.donotAskPreviewConfirmation', StorageScope.GLOBAL, false)) {
if (!await this.askForConfirmation()) {
@@ -438,8 +439,6 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
}
}
this.notificationService.error(localize('turn on failed', "Error while starting Sync: {0}", toErrorMessage(e)));
} finally {
this.turningOnSync = false;
}
}
@@ -570,9 +569,9 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
message: localize('turn off sync confirmation', "Do you want to turn off sync?"),
detail: localize('turn off sync detail', "Your settings, keybindings, extensions and UI State will no longer be synced."),
primaryButton: localize('turn off', "Turn Off"),
checkbox: {
checkbox: this.userDataSyncWorkbenchService.accountStatus === AccountStatus.Available ? {
label: localize('turn off sync everywhere', "Turn off sync on all your devices and clear the data from the cloud.")
}
} : undefined
});
if (result.confirmed) {
return this.userDataSyncWorkbenchService.turnoff(!!result.checkboxChecked);
@@ -591,14 +590,14 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
private getConflictsEditorInputs(syncResource: SyncResource): DiffEditorInput[] {
return this.editorService.editors.filter(input => {
const resource = input instanceof DiffEditorInput ? input.master.resource : input.resource;
const resource = input instanceof DiffEditorInput ? input.primary.resource : input.resource;
return resource && getSyncResourceFromLocalPreview(resource!, this.workbenchEnvironmentService) === syncResource;
}) as DiffEditorInput[];
}
private getAllConflictsEditorInputs(): IEditorInput[] {
return this.editorService.editors.filter(input => {
const resource = input instanceof DiffEditorInput ? input.master.resource : input.resource;
const resource = input instanceof DiffEditorInput ? input.primary.resource : input.resource;
return resource && getSyncResourceFromLocalPreview(resource!, this.workbenchEnvironmentService) !== undefined;
});
}
@@ -887,6 +886,8 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
items.push({ type: 'separator' });
}
items.push({ id: configureSyncCommand.id, label: configureSyncCommand.title });
items.push({ id: showSyncSettingsCommand.id, label: showSyncSettingsCommand.title });
items.push({ id: SHOW_SYNCED_DATA_COMMAND_ID, label: localize('show synced data', "Preferences Sync: Show Synced Data") });
items.push({ type: 'separator' });
items.push({ id: syncNowCommand.id, label: syncNowCommand.title, description: syncNowCommand.description(that.userDataSyncService) });
if (that.userDataAutoSyncService.canToggleEnablement()) {

View File

@@ -7,16 +7,15 @@ import { Registry } from 'vs/platform/registry/common/platform';
import { IViewsRegistry, Extensions, ITreeViewDescriptor, ITreeViewDataProvider, ITreeItem, TreeItemCollapsibleState, IViewsService, TreeViewItemHandleArg, ViewContainer, IViewDescriptorService } from 'vs/workbench/common/views';
import { localize } from 'vs/nls';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { TreeViewPane, TreeView } from 'vs/workbench/browser/parts/views/treeView';
import { TreeViewPane } from 'vs/workbench/browser/parts/views/treeView';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { ALL_SYNC_RESOURCES, SyncResource, IUserDataSyncService, ISyncResourceHandle, SyncStatus, IUserDataSyncResourceEnablementService, IUserDataAutoSyncService } from 'vs/platform/userDataSync/common/userDataSync';
import { ALL_SYNC_RESOURCES, SyncResource, IUserDataSyncService, ISyncResourceHandle as IResourceHandle, SyncStatus, IUserDataSyncResourceEnablementService, IUserDataAutoSyncService } from 'vs/platform/userDataSync/common/userDataSync';
import { registerAction2, Action2, MenuId } from 'vs/platform/actions/common/actions';
import { ContextKeyExpr, ContextKeyEqualsExpr, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { ContextKeyExpr, ContextKeyEqualsExpr } from 'vs/platform/contextkey/common/contextkey';
import { URI } from 'vs/base/common/uri';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { FolderThemeIcon, IThemeService } from 'vs/platform/theme/common/themeService';
import { fromNow } from 'vs/base/common/date';
import { pad } from 'vs/base/common/strings';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { Event } from 'vs/base/common/event';
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
@@ -35,12 +34,15 @@ import { IUserDataSyncWorkbenchService, CONTEXT_SYNC_STATE, getSyncAreaLabel, CO
import { IUserDataSyncMachinesService, IUserDataSyncMachine } from 'vs/platform/userDataSync/common/userDataSyncMachines';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { generateUuid } from 'vs/base/common/uuid';
import { TreeView } from 'vs/workbench/contrib/views/browser/treeView';
import { flatten } from 'vs/base/common/arrays';
export class UserDataSyncViewPaneContainer extends ViewPaneContainer {
constructor(
containerId: string,
@IDialogService private readonly dialogService: IDialogService,
@IUserDataSyncWorkbenchService private readonly userDataSyncWorkbenchService: IUserDataSyncWorkbenchService,
@ICommandService private readonly commandService: ICommandService,
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@ITelemetryService telemetryService: ITelemetryService,
@@ -63,6 +65,24 @@ export class UserDataSyncViewPaneContainer extends ViewPaneContainer {
];
}
getSecondaryActions(): IAction[] {
return [
new Action('workbench.actions.syncData.reset', localize('workbench.actions.syncData.reset', "Reset Synced Data"), undefined, true, () => this.reset()),
];
}
private async reset(): Promise<void> {
const result = await this.dialogService.confirm({
message: localize('reset', "This will clear your synced data from the cloud and stop sync on all your devices."),
title: localize('reset title', "Reset Synced Data"),
type: 'info',
primaryButton: localize('reset button', "Reset"),
});
if (result.confirmed) {
await this.userDataSyncWorkbenchService.turnoff(true);
}
}
}
export class UserDataSyncDataViews extends Disposable {
@@ -72,33 +92,28 @@ export class UserDataSyncDataViews extends Disposable {
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IUserDataAutoSyncService private readonly userDataAutoSyncService: IUserDataAutoSyncService,
@IUserDataSyncResourceEnablementService private readonly userDataSyncResourceEnablementService: IUserDataSyncResourceEnablementService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
) {
super();
this.registerViews(container);
}
private registerViews(container: ViewContainer): void {
const remoteView = this.registerDataView(container, true, true);
this.registerRemoteViewActions(remoteView);
this.registerDataView(container, false, false);
this.registerSyncedDataView(container);
this.registerMachinesView(container);
this.registerActivityView(container, true);
this.registerActivityView(container, false);
}
private registerDataView(container: ViewContainer, remote: boolean, showByDefault: boolean): TreeView {
const id = `workbench.views.sync.${remote ? 'remote' : 'local'}DataView`;
const showByDefaultContext = new RawContextKey<boolean>(id, showByDefault);
const viewEnablementContext = showByDefaultContext.bindTo(this.contextKeyService);
const name = remote ? localize('remote title', "Synced Data") : localize('local title', "Local Backup");
private registerSyncedDataView(container: ViewContainer): void {
const id = `workbench.views.syncedDataView`;
const name = localize('remote title', "Synced Data");
const treeView = this.instantiationService.createInstance(TreeView, id, name);
treeView.showCollapseAllAction = true;
treeView.showRefreshAction = true;
const disposable = treeView.onDidChangeVisibility(visible => {
if (visible && !treeView.dataProvider) {
disposable.dispose();
treeView.dataProvider = remote ? this.instantiationService.createInstance(RemoteUserDataSyncHistoryViewDataProvider)
: this.instantiationService.createInstance(LocalUserDataSyncHistoryViewDataProvider);
treeView.dataProvider = this.instantiationService.createInstance(SyncedDataViewDataProvider);
}
});
this._register(Event.any(this.userDataSyncResourceEnablementService.onDidChangeResourceEnablement, this.userDataAutoSyncService.onDidChangeEnablement)(() => treeView.refresh()));
@@ -107,9 +122,9 @@ export class UserDataSyncDataViews extends Disposable {
id,
name,
ctorDescriptor: new SyncDescriptor(TreeViewPane),
when: ContextKeyExpr.and(CONTEXT_SYNC_STATE.notEqualsTo(SyncStatus.Uninitialized), CONTEXT_ACCOUNT_STATE.isEqualTo(AccountStatus.Available), CONTEXT_ENABLE_VIEWS, showByDefaultContext),
when: ContextKeyExpr.and(CONTEXT_SYNC_STATE.notEqualsTo(SyncStatus.Uninitialized), CONTEXT_ACCOUNT_STATE.isEqualTo(AccountStatus.Available), CONTEXT_ENABLE_VIEWS),
canToggleVisibility: true,
canMoveView: true,
canMoveView: false,
treeView,
collapsed: false,
order: 100,
@@ -118,10 +133,8 @@ export class UserDataSyncDataViews extends Disposable {
registerAction2(class extends Action2 {
constructor() {
super({
id: remote ? SHOW_SYNCED_DATA_COMMAND_ID : 'workbench.userDataSync.actions.showLocalBackupData',
title: remote ?
{ value: localize('workbench.action.showSyncRemoteBackup', "Show Synced Data"), original: `Show Synced Data` }
: { value: localize('workbench.action.showSyncLocalBackup', "Show Local Backup"), original: `Show Local Backup` },
id: SHOW_SYNCED_DATA_COMMAND_ID,
title: { value: localize('workbench.action.showSyncRemoteBackup', "Show Synced Data"), original: `Show Synced Data` },
category: { value: localize('sync preferences', "Preferences Sync"), original: `Preferences Sync` },
menu: {
id: MenuId.CommandPalette,
@@ -135,7 +148,6 @@ export class UserDataSyncDataViews extends Disposable {
const commandService = accessor.get(ICommandService);
await commandService.executeCommand(ENABLE_SYNC_VIEWS_COMMAND_ID);
viewEnablementContext.set(true);
const viewContainer = viewDescriptorService.getViewContainerByViewId(id);
if (viewContainer) {
@@ -155,7 +167,6 @@ export class UserDataSyncDataViews extends Disposable {
});
this.registerDataViewActions(id);
return treeView;
}
private registerMachinesView(container: ViewContainer): void {
@@ -178,7 +189,7 @@ export class UserDataSyncDataViews extends Disposable {
ctorDescriptor: new SyncDescriptor(TreeViewPane),
when: ContextKeyExpr.and(CONTEXT_SYNC_STATE.notEqualsTo(SyncStatus.Uninitialized), CONTEXT_ACCOUNT_STATE.isEqualTo(AccountStatus.Available), CONTEXT_ENABLE_VIEWS),
canToggleVisibility: true,
canMoveView: true,
canMoveView: false,
treeView,
collapsed: false,
order: 200,
@@ -225,6 +236,37 @@ export class UserDataSyncDataViews extends Disposable {
}
private registerActivityView(container: ViewContainer, remote: boolean): void {
const id = `workbench.views.sync.${remote ? 'remote' : 'local'}Activity`;
const name = remote ? localize('remote sync activity title', "Sync Activity (Remote)") : localize('local sync activity title', "Sync Activity (Local)");
const treeView = this.instantiationService.createInstance(TreeView, id, name);
treeView.showCollapseAllAction = true;
treeView.showRefreshAction = true;
const disposable = treeView.onDidChangeVisibility(visible => {
if (visible && !treeView.dataProvider) {
disposable.dispose();
treeView.dataProvider = remote ? this.instantiationService.createInstance(RemoteUserDataSyncActivityViewDataProvider)
: this.instantiationService.createInstance(LocalUserDataSyncActivityViewDataProvider);
}
});
this._register(Event.any(this.userDataSyncResourceEnablementService.onDidChangeResourceEnablement, this.userDataAutoSyncService.onDidChangeEnablement)(() => treeView.refresh()));
const viewsRegistry = Registry.as<IViewsRegistry>(Extensions.ViewsRegistry);
viewsRegistry.registerViews([<ITreeViewDescriptor>{
id,
name,
ctorDescriptor: new SyncDescriptor(TreeViewPane),
when: ContextKeyExpr.and(CONTEXT_SYNC_STATE.notEqualsTo(SyncStatus.Uninitialized), CONTEXT_ACCOUNT_STATE.isEqualTo(AccountStatus.Available), CONTEXT_ENABLE_VIEWS),
canToggleVisibility: true,
canMoveView: false,
treeView,
collapsed: false,
order: 300,
hideByDefault: true,
}], container);
this.registerDataViewActions(id);
}
private registerDataViewActions(viewId: string) {
registerAction2(class extends Action2 {
constructor() {
@@ -249,7 +291,7 @@ export class UserDataSyncDataViews extends Disposable {
super({
id: `workbench.actions.sync.replaceCurrent`,
title: localize('workbench.actions.sync.replaceCurrent', "Restore"),
icon: { id: 'codicon/cloud-download' },
icon: { id: 'codicon/discard' },
menu: {
id: MenuId.ViewItemContext,
when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('view', viewId), ContextKeyExpr.regex('viewItem', /sync-resource-.*/i)),
@@ -262,7 +304,7 @@ export class UserDataSyncDataViews extends Disposable {
const userDataSyncService = accessor.get(IUserDataSyncService);
const { resource, syncResource } = <{ resource: string, syncResource: SyncResource }>JSON.parse(handle.$treeItemHandle);
const result = await dialogService.confirm({
message: localize('confirm replace', "Would you like to replace your current {0} with selected?", getSyncAreaLabel(syncResource)),
message: localize({ key: 'confirm replace', comment: ['A confirmation message to replace current user data (settings, extensions, keybindings, snippets) with selected version'] }, "Would you like to replace your current {0} with selected?", getSyncAreaLabel(syncResource)),
type: 'info',
title: localize('preferences sync', "Preferences Sync")
});
@@ -275,8 +317,8 @@ export class UserDataSyncDataViews extends Disposable {
registerAction2(class extends Action2 {
constructor() {
super({
id: `workbench.actions.sync.commpareWithLocal`,
title: localize('workbench.actions.sync.commpareWithLocal', "Open Changes"),
id: `workbench.actions.sync.compareWithLocal`,
title: localize({ key: 'workbench.actions.sync.compareWithLocal', comment: ['This is an action title to show the changes between local and remote version of resources'] }, "Open Changes"),
});
}
async run(accessor: ServicesAccessor, handle: TreeViewItemHandleArg): Promise<void> {
@@ -298,51 +340,23 @@ export class UserDataSyncDataViews extends Disposable {
});
}
private registerRemoteViewActions(view: TreeView) {
this.registerResetAction(view);
}
private registerResetAction(view: TreeView) {
registerAction2(class extends Action2 {
constructor() {
super({
id: `workbench.actions.syncData.reset`,
title: localize('workbench.actions.syncData.reset', "Reset Synced Data"),
menu: {
id: MenuId.ViewTitle,
when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('view', view.id)),
},
});
}
async run(accessor: ServicesAccessor): Promise<void> {
const dialogService = accessor.get(IDialogService);
const userDataSyncWorkbenchService = accessor.get(IUserDataSyncWorkbenchService);
const result = await dialogService.confirm({
message: localize('reset', "This will clear your synced data from the cloud and stop sync on all your devices."),
title: localize('reset title', "Reset Synced Data"),
type: 'info',
primaryButton: localize('reset button', "Reset"),
});
if (result.confirmed) {
await userDataSyncWorkbenchService.turnoff(true);
await view.refresh();
}
}
});
}
}
interface SyncResourceTreeItem extends ITreeItem {
resource: SyncResource;
resourceHandle: ISyncResourceHandle;
interface ISyncResourceHandle extends IResourceHandle {
syncResource: SyncResource
}
abstract class UserDataSyncHistoryViewDataProvider implements ITreeViewDataProvider {
interface SyncResourceHandleTreeItem extends ITreeItem {
syncResourceHandle: ISyncResourceHandle;
}
abstract class UserDataSyncActivityViewDataProvider implements ITreeViewDataProvider {
private syncResourceHandlesPromise: Promise<ISyncResourceHandle[]> | undefined;
constructor(
@IUserDataSyncService protected readonly userDataSyncService: IUserDataSyncService,
@IUserDataAutoSyncService protected readonly userDataAutoSyncService: IUserDataAutoSyncService,
@IUserDataSyncResourceEnablementService private readonly userDataSyncResourceEnablementService: IUserDataSyncResourceEnablementService,
@INotificationService private readonly notificationService: INotificationService,
) { }
@@ -351,12 +365,8 @@ abstract class UserDataSyncHistoryViewDataProvider implements ITreeViewDataProvi
if (!element) {
return await this.getRoots();
}
const syncResource = ALL_SYNC_RESOURCES.filter(key => key === element.handle)[0] as SyncResource;
if (syncResource) {
return await this.getChildrenForSyncResource(syncResource);
}
if ((<SyncResourceTreeItem>element).resourceHandle) {
return await this.getChildrenForSyncResourceTreeItem(<SyncResourceTreeItem>element);
if ((<SyncResourceHandleTreeItem>element).syncResourceHandle) {
return await this.getChildrenForSyncResourceTreeItem(<SyncResourceHandleTreeItem>element);
}
return [];
} catch (error) {
@@ -365,44 +375,27 @@ abstract class UserDataSyncHistoryViewDataProvider implements ITreeViewDataProvi
}
}
protected async getRoots(): Promise<ITreeItem[]> {
return ALL_SYNC_RESOURCES.map(resourceKey => ({
handle: resourceKey,
collapsibleState: TreeItemCollapsibleState.Collapsed,
label: { label: getSyncAreaLabel(resourceKey) },
description: !this.userDataAutoSyncService.isEnabled() || this.userDataSyncResourceEnablementService.isResourceEnabled(resourceKey) ? undefined : localize('not syncing', "Not syncing"),
themeIcon: FolderThemeIcon,
contextValue: resourceKey
}));
private async getRoots(): Promise<SyncResourceHandleTreeItem[]> {
this.syncResourceHandlesPromise = undefined;
const syncResourceHandles = await this.getSyncResourceHandles();
return syncResourceHandles.map(syncResourceHandle => {
const handle = JSON.stringify({ resource: syncResourceHandle.uri.toString(), syncResource: syncResourceHandle.syncResource });
return {
handle,
collapsibleState: TreeItemCollapsibleState.Collapsed,
label: { label: getSyncAreaLabel(syncResourceHandle.syncResource) },
description: fromNow(syncResourceHandle.created, true),
themeIcon: FolderThemeIcon,
syncResourceHandle,
contextValue: `sync-resource-${syncResourceHandle.syncResource}`
};
});
}
protected async getChildrenForSyncResource(syncResource: SyncResource): Promise<ITreeItem[]> {
const refHandles = await this.getSyncResourceHandles(syncResource);
if (refHandles.length) {
return refHandles.map(({ uri, created }) => {
const handle = JSON.stringify({ resource: uri.toString(), syncResource });
return <SyncResourceTreeItem>{
handle,
collapsibleState: TreeItemCollapsibleState.Collapsed,
label: { label: label(new Date(created)) },
description: fromNow(created, true),
resourceUri: uri,
resource: syncResource,
resourceHandle: { uri, created },
contextValue: `sync-resource-${syncResource}`
};
});
} else {
return [{
handle: generateUuid(),
collapsibleState: TreeItemCollapsibleState.None,
label: { label: localize('no data', "No Data") },
}];
}
}
protected async getChildrenForSyncResourceTreeItem(element: SyncResourceTreeItem): Promise<ITreeItem[]> {
const associatedResources = await this.userDataSyncService.getAssociatedResources((<SyncResourceTreeItem>element).resource, (<SyncResourceTreeItem>element).resourceHandle);
protected async getChildrenForSyncResourceTreeItem(element: SyncResourceHandleTreeItem): Promise<ITreeItem[]> {
const associatedResources = await this.userDataSyncService.getAssociatedResources((<SyncResourceHandleTreeItem>element).syncResourceHandle.syncResource, (<SyncResourceHandleTreeItem>element).syncResourceHandle);
return associatedResources.map(({ resource, comparableResource }) => {
const handle = JSON.stringify({ resource: resource.toString(), comparableResource: comparableResource?.toString() });
return {
@@ -410,33 +403,42 @@ abstract class UserDataSyncHistoryViewDataProvider implements ITreeViewDataProvi
collapsibleState: TreeItemCollapsibleState.None,
resourceUri: resource,
command: { id: `workbench.actions.sync.commpareWithLocal`, title: '', arguments: [<TreeViewItemHandleArg>{ $treeViewId: '', $treeItemHandle: handle }] },
contextValue: `sync-associatedResource-${(<SyncResourceTreeItem>element).resource}`
contextValue: `sync-associatedResource-${(<SyncResourceHandleTreeItem>element).syncResourceHandle.syncResource}`
};
});
}
protected abstract getSyncResourceHandles(syncResource: SyncResource): Promise<ISyncResourceHandle[]>;
private getSyncResourceHandles(): Promise<ISyncResourceHandle[]> {
if (this.syncResourceHandlesPromise === undefined) {
this.syncResourceHandlesPromise = Promise.all(ALL_SYNC_RESOURCES.map(async syncResource => {
const resourceHandles = await this.getResourceHandles(syncResource);
return resourceHandles.map(resourceHandle => ({ ...resourceHandle, syncResource }));
})).then(result => flatten(result).sort((a, b) => b.created - a.created));
}
return this.syncResourceHandlesPromise;
}
protected abstract getResourceHandles(syncResource: SyncResource): Promise<IResourceHandle[]>;
}
class LocalUserDataSyncHistoryViewDataProvider extends UserDataSyncHistoryViewDataProvider {
class LocalUserDataSyncActivityViewDataProvider extends UserDataSyncActivityViewDataProvider {
protected getSyncResourceHandles(syncResource: SyncResource): Promise<ISyncResourceHandle[]> {
protected getResourceHandles(syncResource: SyncResource): Promise<IResourceHandle[]> {
return this.userDataSyncService.getLocalSyncResourceHandles(syncResource);
}
}
class RemoteUserDataSyncHistoryViewDataProvider extends UserDataSyncHistoryViewDataProvider {
class RemoteUserDataSyncActivityViewDataProvider extends UserDataSyncActivityViewDataProvider {
private machinesPromise: Promise<IUserDataSyncMachine[]> | undefined;
constructor(
@IUserDataSyncService userDataSyncService: IUserDataSyncService,
@IUserDataAutoSyncService userDataAutoSyncService: IUserDataAutoSyncService,
@IUserDataSyncResourceEnablementService userDataSyncResourceEnablementService: IUserDataSyncResourceEnablementService,
@IUserDataSyncMachinesService private readonly userDataSyncMachinesService: IUserDataSyncMachinesService,
@INotificationService notificationService: INotificationService,
) {
super(userDataSyncService, userDataAutoSyncService, userDataSyncResourceEnablementService, notificationService);
super(userDataSyncService, userDataAutoSyncService, notificationService);
}
async getChildren(element?: ITreeItem): Promise<ITreeItem[]> {
@@ -453,27 +455,30 @@ class RemoteUserDataSyncHistoryViewDataProvider extends UserDataSyncHistoryViewD
return this.machinesPromise;
}
protected getSyncResourceHandles(syncResource: SyncResource): Promise<ISyncResourceHandle[]> {
protected getResourceHandles(syncResource: SyncResource): Promise<IResourceHandle[]> {
return this.userDataSyncService.getRemoteSyncResourceHandles(syncResource);
}
protected async getChildrenForSyncResourceTreeItem(element: SyncResourceTreeItem): Promise<ITreeItem[]> {
protected async getChildrenForSyncResourceTreeItem(element: SyncResourceHandleTreeItem): Promise<ITreeItem[]> {
const children = await super.getChildrenForSyncResourceTreeItem(element);
const machineId = await this.userDataSyncService.getMachineId(element.resource, element.resourceHandle);
const machineId = await this.userDataSyncService.getMachineId(element.syncResourceHandle.syncResource, element.syncResourceHandle);
if (machineId) {
const machines = await this.getMachines();
const machine = machines.find(({ id }) => id === machineId);
children.push({
handle: machineId,
label: { label: machine?.name || machineId },
collapsibleState: TreeItemCollapsibleState.None,
themeIcon: Codicon.vm,
});
children[0].description = machine?.isCurrent ? localize({ key: 'current', comment: ['Represents current machine'] }, "Current") : machine?.name;
}
return children;
}
}
class SyncedDataViewDataProvider extends RemoteUserDataSyncActivityViewDataProvider {
protected async getResourceHandles(syncResource: SyncResource): Promise<IResourceHandle[]> {
const resourceHandles = await this.userDataSyncService.getRemoteSyncResourceHandles(syncResource);
return resourceHandles.length ? [resourceHandles[0]] : [];
}
}
class UserDataSyncMachinesViewDataProvider implements ITreeViewDataProvider {
private machinesPromise: Promise<IUserDataSyncMachine[]> | undefined;
@@ -582,10 +587,3 @@ class UserDataSyncMachinesViewDataProvider implements ITreeViewDataProvider {
});
}
}
function label(date: Date): string {
return date.toLocaleDateString() +
' ' + pad(date.getHours(), 2) +
':' + pad(date.getMinutes(), 2) +
':' + pad(date.getSeconds(), 2);
}

View File

@@ -18,6 +18,8 @@ export class UserDataAutoSyncService extends UserDataAutoSyncEnablementService i
declare readonly _serviceBrand: undefined;
private readonly channel: IChannel;
get onTurnOnSync(): Event<void> { return this.channel.listen<void>('onTurnOnSync'); }
get onDidTurnOnSync(): Event<UserDataSyncError | undefined> { return Event.map(this.channel.listen<Error | undefined>('onDidTurnOnSync'), e => e ? UserDataSyncError.toUserDataSyncError(e) : undefined); }
get onError(): Event<UserDataSyncError> { return Event.map(this.channel.listen<Error>('onError'), e => UserDataSyncError.toUserDataSyncError(e)); }
constructor(

View File

@@ -50,7 +50,7 @@ class UserDataSyncReportIssueContribution extends Disposable implements IWorkben
case UserDataSyncErrorCode.TooManyRequests:
this.notificationService.notify({
severity: Severity.Error,
message: localize('too many requests', "Turned off syncing preferences on this device because it is making too many requests. Please report an issue by providing the sync logs."),
message: localize({ key: 'too many requests', comment: ['Preferences Sync is the name of the feature'] }, "Preferences sync is disabled because the current device is making too many requests. Please report an issue by providing the sync logs."),
actions: {
primary: [
new Action('Show Sync Logs', localize('show sync logs', "Show Log"), undefined, true, () => this.commandService.executeCommand(SHOW_SYNC_LOG_COMMAND_ID)),