diff --git a/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.ts b/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.ts index e512ed141a0..e29d4a29225 100644 --- a/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.ts +++ b/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.ts @@ -9,11 +9,12 @@ import nls = require('vs/nls'); import 'vs/css!./media/dirtydiffDecorator'; import { ThrottledDelayer, always } from 'vs/base/common/async'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle'; import { TPromise } from 'vs/base/common/winjs.base'; +import { any as anyEvent, filterEvent } from 'vs/base/common/event'; import * as ext from 'vs/workbench/common/contributions'; import * as common from 'vs/editor/common/editorCommon'; -import * as widget from 'vs/editor/browser/codeEditor'; +import { CodeEditor } from 'vs/editor/browser/codeEditor'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IMessageService } from 'vs/platform/message/common/message'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; @@ -23,7 +24,7 @@ import { IModelService } from 'vs/editor/common/services/modelService'; import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService'; import URI from 'vs/base/common/uri'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; -import { ISCMService } from 'vs/workbench/services/scm/common/scm'; +import { ISCMService, ISCMRepository } from 'vs/workbench/services/scm/common/scm'; import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations'; import { registerThemingParticipant, ITheme, ICssStyleCollector, themeColorFromId } from 'vs/platform/theme/common/themeService'; import { registerColor } from 'vs/platform/theme/common/colorRegistry'; @@ -87,15 +88,17 @@ class DirtyDiffModelDecorator { } }); - private decorations: string[]; + private decorations: string[] = []; private baselineModel: common.IModel; private diffDelayer: ThrottledDelayer; private _originalURIPromise: TPromise; - private toDispose: IDisposable[]; + + private repositoryDisposables = new Set(); + private toDispose: IDisposable[] = []; constructor( private model: common.IModel, - private uri: URI, + // private editor: CodeEditor, @ISCMService private scmService: ISCMService, @IModelService private modelService: IModelService, @IEditorWorkerService private editorWorkerService: IEditorWorkerService, @@ -103,12 +106,28 @@ class DirtyDiffModelDecorator { @IWorkspaceContextService private contextService: IWorkspaceContextService, @ITextModelService private textModelResolverService: ITextModelService ) { - this.decorations = []; this.diffDelayer = new ThrottledDelayer(200); - this.toDispose = []; - this.triggerDiff(); + this.toDispose.push(model.onDidChangeContent(() => this.triggerDiff())); - this.toDispose.push(scmService.onDidChangeRepository(() => this.triggerDiff())); + scmService.onDidAddRepository(this.onDidAddRepository, this, this.toDispose); + scmService.repositories.forEach(r => this.onDidAddRepository(r)); + + this.triggerDiff(); + } + + private onDidAddRepository(repository: ISCMRepository): void { + const disposables: IDisposable[] = []; + + this.repositoryDisposables.add(disposables); + disposables.push(toDisposable(() => this.repositoryDisposables.delete(disposables))); + + const onDidChange = anyEvent(repository.provider.onDidChange, repository.provider.onDidChangeResources); + onDidChange(this.triggerDiff, this, disposables); + + const onDidRemoveThis = filterEvent(this.scmService.onDidRemoveRepository, r => r === repository); + onDidRemoveThis(() => dispose(disposables)); + + this.triggerDiff(); } private triggerDiff(): TPromise { @@ -174,7 +193,7 @@ class DirtyDiffModelDecorator { private async getOriginalResource(): TPromise { for (const repository of this.scmService.repositories) { - const result = repository.provider.getOriginalResource(this.uri); + const result = repository.provider.getOriginalResource(this.model.uri); if (result) { return result; @@ -237,6 +256,9 @@ class DirtyDiffModelDecorator { this.diffDelayer.cancel(); this.diffDelayer = null; } + + this.repositoryDisposables.forEach(d => dispose(d)); + this.repositoryDisposables.clear(); } } @@ -271,28 +293,25 @@ export class DirtyDiffDecorator implements ext.IWorkbenchContribution { .map(e => e.getControl()) // only interested in code editor widgets - .filter(c => c instanceof widget.CodeEditor) + .filter(c => c instanceof CodeEditor) // map to models - .map(e => (e).getModel()) + .map(editor => (editor as CodeEditor).getModel()) // remove nulls and duplicates - .filter((m, i, a) => !!m && !!m.uri && a.indexOf(m, i + 1) === -1) + .filter((m, i, a) => !!m && !!m.uri && a.indexOf(m, i + 1) === -1); - // get the associated resource - .map(m => ({ model: m, uri: m.uri })); + const newModels = models.filter(p => this.models.every(m => p !== m)); + const oldModels = this.models.filter(m => models.every(p => p !== m)); - const newModels = models.filter(p => this.models.every(m => p.model !== m)); - const oldModels = this.models.filter(m => models.every(p => p.model !== m)); - - newModels.forEach(({ model, uri }) => this.onModelVisible(model, uri)); + newModels.forEach(m => this.onModelVisible(m)); oldModels.forEach(m => this.onModelInvisible(m)); - this.models = models.map(p => p.model); + this.models = models; } - private onModelVisible(model: common.IModel, uri: URI): void { - this.decorators[model.id] = this.instantiationService.createInstance(DirtyDiffModelDecorator, model, uri); + private onModelVisible(model: common.IModel): void { + this.decorators[model.id] = this.instantiationService.createInstance(DirtyDiffModelDecorator, model); } private onModelInvisible(model: common.IModel): void { diff --git a/src/vs/workbench/services/scm/common/scm.ts b/src/vs/workbench/services/scm/common/scm.ts index 7147cff15d6..a9337cf69b8 100644 --- a/src/vs/workbench/services/scm/common/scm.ts +++ b/src/vs/workbench/services/scm/common/scm.ts @@ -88,7 +88,6 @@ export interface ISCMService { readonly _serviceBrand: any; readonly onDidAddRepository: Event; readonly onDidRemoveRepository: Event; - readonly onDidChangeRepository: Event; readonly repositories: ISCMRepository[]; diff --git a/src/vs/workbench/services/scm/common/scmService.ts b/src/vs/workbench/services/scm/common/scmService.ts index 6e429c117b1..1a582fa342a 100644 --- a/src/vs/workbench/services/scm/common/scmService.ts +++ b/src/vs/workbench/services/scm/common/scmService.ts @@ -62,9 +62,6 @@ export class SCMService implements ISCMService { private _onDidRemoveProvider = new Emitter(); get onDidRemoveRepository(): Event { return this._onDidRemoveProvider.event; } - private _onDidChangeProvider = new Emitter(); - get onDidChangeRepository(): Event { return this._onDidChangeProvider.event; } - constructor() { } registerSCMProvider(provider: ISCMProvider): ISCMRepository {