From f429fffa7f043c5af149ae4830f1bf98fae196e4 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Fri, 27 Sep 2024 14:54:34 +0200 Subject: [PATCH] SCM - switch action button to observable to avoid using the onDidChange event (#229958) --- src/vs/workbench/api/browser/mainThreadSCM.ts | 8 +++++++- src/vs/workbench/api/common/extHost.protocol.ts | 2 +- src/vs/workbench/api/common/extHostSCM.ts | 16 +++++++++++++--- .../workbench/contrib/scm/browser/scmViewPane.ts | 9 +++++++-- src/vs/workbench/contrib/scm/common/scm.ts | 4 ++-- 5 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadSCM.ts b/src/vs/workbench/api/browser/mainThreadSCM.ts index 3a90525f8eb0a..d2a6492f93e9c 100644 --- a/src/vs/workbench/api/browser/mainThreadSCM.ts +++ b/src/vs/workbench/api/browser/mainThreadSCM.ts @@ -271,7 +271,6 @@ class MainThreadSCMProvider implements ISCMProvider, QuickDiffProvider { get contextValue(): string { return this._providerId; } get acceptInputCommand(): Command | undefined { return this.features.acceptInputCommand; } - get actionButton(): ISCMActionButtonDescriptor | undefined { return this.features.actionButton ?? undefined; } private readonly _count = observableValue(this, undefined); get count() { return this._count; } @@ -285,6 +284,9 @@ class MainThreadSCMProvider implements ISCMProvider, QuickDiffProvider { private readonly _commitTemplate = observableValue(this, ''); get commitTemplate() { return this._commitTemplate; } + private readonly _actionButton = observableValue(this, undefined); + get actionButton(): IObservable { return this._actionButton; } + private readonly _onDidChange = new Emitter(); readonly onDidChange: Event = this._onDidChange.event; @@ -323,6 +325,10 @@ class MainThreadSCMProvider implements ISCMProvider, QuickDiffProvider { this._commitTemplate.set(features.commitTemplate, undefined); } + if (typeof features.actionButton !== 'undefined') { + this._actionButton.set(features.actionButton, undefined); + } + if (typeof features.count !== 'undefined') { this._count.set(features.count, undefined); } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 90b6210401f1d..26b584ef5f703 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1534,7 +1534,7 @@ export interface SCMProviderFeatures { count?: number; commitTemplate?: string; acceptInputCommand?: languages.Command; - actionButton?: SCMActionButtonDto | null; + actionButton?: SCMActionButtonDto; statusBarCommands?: ICommandDto[]; } diff --git a/src/vs/workbench/api/common/extHostSCM.ts b/src/vs/workbench/api/common/extHostSCM.ts index d03aa03266d00..d99bc796dd008 100644 --- a/src/vs/workbench/api/common/extHostSCM.ts +++ b/src/vs/workbench/api/common/extHostSCM.ts @@ -27,6 +27,7 @@ import { checkProposedApiEnabled, isProposedApiEnabled } from '../../services/ex import { ExtHostDocuments } from './extHostDocuments.js'; import { Schemas } from '../../../base/common/network.js'; import { isLinux } from '../../../base/common/platform.js'; +import { structuralEquals } from '../../../base/common/equals.js'; type ProviderHandle = number; type GroupHandle = number; @@ -654,13 +655,21 @@ class ExtHostSourceControl implements vscode.SourceControl { checkProposedApiEnabled(this._extension, 'scmActionButton'); return this._actionButton; } + set actionButton(actionButton: vscode.SourceControlActionButton | undefined) { checkProposedApiEnabled(this._extension, 'scmActionButton'); - this._actionButtonDisposables.value = new DisposableStore(); + + // We have to do this check before converting the command to it's internal + // representation since that would always create a command with a unique + // identifier + if (structuralEquals(this._actionButton, actionButton)) { + return; + } this._actionButton = actionButton; + this._actionButtonDisposables.value = new DisposableStore(); - const internal = actionButton !== undefined ? + const actionButtonDto = actionButton !== undefined ? { command: { ...this._commands.converter.toInternal(actionButton.command, this._actionButtonDisposables.value), @@ -671,7 +680,8 @@ class ExtHostSourceControl implements vscode.SourceControl { }), enabled: actionButton.enabled } satisfies SCMActionButtonDto : undefined; - this.#proxy.$updateSourceControl(this.handle, { actionButton: internal ?? null }); + + this.#proxy.$updateSourceControl(this.handle, { actionButton: actionButtonDto }); } diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index a5ec31b3ad2b0..57350808cc0bd 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -2449,7 +2449,12 @@ export class SCMViewPane extends ViewPane { for (const repository of added) { const repositoryDisposables = new DisposableStore(); - repositoryDisposables.add(repository.provider.onDidChange(() => this.updateChildren(repository))); + repositoryDisposables.add(autorun(reader => { + /** @description action button */ + repository.provider.actionButton.read(reader); + this.updateChildren(repository); + })); + repositoryDisposables.add(repository.input.onDidChangeVisibility(() => this.updateChildren(repository))); repositoryDisposables.add(repository.provider.onDidChangeResourceGroups(() => this.updateChildren(repository))); @@ -2835,7 +2840,7 @@ class SCMTreeDataSource extends Disposable implements IAsyncDataSource; readonly historyProvider: IObservable; readonly acceptInputCommand?: Command; - readonly actionButton?: ISCMActionButtonDescriptor; + readonly actionButton: IObservable; readonly statusBarCommands: IObservable; readonly onDidChange: Event; @@ -124,7 +124,7 @@ export interface ISCMActionButtonDescriptor { export interface ISCMActionButton { readonly type: 'actionButton'; readonly repository: ISCMRepository; - readonly button?: ISCMActionButtonDescriptor; + readonly button: ISCMActionButtonDescriptor; } export interface ISCMInput {