From 4b9c19ab032aaca54f60f937ab325eb00f59f984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 29 Jun 2020 15:46:35 +0200 Subject: [PATCH] fixes #101277 --- src/vs/workbench/api/browser/mainThreadSCM.ts | 35 ++++++++-------- .../workbench/api/common/extHost.protocol.ts | 2 +- src/vs/workbench/api/common/extHostSCM.ts | 40 +++++-------------- .../workbench/contrib/scm/browser/activity.ts | 6 +-- .../contrib/scm/browser/scmViewPane.ts | 26 ++++++++++-- src/vs/workbench/contrib/scm/common/scm.ts | 5 --- .../contrib/scm/common/scmService.ts | 38 ++++++++---------- 7 files changed, 68 insertions(+), 84 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadSCM.ts b/src/vs/workbench/api/browser/mainThreadSCM.ts index 158de62f0c9..8f78a95e712 100644 --- a/src/vs/workbench/api/browser/mainThreadSCM.ts +++ b/src/vs/workbench/api/browser/mainThreadSCM.ts @@ -6,7 +6,7 @@ import { URI, UriComponents } from 'vs/base/common/uri'; import { Event, Emitter } from 'vs/base/common/event'; import { assign } from 'vs/base/common/objects'; -import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; +import { IDisposable, DisposableStore, combinedDisposable } from 'vs/base/common/lifecycle'; import { ISCMService, ISCMRepository, ISCMProvider, ISCMResource, ISCMResourceGroup, ISCMResourceDecorations, IInputValidation } from 'vs/workbench/contrib/scm/common/scm'; import { ExtHostContext, MainThreadSCMShape, ExtHostSCMShape, SCMProviderFeatures, SCMRawResourceSplices, SCMGroupFeatures, MainContext, IExtHostContext } from '../common/extHost.protocol'; import { Command } from 'vs/editor/common/modes'; @@ -264,7 +264,7 @@ export class MainThreadSCM implements MainThreadSCMShape { private readonly _proxy: ExtHostSCMShape; private _repositories = new Map(); - private _inputDisposables = new Map(); + private _repositoryDisposables = new Map(); private readonly _disposables = new DisposableStore(); constructor( @@ -272,17 +272,14 @@ export class MainThreadSCM implements MainThreadSCMShape { @ISCMService private readonly scmService: ISCMService ) { this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostSCM); - - Event.debounce(scmService.onDidChangeSelectedRepositories, (_, e) => e, 100) - (this.onDidChangeSelectedRepositories, this, this._disposables); } dispose(): void { this._repositories.forEach(r => r.dispose()); this._repositories.clear(); - this._inputDisposables.forEach(d => d.dispose()); - this._inputDisposables.clear(); + this._repositoryDisposables.forEach(d => d.dispose()); + this._repositoryDisposables.clear(); this._disposables.dispose(); } @@ -292,8 +289,16 @@ export class MainThreadSCM implements MainThreadSCMShape { const repository = this.scmService.registerSCMProvider(provider); this._repositories.set(handle, repository); - const inputDisposable = repository.input.onDidChange(value => this._proxy.$onInputBoxValueChange(handle, value)); - this._inputDisposables.set(handle, inputDisposable); + const disposable = combinedDisposable( + Event.filter(repository.onDidChangeSelection, selected => selected)(_ => this._proxy.$setSelectedSourceControl(handle)), + repository.input.onDidChange(value => this._proxy.$onInputBoxValueChange(handle, value)) + ); + + if (repository.selected) { + setTimeout(() => this._proxy.$setSelectedSourceControl(handle), 0); + } + + this._repositoryDisposables.set(handle, disposable); } $updateSourceControl(handle: number, features: SCMProviderFeatures): void { @@ -314,8 +319,8 @@ export class MainThreadSCM implements MainThreadSCMShape { return; } - this._inputDisposables.get(handle)!.dispose(); - this._inputDisposables.delete(handle); + this._repositoryDisposables.get(handle)!.dispose(); + this._repositoryDisposables.delete(handle); repository.dispose(); this._repositories.delete(handle); @@ -422,12 +427,4 @@ export class MainThreadSCM implements MainThreadSCMShape { repository.input.validateInput = async () => undefined; } } - - private onDidChangeSelectedRepositories(repositories: ISCMRepository[]): void { - const handles = repositories - .filter(r => r.provider instanceof MainThreadSCMProvider) - .map(r => (r.provider as MainThreadSCMProvider).handle); - - this._proxy.$setSelectedSourceControls(handles); - } } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 8662080fd37..23497dc06b2 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1437,7 +1437,7 @@ export interface ExtHostSCMShape { $onInputBoxValueChange(sourceControlHandle: number, value: string): void; $executeResourceCommand(sourceControlHandle: number, groupHandle: number, handle: number, preserveFocus: boolean): Promise; $validateInput(sourceControlHandle: number, value: string, cursorPosition: number): Promise<[string, number] | undefined>; - $setSelectedSourceControls(selectedSourceControlHandles: number[]): Promise; + $setSelectedSourceControl(selectedSourceControlHandle: number | undefined): Promise; } export interface ExtHostTaskShape { diff --git a/src/vs/workbench/api/common/extHostSCM.ts b/src/vs/workbench/api/common/extHostSCM.ts index 50473953083..6464c9af686 100644 --- a/src/vs/workbench/api/common/extHostSCM.ts +++ b/src/vs/workbench/api/common/extHostSCM.ts @@ -536,7 +536,7 @@ export class ExtHostSCM implements ExtHostSCMShape { private readonly _onDidChangeActiveProvider = new Emitter(); get onDidChangeActiveProvider(): Event { return this._onDidChangeActiveProvider.event; } - private _selectedSourceControlHandles = new Set(); + private _selectedSourceControlHandle: number | undefined; constructor( mainContext: IMainContext, @@ -681,40 +681,18 @@ export class ExtHostSCM implements ExtHostSCMShape { }); } - $setSelectedSourceControls(selectedSourceControlHandles: number[]): Promise { - this.logService.trace('ExtHostSCM#$setSelectedSourceControls', selectedSourceControlHandles); + $setSelectedSourceControl(selectedSourceControlHandle: number | undefined): Promise { + this.logService.trace('ExtHostSCM#$setSelectedSourceControl', selectedSourceControlHandle); - const set = new Set(); - - for (const handle of selectedSourceControlHandles) { - set.add(handle); + if (selectedSourceControlHandle !== undefined) { + this._sourceControls.get(selectedSourceControlHandle)?.setSelectionState(true); } - set.forEach(handle => { - if (!this._selectedSourceControlHandles.has(handle)) { - const sourceControl = this._sourceControls.get(handle); + if (this._selectedSourceControlHandle !== undefined) { + this._sourceControls.get(this._selectedSourceControlHandle)?.setSelectionState(false); + } - if (!sourceControl) { - return; - } - - sourceControl.setSelectionState(true); - } - }); - - this._selectedSourceControlHandles.forEach(handle => { - if (!set.has(handle)) { - const sourceControl = this._sourceControls.get(handle); - - if (!sourceControl) { - return; - } - - sourceControl.setSelectionState(false); - } - }); - - this._selectedSourceControlHandles = set; + this._selectedSourceControlHandle = selectedSourceControlHandle; return Promise.resolve(undefined); } } diff --git a/src/vs/workbench/contrib/scm/browser/activity.ts b/src/vs/workbench/contrib/scm/browser/activity.ts index d93238046a2..c422287b3c8 100644 --- a/src/vs/workbench/contrib/scm/browser/activity.ts +++ b/src/vs/workbench/contrib/scm/browser/activity.ts @@ -92,7 +92,7 @@ export class SCMStatusController implements IWorkbenchContribution { } private onDidAddRepository(repository: ISCMRepository): void { - const focusDisposable = repository.onDidFocus(() => this.focusRepository(repository)); + const selectedDisposable = Event.filter(repository.onDidChangeSelection, selected => selected)(() => this.focusRepository(repository)); const onDidChange = Event.any(repository.provider.onDidChange, repository.provider.onDidChangeResources); const changeDisposable = onDidChange(() => this.renderActivityCount()); @@ -104,14 +104,12 @@ export class SCMStatusController implements IWorkbenchContribution { if (this.scmService.repositories.length === 0) { this.focusRepository(undefined); - } else if (this.focusedRepository === repository) { - this.scmService.repositories[0].focus(); } this.renderActivityCount(); }); - const disposable = combinedDisposable(focusDisposable, changeDisposable, removeDisposable); + const disposable = combinedDisposable(selectedDisposable, changeDisposable, removeDisposable); this.disposables.push(disposable); if (this.focusedRepository) { diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index f6fd6d118bf..1216599ff57 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -1381,6 +1381,7 @@ class SCMInputWidget extends Disposable { this._register(this.inputEditor); this._register(this.inputEditor.onDidFocusEditorText(() => { + this.input?.repository.setSelected(true); // TODO@joao: remove addClass(this.editorContainer, 'synthetic-focus'); this.renderValidation(); })); @@ -1665,11 +1666,24 @@ export class SCMViewPane extends ViewPane { } private async open(e: IOpenEvent): Promise { - if (!e.element || isSCMRepository(e.element) || isSCMResourceGroup(e.element) || ResourceTree.isResourceNode(e.element)) { + if (!e.element) { return; - } + } else if (isSCMRepository(e.element)) { // TODO@joao: remove + e.element.setSelected(true); + return; + } else if (isSCMResourceGroup(e.element)) { // TODO@joao: remove + const provider = e.element.provider; + const repository = this.scmService.repositories.find(r => r.provider === provider); + repository?.setSelected(true); + return; + } else if (ResourceTree.isResourceNode(e.element)) { // TODO@joao: remove + const provider = e.element.context.provider; + const repository = this.scmService.repositories.find(r => r.provider === provider); + repository?.setSelected(true); + return; + } else if (isSCMInput(e.element)) { + e.element.repository.setSelected(true); // TODO@joao: remove - if (isSCMInput(e.element)) { const widget = this.inputRenderer.getRenderedInputWidget(e.element); if (widget) { @@ -1685,6 +1699,7 @@ export class SCMViewPane extends ViewPane { return; } + // ISCMResource await e.element.open(!!e.editorOptions.preserveFocus); if (e.editorOptions.pinned) { @@ -1694,6 +1709,11 @@ export class SCMViewPane extends ViewPane { activeEditorPane.group.pinEditor(activeEditorPane.input); } } + + // TODO@joao: remove + const provider = e.element.resourceGroup.provider; + const repository = this.scmService.repositories.find(r => r.provider === provider); + repository?.setSelected(true); } private onListContextMenu(e: ITreeContextMenuEvent): void { diff --git a/src/vs/workbench/contrib/scm/common/scm.ts b/src/vs/workbench/contrib/scm/common/scm.ts index e59d557d182..cd96a61d4de 100644 --- a/src/vs/workbench/contrib/scm/common/scm.ts +++ b/src/vs/workbench/contrib/scm/common/scm.ts @@ -96,12 +96,10 @@ export interface ISCMInput { } export interface ISCMRepository extends IDisposable { - readonly onDidFocus: Event; readonly selected: boolean; readonly onDidChangeSelection: Event; readonly provider: ISCMProvider; readonly input: ISCMInput; - focus(): void; setSelected(selected: boolean): void; } @@ -110,10 +108,7 @@ export interface ISCMService { readonly _serviceBrand: undefined; readonly onDidAddRepository: Event; readonly onDidRemoveRepository: Event; - readonly repositories: ISCMRepository[]; - readonly selectedRepositories: ISCMRepository[]; - readonly onDidChangeSelectedRepositories: Event; registerSCMProvider(provider: ISCMProvider): ISCMRepository; } diff --git a/src/vs/workbench/contrib/scm/common/scmService.ts b/src/vs/workbench/contrib/scm/common/scmService.ts index 714a2746f48..fac8be966b7 100644 --- a/src/vs/workbench/contrib/scm/common/scmService.ts +++ b/src/vs/workbench/contrib/scm/common/scmService.ts @@ -7,7 +7,6 @@ import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { Event, Emitter } from 'vs/base/common/event'; import { ISCMService, ISCMProvider, ISCMInput, ISCMRepository, IInputValidator } from './scm'; import { ILogService } from 'vs/platform/log/common/log'; -import { equals } from 'vs/base/common/arrays'; class SCMInput implements ISCMInput { @@ -76,9 +75,6 @@ class SCMInput implements ISCMInput { class SCMRepository implements ISCMRepository { - private readonly _onDidFocus = new Emitter(); - readonly onDidFocus: Event = this._onDidFocus.event; - private _selected = false; get selected(): boolean { return this._selected; @@ -94,10 +90,6 @@ class SCMRepository implements ISCMRepository { private disposable: IDisposable ) { } - focus(): void { - this._onDidFocus.fire(); - } - setSelected(selected: boolean): void { if (this._selected === selected) { return; @@ -121,11 +113,10 @@ export class SCMService implements ISCMService { private _repositories: ISCMRepository[] = []; get repositories(): ISCMRepository[] { return [...this._repositories]; } - private _selectedRepositories: ISCMRepository[] = []; - get selectedRepositories(): ISCMRepository[] { return [...this._selectedRepositories]; } + private _selectedRepository: ISCMRepository | undefined; - private readonly _onDidChangeSelectedRepositories = new Emitter(); - readonly onDidChangeSelectedRepositories: Event = this._onDidChangeSelectedRepositories.event; + private readonly _onDidSelectRepository = new Emitter(); + readonly onDidSelectRepository: Event = this._onDidSelectRepository.event; private readonly _onDidAddProvider = new Emitter(); readonly onDidAddRepository: Event = this._onDidAddProvider.event; @@ -155,26 +146,31 @@ export class SCMService implements ISCMService { this._providerIds.delete(provider.id); this._repositories.splice(index, 1); this._onDidRemoveProvider.fire(repository); - this.onDidChangeSelection(); + + if (this._selectedRepository === repository) { + this.select(this._repositories[0]); + } }); const repository = new SCMRepository(provider, disposable); - const selectedDisposable = repository.onDidChangeSelection(this.onDidChangeSelection, this); + const selectedDisposable = Event.map(Event.filter(repository.onDidChangeSelection, selected => selected), _ => repository)(this.select, this); this._repositories.push(repository); this._onDidAddProvider.fire(repository); + if (!this._selectedRepository) { + repository.setSelected(true); + } + return repository; } - private onDidChangeSelection(): void { - const selectedRepositories = this._repositories.filter(r => r.selected); - - if (equals(this._selectedRepositories, selectedRepositories)) { - return; + private select(repository: ISCMRepository | undefined): void { + if (this._selectedRepository) { + this._selectedRepository.setSelected(false); } - this._selectedRepositories = this._repositories.filter(r => r.selected); - this._onDidChangeSelectedRepositories.fire(this.selectedRepositories); + this._selectedRepository = repository; + this._onDidSelectRepository.fire(this._selectedRepository); } }