diff --git a/src/vs/workbench/contrib/scm/browser/quickDiffDecorator.ts b/src/vs/workbench/contrib/scm/browser/quickDiffDecorator.ts index 8e701d3d92c36..01c9eb2173c2f 100644 --- a/src/vs/workbench/contrib/scm/browser/quickDiffDecorator.ts +++ b/src/vs/workbench/contrib/scm/browser/quickDiffDecorator.ts @@ -21,6 +21,10 @@ import { QuickDiffModel, IQuickDiffModelService } from './quickDiffModel.js'; import { IWorkbenchContribution } from '../../../common/contributions.js'; import { ResourceMap } from '../../../../base/common/map.js'; import { IUriIdentityService } from '../../../../platform/uriIdentity/common/uriIdentity.js'; +import { IContextKey, IContextKeyService, RawContextKey } from '../../../../platform/contextkey/common/contextkey.js'; +import { autorun, autorunWithStore, observableFromEvent } from '../../../../base/common/observable.js'; + +export const quickDiffDecorationCount = new RawContextKey('quickDiffDecorationCount', 0); class QuickDiffDecorator extends Disposable { @@ -166,7 +170,7 @@ class QuickDiffDecorator extends Disposable { override dispose(): void { if (this.decorationsCollection) { - this.decorationsCollection?.clear(); + this.decorationsCollection.clear(); } this.decorationsCollection = undefined; this.quickDiffModelRef.dispose(); @@ -182,6 +186,10 @@ interface QuickDiffWorkbenchControllerViewState { export class QuickDiffWorkbenchController extends Disposable implements IWorkbenchContribution { private enabled = false; + private readonly quickDiffDecorationCount: IContextKey; + + private readonly activeEditor = observableFromEvent(this, + this.editorService.onDidActiveEditorChange, () => this.editorService.activeEditor); // Resource URI -> Code Editor Id -> Decoration (Disposable) private readonly decorators = new ResourceMap>(); @@ -194,10 +202,13 @@ export class QuickDiffWorkbenchController extends Disposable implements IWorkben @IConfigurationService private readonly configurationService: IConfigurationService, @IQuickDiffModelService private readonly quickDiffModelService: IQuickDiffModelService, @IUriIdentityService private readonly uriIdentityService: IUriIdentityService, + @IContextKeyService contextKeyService: IContextKeyService, ) { super(); this.stylesheet = domStylesheetsJs.createStyleSheet(undefined, undefined, this._store); + this.quickDiffDecorationCount = quickDiffDecorationCount.bindTo(contextKeyService); + const onDidChangeConfiguration = Event.filter(configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('scm.diffDecorations')); this._register(onDidChangeConfiguration(this.onDidChangeConfiguration, this)); this.onDidChangeConfiguration(); @@ -266,6 +277,9 @@ export class QuickDiffWorkbenchController extends Disposable implements IWorkben this.transientDisposables.add(Event.any(this.editorService.onDidCloseEditor, this.editorService.onDidVisibleEditorsChange)(() => this.onEditorsChanged())); this.onEditorsChanged(); + + this.onDidActiveEditorChange(); + this.enabled = true; } @@ -275,6 +289,7 @@ export class QuickDiffWorkbenchController extends Disposable implements IWorkben } this.transientDisposables.clear(); + this.quickDiffDecorationCount.set(0); for (const [uri, decoratorMap] of this.decorators.entries()) { decoratorMap.dispose(); @@ -284,6 +299,37 @@ export class QuickDiffWorkbenchController extends Disposable implements IWorkben this.enabled = false; } + private onDidActiveEditorChange(): void { + this.transientDisposables.add(autorunWithStore((reader, store) => { + const activeEditor = this.activeEditor.read(reader); + const activeTextEditorControl = this.editorService.activeTextEditorControl; + + if (!isCodeEditor(activeTextEditorControl) || !activeEditor?.resource) { + this.quickDiffDecorationCount.set(0); + return; + } + + const quickDiffModelRef = this.quickDiffModelService.createQuickDiffModelReference(activeEditor.resource); + if (!quickDiffModelRef) { + this.quickDiffDecorationCount.set(0); + return; + } + + store.add(quickDiffModelRef); + + const visibleDecorationCount = observableFromEvent(this, + quickDiffModelRef.object.onDidChange, () => { + const visibleQuickDiffs = quickDiffModelRef.object.quickDiffs.filter(quickDiff => quickDiff.visible); + return quickDiffModelRef.object.changes.filter(labeledChange => visibleQuickDiffs.some(quickDiff => quickDiff.label === labeledChange.label)).length; + }); + + store.add(autorun(reader => { + const count = visibleDecorationCount.read(reader); + this.quickDiffDecorationCount.set(count); + })); + })); + } + private onEditorsChanged(): void { for (const editor of this.editorService.visibleTextEditorControls) { if (!isCodeEditor(editor)) { diff --git a/src/vs/workbench/contrib/scm/browser/quickDiffWidget.ts b/src/vs/workbench/contrib/scm/browser/quickDiffWidget.ts index 37ed63fb396f1..791a1eb7f3178 100644 --- a/src/vs/workbench/contrib/scm/browser/quickDiffWidget.ts +++ b/src/vs/workbench/contrib/scm/browser/quickDiffWidget.ts @@ -49,6 +49,7 @@ import { Codicon } from '../../../../base/common/codicons.js'; import { Color } from '../../../../base/common/color.js'; import { KeyCode, KeyMod } from '../../../../base/common/keyCodes.js'; import { getOuterEditor } from '../../../../editor/browser/widget/codeEditor/embeddedCodeEditorWidget.js'; +import { quickDiffDecorationCount } from './quickDiffDecorator.js'; export const isQuickDiffVisible = new RawContextKey('dirtyDiffVisible', false); @@ -804,7 +805,7 @@ export class GotoPreviousChangeAction extends EditorAction { super({ id: 'workbench.action.editor.previousChange', label: nls.localize2('move to previous change', "Go to Previous Change"), - precondition: TextCompareEditorActiveContext.toNegated(), + precondition: ContextKeyExpr.and(TextCompareEditorActiveContext.toNegated(), quickDiffDecorationCount.notEqualsTo(0)), kbOpts: { kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.Shift | KeyMod.Alt | KeyCode.F5, weight: KeybindingWeight.EditorContrib } }); } @@ -844,7 +845,7 @@ export class GotoNextChangeAction extends EditorAction { super({ id: 'workbench.action.editor.nextChange', label: nls.localize2('move to next change', "Go to Next Change"), - precondition: TextCompareEditorActiveContext.toNegated(), + precondition: ContextKeyExpr.and(TextCompareEditorActiveContext.toNegated(), quickDiffDecorationCount.notEqualsTo(0)), kbOpts: { kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.Alt | KeyCode.F5, weight: KeybindingWeight.EditorContrib } }); }