From 29a15dd045a9d6d7e633944ea30dad0f8366bdc0 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 4 Feb 2020 08:34:55 +0100 Subject: [PATCH] working copy - support initial working copies --- src/vs/workbench/browser/contextkeys.ts | 3 ++- .../browser/parts/editor/editorAutoSave.ts | 22 ++++++++++++++----- .../contrib/backup/common/backupTracker.ts | 22 ++++++++++++++----- .../contrib/files/browser/fileActions.ts | 12 +++++----- .../files/browser/views/openEditorsView.ts | 2 +- .../files/common/dirtyFilesIndicator.ts | 15 +++++-------- .../search/browser/searchEditorInput.ts | 7 +----- src/vs/workbench/electron-browser/window.ts | 22 ++++++++++++------- 8 files changed, 62 insertions(+), 43 deletions(-) diff --git a/src/vs/workbench/browser/contextkeys.ts b/src/vs/workbench/browser/contextkeys.ts index 6f1eebf4841..2f138cb0c65 100644 --- a/src/vs/workbench/browser/contextkeys.ts +++ b/src/vs/workbench/browser/contextkeys.ts @@ -118,6 +118,7 @@ export class WorkbenchContextKeysHandler extends Disposable { // Working Copies this.dirtyWorkingCopiesContext = DirtyWorkingCopiesContext.bindTo(this.contextKeyService); + this.dirtyWorkingCopiesContext.set(this.workingCopyService.hasDirty); // Inputs this.inputFocusedContext = InputFocusedContext.bindTo(this.contextKeyService); @@ -187,7 +188,7 @@ export class WorkbenchContextKeysHandler extends Disposable { this._register(this.layoutService.onPartVisibilityChange(() => this.editorAreaVisibleContext.set(this.layoutService.isVisible(Parts.EDITOR_PART)))); - this._register(this.workingCopyService.onDidChangeDirty(w => this.dirtyWorkingCopiesContext.set(w.isDirty() || this.workingCopyService.hasDirty))); + this._register(this.workingCopyService.onDidChangeDirty(workingCopy => this.dirtyWorkingCopiesContext.set(workingCopy.isDirty() || this.workingCopyService.hasDirty))); } private updateEditorContextKeys(): void { diff --git a/src/vs/workbench/browser/parts/editor/editorAutoSave.ts b/src/vs/workbench/browser/parts/editor/editorAutoSave.ts index 4bf84682dba..ddd07b51647 100644 --- a/src/vs/workbench/browser/parts/editor/editorAutoSave.ts +++ b/src/vs/workbench/browser/parts/editor/editorAutoSave.ts @@ -38,6 +38,9 @@ export class EditorAutoSave extends Disposable implements IWorkbenchContribution // Figure out initial auto save config this.onAutoSaveConfigurationChange(filesConfigurationService.getAutoSaveConfiguration(), false); + // Fill in initial dirty working copies + this.workingCopyService.dirtyWorkingCopies.forEach(workingCopy => this.onDidRegister(workingCopy)); + this.registerListeners(); } @@ -47,10 +50,10 @@ export class EditorAutoSave extends Disposable implements IWorkbenchContribution this._register(this.filesConfigurationService.onAutoSaveConfigurationChange(config => this.onAutoSaveConfigurationChange(config, true))); // Working Copy events - this._register(this.workingCopyService.onDidRegister(c => this.onDidRegister(c))); - this._register(this.workingCopyService.onDidUnregister(c => this.onDidUnregister(c))); - this._register(this.workingCopyService.onDidChangeDirty(c => this.onDidChangeDirty(c))); - this._register(this.workingCopyService.onDidChangeContent(c => this.onDidChangeContent(c))); + this._register(this.workingCopyService.onDidRegister(workingCopy => this.onDidRegister(workingCopy))); + this._register(this.workingCopyService.onDidUnregister(workingCopy => this.onDidUnregister(workingCopy))); + this._register(this.workingCopyService.onDidChangeDirty(workingCopy => this.onDidChangeDirty(workingCopy))); + this._register(this.workingCopyService.onDidChangeContent(workingCopy => this.onDidChangeContent(workingCopy))); } private onWindowFocusChange(focused: boolean): void { @@ -141,7 +144,9 @@ export class EditorAutoSave extends Disposable implements IWorkbenchContribution } private onDidRegister(workingCopy: IWorkingCopy): void { - this.scheduleAutoSave(workingCopy); + if (workingCopy.isDirty()) { + this.scheduleAutoSave(workingCopy); + } } private onDidUnregister(workingCopy: IWorkingCopy): void { @@ -149,13 +154,18 @@ export class EditorAutoSave extends Disposable implements IWorkbenchContribution } private onDidChangeDirty(workingCopy: IWorkingCopy): void { - if (!workingCopy.isDirty()) { + if (workingCopy.isDirty()) { + this.scheduleAutoSave(workingCopy); + } else { this.discardAutoSave(workingCopy); } } private onDidChangeContent(workingCopy: IWorkingCopy): void { if (workingCopy.isDirty()) { + // this listener will make sure that the auto save is + // pushed out for as long as the user is still changing + // the content of the working copy. this.scheduleAutoSave(workingCopy); } } diff --git a/src/vs/workbench/contrib/backup/common/backupTracker.ts b/src/vs/workbench/contrib/backup/common/backupTracker.ts index 9de7c678112..074a0c545aa 100644 --- a/src/vs/workbench/contrib/backup/common/backupTracker.ts +++ b/src/vs/workbench/contrib/backup/common/backupTracker.ts @@ -46,16 +46,19 @@ export abstract class BackupTracker extends Disposable { // Figure out initial auto save config this.onAutoSaveConfigurationChange(filesConfigurationService.getAutoSaveConfiguration()); + // Fill in initial dirty working copies + this.workingCopyService.dirtyWorkingCopies.forEach(workingCopy => this.onDidRegister(workingCopy)); + this.registerListeners(); } private registerListeners() { // Working Copy events - this._register(this.workingCopyService.onDidRegister(c => this.onDidRegister(c))); - this._register(this.workingCopyService.onDidUnregister(c => this.onDidUnregister(c))); - this._register(this.workingCopyService.onDidChangeDirty(c => this.onDidChangeDirty(c))); - this._register(this.workingCopyService.onDidChangeContent(c => this.onDidChangeContent(c))); + this._register(this.workingCopyService.onDidRegister(workingCopy => this.onDidRegister(workingCopy))); + this._register(this.workingCopyService.onDidUnregister(workingCopy => this.onDidUnregister(workingCopy))); + this._register(this.workingCopyService.onDidChangeDirty(workingCopy => this.onDidChangeDirty(workingCopy))); + this._register(this.workingCopyService.onDidChangeContent(workingCopy => this.onDidChangeContent(workingCopy))); // Listen to auto save config changes this._register(this.filesConfigurationService.onAutoSaveConfigurationChange(c => this.onAutoSaveConfigurationChange(c))); @@ -65,7 +68,9 @@ export abstract class BackupTracker extends Disposable { } private onDidRegister(workingCopy: IWorkingCopy): void { - this.scheduleBackup(workingCopy); + if (workingCopy.isDirty()) { + this.scheduleBackup(workingCopy); + } } private onDidUnregister(workingCopy: IWorkingCopy): void { @@ -78,7 +83,9 @@ export abstract class BackupTracker extends Disposable { } private onDidChangeDirty(workingCopy: IWorkingCopy): void { - if (!workingCopy.isDirty()) { + if (workingCopy.isDirty()) { + this.scheduleBackup(workingCopy); + } else { this.discardBackup(workingCopy); } } @@ -91,6 +98,9 @@ export abstract class BackupTracker extends Disposable { // Schedule backup if dirty if (workingCopy.isDirty()) { + // this listener will make sure that the backup is + // pushed out for as long as the user is still changing + // the content of the working copy. this.scheduleBackup(workingCopy); } } diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index 75143ade13d..6cdee12a156 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -522,7 +522,7 @@ export class ToggleAutoSaveAction extends Action { } export abstract class BaseSaveAllAction extends Action { - private lastIsDirty: boolean; + private lastDirtyState: boolean; constructor( id: string, @@ -533,8 +533,8 @@ export abstract class BaseSaveAllAction extends Action { ) { super(id, label); - this.lastIsDirty = this.workingCopyService.hasDirty; - this.enabled = this.lastIsDirty; + this.lastDirtyState = this.workingCopyService.hasDirty; + this.enabled = this.lastDirtyState; this.registerListeners(); } @@ -544,14 +544,14 @@ export abstract class BaseSaveAllAction extends Action { private registerListeners(): void { // update enablement based on working copy changes - this._register(this.workingCopyService.onDidChangeDirty(w => this.updateEnablement(w))); + this._register(this.workingCopyService.onDidChangeDirty(workingCopy => this.updateEnablement(workingCopy))); } private updateEnablement(workingCopy: IWorkingCopy): void { const hasDirty = workingCopy.isDirty() || this.workingCopyService.hasDirty; - if (this.lastIsDirty !== hasDirty) { + if (this.lastDirtyState !== hasDirty) { this.enabled = hasDirty; - this.lastIsDirty = this.enabled; + this.lastDirtyState = this.enabled; } } diff --git a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts index 5b9d427175a..7f4bd5af4e9 100644 --- a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts +++ b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts @@ -104,7 +104,7 @@ export class OpenEditorsView extends ViewPane { this._register(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationChange(e))); // Handle dirty counter - this._register(this.workingCopyService.onDidChangeDirty(c => this.updateDirtyIndicator(c))); + this._register(this.workingCopyService.onDidChangeDirty(workingCopy => this.updateDirtyIndicator(workingCopy))); } private registerUpdateEvents(): void { diff --git a/src/vs/workbench/contrib/files/common/dirtyFilesIndicator.ts b/src/vs/workbench/contrib/files/common/dirtyFilesIndicator.ts index 369174b9f64..fd1995933f4 100644 --- a/src/vs/workbench/contrib/files/common/dirtyFilesIndicator.ts +++ b/src/vs/workbench/contrib/files/common/dirtyFilesIndicator.ts @@ -15,11 +15,7 @@ import { IFilesConfigurationService, AutoSaveMode } from 'vs/workbench/services/ export class DirtyFilesIndicator extends Disposable implements IWorkbenchContribution { private readonly badgeHandle = this._register(new MutableDisposable()); - private lastKnownDirtyCount: number | undefined; - - private get hasDirtyCount(): boolean { - return typeof this.lastKnownDirtyCount === 'number' && this.lastKnownDirtyCount > 0; - } + private lastKnownDirtyCount = 0; constructor( @ILifecycleService private readonly lifecycleService: ILifecycleService, @@ -29,13 +25,15 @@ export class DirtyFilesIndicator extends Disposable implements IWorkbenchContrib ) { super(); + this.updateActivityBadge(); + this.registerListeners(); } private registerListeners(): void { // Working copy dirty indicator - this._register(this.workingCopyService.onDidChangeDirty(c => this.onWorkingCopyDidChangeDirty(c))); + this._register(this.workingCopyService.onDidChangeDirty(workingCopy => this.onWorkingCopyDidChangeDirty(workingCopy))); // Lifecycle this.lifecycleService.onShutdown(this.dispose, this); @@ -47,14 +45,13 @@ export class DirtyFilesIndicator extends Disposable implements IWorkbenchContrib return; // do not indicate dirty of working copies that are auto saved after short delay } - if (gotDirty || this.hasDirtyCount) { + if (gotDirty || this.lastKnownDirtyCount > 0) { this.updateActivityBadge(); } } private updateActivityBadge(): void { - const dirtyCount = this.workingCopyService.dirtyCount; - this.lastKnownDirtyCount = dirtyCount; + const dirtyCount = this.lastKnownDirtyCount = this.workingCopyService.dirtyCount; // Indicate dirty count in badge if any if (dirtyCount > 0) { diff --git a/src/vs/workbench/contrib/search/browser/searchEditorInput.ts b/src/vs/workbench/contrib/search/browser/searchEditorInput.ts index b75ecfed99f..76542852994 100644 --- a/src/vs/workbench/contrib/search/browser/searchEditorInput.ts +++ b/src/vs/workbench/contrib/search/browser/searchEditorInput.ts @@ -172,14 +172,9 @@ export class SearchEditorInput extends EditorInput { return null; } - async setDirty(dirty: boolean) { + setDirty(dirty: boolean) { this.dirty = dirty; this._onDidChangeDirty.fire(); - - await this.model; - - // fire again because some listeners dont attach early enough. See #89406 and #89267. - this._onDidChangeDirty.fire(); } isDirty() { diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index debe0d0e1d6..782483ff9c5 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -272,13 +272,10 @@ export class ElectronWindow extends Disposable { return; // do not indicate dirty of working copies that are auto saved after short delay } - if ((!this.isDocumentedEdited && gotDirty) || (this.isDocumentedEdited && !gotDirty)) { - const hasDirtyFiles = this.workingCopyService.hasDirty; - this.isDocumentedEdited = hasDirtyFiles; - - this.electronService.setDocumentEdited(hasDirtyFiles); - } + this.updateDocumentEdited(gotDirty); })); + + this.updateDocumentEdited(); } // Detect minimize / maximize @@ -290,6 +287,15 @@ export class ElectronWindow extends Disposable { this.onDidChangeMaximized(this.environmentService.configuration.maximized ?? false); } + private updateDocumentEdited(isDirty = this.workingCopyService.hasDirty): void { + if ((!this.isDocumentedEdited && isDirty) || (this.isDocumentedEdited && !isDirty)) { + const hasDirtyFiles = this.workingCopyService.hasDirty; + this.isDocumentedEdited = hasDirtyFiles; + + this.electronService.setDocumentEdited(hasDirtyFiles); + } + } + private onDidChangeMaximized(maximized: boolean): void { this.layoutService.updateWindowMaximizedState(maximized); } @@ -650,8 +656,8 @@ export class ElectronWindow extends Disposable { } // Otherwise resolve promise when resource is saved - const listener = this.workingCopyService.onDidChangeDirty(e => { - if (!e.isDirty() && isEqual(resource, e.resource)) { + const listener = this.workingCopyService.onDidChangeDirty(workingCopy => { + if (!workingCopy.isDirty() && isEqual(resource, workingCopy.resource)) { listener.dispose(); resolve();