mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-04 17:23:45 -05:00
Merge from vscode 5d18ad4c5902e3bddbc9f78da82dfc2ac349e908 (#9683)
This commit is contained in:
@@ -9,7 +9,7 @@ import { canceled, isPromiseCanceledError } from 'vs/base/common/errors';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { Disposable, DisposableStore, dispose, MutableDisposable, toDisposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { isWeb } from 'vs/base/common/platform';
|
||||
import { isEqual } from 'vs/base/common/resources';
|
||||
import { isEqual, basename } from 'vs/base/common/resources';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import type { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { registerEditorContribution, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
|
||||
@@ -32,7 +32,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import {
|
||||
CONTEXT_SYNC_STATE, getUserDataSyncStore, ISyncConfiguration, IUserDataAutoSyncService, IUserDataSyncService, IUserDataSyncStore, registerConfiguration,
|
||||
SyncResource, SyncStatus, UserDataSyncError, UserDataSyncErrorCode, USER_DATA_SYNC_SCHEME, IUserDataSyncEnablementService, CONTEXT_SYNC_ENABLEMENT,
|
||||
SyncResourceConflicts, Conflict, getSyncResourceFromLocalPreview, getSyncResourceFromRemotePreview
|
||||
SyncResourceConflicts, Conflict, getSyncResourceFromLocalPreview
|
||||
} from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { FloatingClickWidget } from 'vs/workbench/browser/parts/editor/editorWidgets';
|
||||
import { GLOBAL_ACTIVITY_ID } from 'vs/workbench/common/activity';
|
||||
@@ -69,6 +69,7 @@ function getSyncAreaLabel(source: SyncResource): string {
|
||||
switch (source) {
|
||||
case SyncResource.Settings: return localize('settings', "Settings");
|
||||
case SyncResource.Keybindings: return localize('keybindings', "Keyboard Shortcuts");
|
||||
case SyncResource.Snippets: return localize('snippets', "User Snippets");
|
||||
case SyncResource.Extensions: return localize('extensions', "Extensions");
|
||||
case SyncResource.GlobalState: return localize('ui state label', "UI State");
|
||||
}
|
||||
@@ -100,6 +101,7 @@ const signInCommand = { id: 'workbench.userData.actions.signin', title: localize
|
||||
const stopSyncCommand = { id: 'workbench.userData.actions.stopSync', title(authenticationProviderId: string, account: AuthenticationSession | undefined, authenticationService: IAuthenticationService) { return getIdentityTitle(localize('stop sync', "Sync: Turn off Sync"), authenticationProviderId, account, authenticationService); } };
|
||||
const resolveSettingsConflictsCommand = { id: 'workbench.userData.actions.resolveSettingsConflicts', title: localize('showConflicts', "Sync: Show Settings Conflicts") };
|
||||
const resolveKeybindingsConflictsCommand = { id: 'workbench.userData.actions.resolveKeybindingsConflicts', title: localize('showKeybindingsConflicts', "Sync: Show Keybindings Conflicts") };
|
||||
const resolveSnippetsConflictsCommand = { id: 'workbench.userData.actions.resolveSnippetsConflicts', title: localize('showSnippetsConflicts', "Sync: Show User Snippets Conflicts") };
|
||||
const configureSyncCommand = { id: 'workbench.userData.actions.configureSync', title: localize('configure sync', "Sync: Configure") };
|
||||
const showSyncActivityCommand = {
|
||||
id: 'workbench.userData.actions.showSyncActivity', title(userDataSyncService: IUserDataSyncService): string {
|
||||
@@ -291,6 +293,9 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
if (conflicts.length) {
|
||||
const conflictsSources: SyncResource[] = conflicts.map(conflict => conflict.syncResource);
|
||||
this.conflictsSources.set(conflictsSources.join(','));
|
||||
if (conflictsSources.indexOf(SyncResource.Snippets) !== -1) {
|
||||
this.registerShowSnippetsConflictsAction();
|
||||
}
|
||||
|
||||
// Clear and dispose conflicts those were cleared
|
||||
this.conflictsDisposables.forEach((disposable, conflictsSource) => {
|
||||
@@ -301,8 +306,19 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
});
|
||||
|
||||
for (const { syncResource, conflicts } of this.userDataSyncService.conflicts) {
|
||||
const conflictsEditorInput = this.getConflictsEditorInput(syncResource);
|
||||
if (!conflictsEditorInput && !this.conflictsDisposables.has(syncResource)) {
|
||||
const conflictsEditorInputs = this.getConflictsEditorInputs(syncResource);
|
||||
|
||||
// close stale conflicts editor previews
|
||||
if (conflictsEditorInputs.length) {
|
||||
conflictsEditorInputs.forEach(input => {
|
||||
if (!conflicts.some(({ local }) => isEqual(local, input.master.resource))) {
|
||||
input.dispose();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Show conflicts notification if not shown before
|
||||
else if (!this.conflictsDisposables.has(syncResource)) {
|
||||
const conflictsArea = getSyncAreaLabel(syncResource);
|
||||
const handle = this.notificationService.prompt(Severity.Warning, localize('conflicts detected', "Unable to sync due to conflicts in {0}. Please resolve them to continue.", conflictsArea.toLowerCase()),
|
||||
[
|
||||
@@ -338,9 +354,9 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
handle.close();
|
||||
|
||||
// close opened conflicts editor previews
|
||||
const conflictsEditorInput = this.getConflictsEditorInput(syncResource);
|
||||
if (conflictsEditorInput) {
|
||||
conflictsEditorInput.dispose();
|
||||
const conflictsEditorInputs = this.getConflictsEditorInputs(syncResource);
|
||||
if (conflictsEditorInputs.length) {
|
||||
conflictsEditorInputs.forEach(input => input.dispose());
|
||||
}
|
||||
|
||||
this.conflictsDisposables.delete(syncResource);
|
||||
@@ -496,7 +512,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
if (this.userDataSyncService.status !== SyncStatus.Uninitialized && this.userDataSyncEnablementService.isEnabled() && this.authenticationState.get() === AuthStatus.SignedOut) {
|
||||
badge = new NumberBadge(1, () => localize('sign in to sync', "Sign in to Sync"));
|
||||
} else if (this.userDataSyncService.conflicts.length) {
|
||||
badge = new NumberBadge(this.userDataSyncService.conflicts.length, () => localize('has conflicts', "Sync: Conflicts Detected"));
|
||||
badge = new NumberBadge(this.userDataSyncService.conflicts.reduce((result, syncResourceConflict) => { return result + syncResourceConflict.conflicts.length; }, 0), () => localize('has conflicts', "Sync: Conflicts Detected"));
|
||||
}
|
||||
|
||||
if (badge) {
|
||||
@@ -605,6 +621,9 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
}, {
|
||||
id: SyncResource.Keybindings,
|
||||
label: getSyncAreaLabel(SyncResource.Keybindings)
|
||||
}, {
|
||||
id: SyncResource.Snippets,
|
||||
label: getSyncAreaLabel(SyncResource.Snippets)
|
||||
}, {
|
||||
id: SyncResource.Extensions,
|
||||
label: getSyncAreaLabel(SyncResource.Extensions)
|
||||
@@ -712,6 +731,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
switch (source) {
|
||||
case SyncResource.Settings: return this.userDataSyncEnablementService.setResourceEnablement(SyncResource.Settings, false);
|
||||
case SyncResource.Keybindings: return this.userDataSyncEnablementService.setResourceEnablement(SyncResource.Keybindings, false);
|
||||
case SyncResource.Snippets: return this.userDataSyncEnablementService.setResourceEnablement(SyncResource.Snippets, false);
|
||||
case SyncResource.Extensions: return this.userDataSyncEnablementService.setResourceEnablement(SyncResource.Extensions, false);
|
||||
case SyncResource.GlobalState: return this.userDataSyncEnablementService.setResourceEnablement(SyncResource.GlobalState, false);
|
||||
}
|
||||
@@ -727,8 +747,11 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
}
|
||||
}
|
||||
|
||||
private getConflictsEditorInput(syncResource: SyncResource): IEditorInput | undefined {
|
||||
return this.editorService.editors.filter(input => input instanceof DiffEditorInput && getSyncResourceFromLocalPreview(input.master.resource!, this.workbenchEnvironmentService) === syncResource)[0];
|
||||
private getConflictsEditorInputs(syncResource: SyncResource): DiffEditorInput[] {
|
||||
return this.editorService.editors.filter(input => {
|
||||
const resource = input instanceof DiffEditorInput ? input.master.resource : input.resource;
|
||||
return getSyncResourceFromLocalPreview(resource!, this.workbenchEnvironmentService) === syncResource;
|
||||
}) as DiffEditorInput[];
|
||||
}
|
||||
|
||||
private getAllConflictsEditorInputs(): IEditorInput[] {
|
||||
@@ -752,6 +775,8 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
label = localize('settings conflicts preview', "Settings Conflicts (Remote ↔ Local)");
|
||||
} else if (syncResource === SyncResource.Keybindings) {
|
||||
label = localize('keybindings conflicts preview', "Keybindings Conflicts (Remote ↔ Local)");
|
||||
} else if (syncResource === SyncResource.Snippets) {
|
||||
label = localize('snippets conflicts preview', "User Snippet Conflicts (Remote ↔ Local) - {0}", basename(conflict.local));
|
||||
}
|
||||
await this.editorService.openEditor({
|
||||
leftResource: conflict.remote,
|
||||
@@ -775,6 +800,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
this.registerSignInAction();
|
||||
this.registerShowSettingsConflictsAction();
|
||||
this.registerShowKeybindingsConflictsAction();
|
||||
this.registerShowSnippetsConflictsAction();
|
||||
this.registerSyncStatusAction();
|
||||
|
||||
this.registerTurnOffSyncAction();
|
||||
@@ -894,7 +920,36 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
command: resolveKeybindingsConflictsCommand,
|
||||
when: resolveKeybindingsConflictsWhenContext,
|
||||
});
|
||||
}
|
||||
|
||||
private _snippetsConflictsActionsDisposable: DisposableStore = new DisposableStore();
|
||||
private registerShowSnippetsConflictsAction(): void {
|
||||
this._snippetsConflictsActionsDisposable.clear();
|
||||
const resolveSnippetsConflictsWhenContext = ContextKeyExpr.regex(CONTEXT_CONFLICTS_SOURCES.keys()[0], /.*snippets.*/i);
|
||||
const conflicts: Conflict[] | undefined = this.userDataSyncService.conflicts.filter(({ syncResource }) => syncResource === SyncResource.Snippets)[0]?.conflicts;
|
||||
this._snippetsConflictsActionsDisposable.add(CommandsRegistry.registerCommand(resolveSnippetsConflictsCommand.id, () => this.handleSyncResourceConflicts(SyncResource.Snippets)));
|
||||
this._snippetsConflictsActionsDisposable.add(MenuRegistry.appendMenuItem(MenuId.GlobalActivity, {
|
||||
group: '5_sync',
|
||||
command: {
|
||||
id: resolveSnippetsConflictsCommand.id,
|
||||
title: localize('resolveSnippetsConflicts_global', "Sync: Show User Snippets Conflicts ({0})", conflicts?.length || 1),
|
||||
},
|
||||
when: resolveSnippetsConflictsWhenContext,
|
||||
order: 2
|
||||
}));
|
||||
this._snippetsConflictsActionsDisposable.add(MenuRegistry.appendMenuItem(MenuId.MenubarPreferencesMenu, {
|
||||
group: '5_sync',
|
||||
command: {
|
||||
id: resolveSnippetsConflictsCommand.id,
|
||||
title: localize('resolveSnippetsConflicts_global', "Sync: Show User Snippets Conflicts ({0})", conflicts?.length || 1),
|
||||
},
|
||||
when: resolveSnippetsConflictsWhenContext,
|
||||
order: 2
|
||||
}));
|
||||
this._snippetsConflictsActionsDisposable.add(MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
|
||||
command: resolveSnippetsConflictsCommand,
|
||||
when: resolveSnippetsConflictsWhenContext,
|
||||
}));
|
||||
}
|
||||
|
||||
private registerSyncStatusAction(): void {
|
||||
@@ -938,6 +993,9 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
case SyncResource.Keybindings:
|
||||
items.push({ id: resolveKeybindingsConflictsCommand.id, label: resolveKeybindingsConflictsCommand.title });
|
||||
break;
|
||||
case SyncResource.Snippets:
|
||||
items.push({ id: resolveSnippetsConflictsCommand.id, label: resolveSnippetsConflictsCommand.title });
|
||||
break;
|
||||
}
|
||||
}
|
||||
items.push({ type: 'separator' });
|
||||
@@ -1074,7 +1132,6 @@ class AcceptChangesContribution extends Disposable implements IEditorContributio
|
||||
constructor(
|
||||
private editor: ICodeEditor,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
|
||||
@IUserDataSyncService private readonly userDataSyncService: IUserDataSyncService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IDialogService private readonly dialogService: IDialogService,
|
||||
@@ -1088,7 +1145,8 @@ class AcceptChangesContribution extends Disposable implements IEditorContributio
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
this._register(this.editor.onDidChangeModel(e => this.update()));
|
||||
this._register(this.editor.onDidChangeModel(() => this.update()));
|
||||
this._register(this.userDataSyncService.onDidChangeConflicts(() => this.update()));
|
||||
this._register(Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('diffEditor.renderSideBySide'))(() => this.update()));
|
||||
}
|
||||
|
||||
@@ -1107,11 +1165,16 @@ class AcceptChangesContribution extends Disposable implements IEditorContributio
|
||||
return false; // we need a model
|
||||
}
|
||||
|
||||
if (getSyncResourceFromLocalPreview(model.uri, this.environmentService) !== undefined) {
|
||||
const syncResourceConflicts = this.getSyncResourceConflicts(model.uri);
|
||||
if (!syncResourceConflicts) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (syncResourceConflicts.conflicts.some(({ local }) => isEqual(local, model.uri))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (getSyncResourceFromRemotePreview(model.uri, this.environmentService) !== undefined) {
|
||||
if (syncResourceConflicts.conflicts.some(({ remote }) => isEqual(remote, model.uri))) {
|
||||
return this.configurationService.getValue<boolean>('diffEditor.renderSideBySide');
|
||||
}
|
||||
|
||||
@@ -1121,16 +1184,17 @@ class AcceptChangesContribution extends Disposable implements IEditorContributio
|
||||
|
||||
private createAcceptChangesWidgetRenderer(): void {
|
||||
if (!this.acceptChangesButton) {
|
||||
const isRemote = getSyncResourceFromRemotePreview(this.editor.getModel()!.uri, this.environmentService) !== undefined;
|
||||
const resource = this.editor.getModel()!.uri;
|
||||
const syncResourceConflicts = this.getSyncResourceConflicts(resource)!;
|
||||
const isRemote = syncResourceConflicts.conflicts.some(({ remote }) => isEqual(remote, resource));
|
||||
const acceptRemoteLabel = localize('accept remote', "Accept Remote");
|
||||
const acceptLocalLabel = localize('accept local', "Accept Local");
|
||||
this.acceptChangesButton = this.instantiationService.createInstance(FloatingClickWidget, this.editor, isRemote ? acceptRemoteLabel : acceptLocalLabel, null);
|
||||
this._register(this.acceptChangesButton.onClick(async () => {
|
||||
const model = this.editor.getModel();
|
||||
if (model) {
|
||||
const conflictsSource = (getSyncResourceFromLocalPreview(model.uri, this.environmentService) || getSyncResourceFromRemotePreview(model.uri, this.environmentService))!;
|
||||
this.telemetryService.publicLog2<{ source: string, action: string }, SyncConflictsClassification>('sync/handleConflicts', { source: conflictsSource, action: isRemote ? 'acceptRemote' : 'acceptLocal' });
|
||||
const syncAreaLabel = getSyncAreaLabel(conflictsSource);
|
||||
this.telemetryService.publicLog2<{ source: string, action: string }, SyncConflictsClassification>('sync/handleConflicts', { source: syncResourceConflicts.syncResource, action: isRemote ? 'acceptRemote' : 'acceptLocal' });
|
||||
const syncAreaLabel = getSyncAreaLabel(syncResourceConflicts.syncResource);
|
||||
const result = await this.dialogService.confirm({
|
||||
type: 'info',
|
||||
title: isRemote
|
||||
@@ -1146,7 +1210,7 @@ class AcceptChangesContribution extends Disposable implements IEditorContributio
|
||||
await this.userDataSyncService.acceptConflict(model.uri, model.getValue());
|
||||
} catch (e) {
|
||||
if (e instanceof UserDataSyncError && e.code === UserDataSyncErrorCode.LocalPreconditionFailed) {
|
||||
const syncResourceCoflicts = this.userDataSyncService.conflicts.filter(({ syncResource }) => syncResource === conflictsSource)[0];
|
||||
const syncResourceCoflicts = this.userDataSyncService.conflicts.filter(({ syncResource }) => syncResource === syncResourceConflicts.syncResource)[0];
|
||||
if (syncResourceCoflicts && syncResourceCoflicts.conflicts.some(conflict => isEqual(conflict.local, model.uri) || isEqual(conflict.remote, model.uri))) {
|
||||
this.notificationService.warn(localize('update conflicts', "Could not resolve conflicts as there is new local version available. Please try again."));
|
||||
}
|
||||
@@ -1162,6 +1226,10 @@ class AcceptChangesContribution extends Disposable implements IEditorContributio
|
||||
}
|
||||
}
|
||||
|
||||
private getSyncResourceConflicts(resource: URI): SyncResourceConflicts | undefined {
|
||||
return this.userDataSyncService.conflicts.filter(({ conflicts }) => conflicts.some(({ local, remote }) => isEqual(local, resource) || isEqual(remote, resource)))[0];
|
||||
}
|
||||
|
||||
private disposeAcceptChangesWidgetRenderer(): void {
|
||||
dispose(this.acceptChangesButton);
|
||||
this.acceptChangesButton = undefined;
|
||||
|
||||
Reference in New Issue
Block a user