From e8d3a7b8dc7064c4743ef70cb9ef38c5fca558bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 28 Oct 2020 15:15:39 +0100 Subject: [PATCH] fixes #108046 --- src/vs/workbench/api/browser/mainThreadSCM.ts | 9 ++--- .../workbench/contrib/scm/browser/activity.ts | 34 +++++++------------ .../contrib/scm/browser/scmViewPane.ts | 30 ++++++++++------ .../contrib/scm/browser/scmViewService.ts | 30 ++++++++++++++++ src/vs/workbench/contrib/scm/browser/util.ts | 2 +- src/vs/workbench/contrib/scm/common/scm.ts | 7 ++-- .../contrib/scm/common/scmService.ts | 24 ------------- 7 files changed, 72 insertions(+), 64 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadSCM.ts b/src/vs/workbench/api/browser/mainThreadSCM.ts index 85315eb3341..32dbe8049de 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 { IDisposable, DisposableStore, combinedDisposable } from 'vs/base/common/lifecycle'; -import { ISCMService, ISCMRepository, ISCMProvider, ISCMResource, ISCMResourceGroup, ISCMResourceDecorations, IInputValidation } from 'vs/workbench/contrib/scm/common/scm'; +import { ISCMService, ISCMRepository, ISCMProvider, ISCMResource, ISCMResourceGroup, ISCMResourceDecorations, IInputValidation, ISCMViewService } 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'; import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; @@ -273,7 +273,8 @@ export class MainThreadSCM implements MainThreadSCMShape { constructor( extHostContext: IExtHostContext, - @ISCMService private readonly scmService: ISCMService + @ISCMService private readonly scmService: ISCMService, + @ISCMViewService private readonly scmViewService: ISCMViewService ) { this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostSCM); } @@ -294,11 +295,11 @@ export class MainThreadSCM implements MainThreadSCMShape { this._repositories.set(handle, repository); const disposable = combinedDisposable( - Event.filter(repository.onDidChangeSelection, selected => selected)(_ => this._proxy.$setSelectedSourceControl(handle)), + Event.filter(this.scmViewService.onDidFocusRepository, r => r === repository)(_ => this._proxy.$setSelectedSourceControl(handle)), repository.input.onDidChange(({ value }) => this._proxy.$onInputBoxValueChange(handle, value)) ); - if (repository.selected) { + if (this.scmViewService.focusedRepository === repository) { setTimeout(() => this._proxy.$setSelectedSourceControl(handle), 0); } diff --git a/src/vs/workbench/contrib/scm/browser/activity.ts b/src/vs/workbench/contrib/scm/browser/activity.ts index 6de2a102174..87764bb2879 100644 --- a/src/vs/workbench/contrib/scm/browser/activity.ts +++ b/src/vs/workbench/contrib/scm/browser/activity.ts @@ -7,7 +7,7 @@ import { localize } from 'vs/nls'; import { basename } from 'vs/base/common/resources'; import { IDisposable, dispose, Disposable, DisposableStore, combinedDisposable, MutableDisposable } from 'vs/base/common/lifecycle'; import { Event } from 'vs/base/common/event'; -import { VIEW_PANE_ID, ISCMService, ISCMRepository } from 'vs/workbench/contrib/scm/common/scm'; +import { VIEW_PANE_ID, ISCMService, ISCMRepository, ISCMViewService } from 'vs/workbench/contrib/scm/common/scm'; import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; @@ -32,10 +32,12 @@ export class SCMStatusController implements IWorkbenchContribution { private focusedRepository: ISCMRepository | undefined = undefined; private focusedProviderContextKey: IContextKey; private readonly badgeDisposable = new MutableDisposable(); - private disposables: IDisposable[] = []; + private disposables = new DisposableStore(); + private repositoryDisposables = new Set(); constructor( @ISCMService private readonly scmService: ISCMService, + @ISCMViewService private readonly scmViewService: ISCMViewService, @IStatusbarService private readonly statusbarService: IStatusbarService, @IContextKeyService readonly contextKeyService: IContextKeyService, @IActivityService private readonly activityService: IActivityService, @@ -54,6 +56,9 @@ export class SCMStatusController implements IWorkbenchContribution { this.onDidAddRepository(repository); } + this.scmViewService.onDidFocusRepository(this.focusRepository, this, this.disposables); + this.focusRepository(this.scmViewService.focusedRepository); + editorService.onDidActiveEditorChange(this.tryFocusRepositoryBasedOnActiveEditor, this, this.disposables); this.renderActivityCount(); } @@ -92,35 +97,18 @@ export class SCMStatusController implements IWorkbenchContribution { } private onDidAddRepository(repository: ISCMRepository): void { - 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()); const onDidRemove = Event.filter(this.scmService.onDidRemoveRepository, e => e === repository); const removeDisposable = onDidRemove(() => { disposable.dispose(); - this.disposables = this.disposables.filter(d => d !== removeDisposable); - - if (this.scmService.repositories.length === 0) { - this.focusRepository(undefined); - } - + this.repositoryDisposables.delete(disposable); this.renderActivityCount(); }); - const disposable = combinedDisposable(selectedDisposable, changeDisposable, removeDisposable); - this.disposables.push(disposable); - - if (this.focusedRepository) { - return; - } - - if (this.tryFocusRepositoryBasedOnActiveEditor()) { - return; - } - - this.focusRepository(repository); + const disposable = combinedDisposable(changeDisposable, removeDisposable); + this.repositoryDisposables.add(disposable); } private onDidRemoveRepository(repository: ISCMRepository): void { @@ -201,5 +189,7 @@ export class SCMStatusController implements IWorkbenchContribution { this.statusBarDisposable.dispose(); this.badgeDisposable.dispose(); this.disposables = dispose(this.disposables); + dispose(this.repositoryDisposables.values()); + this.repositoryDisposables.clear(); } } diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index f6453d6dc31..bff5a354eab 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -1419,6 +1419,7 @@ class SCMInputWidget extends Disposable { @IKeybindingService private keybindingService: IKeybindingService, @IConfigurationService private configurationService: IConfigurationService, @IInstantiationService instantiationService: IInstantiationService, + @ISCMViewService private readonly scmViewService: ISCMViewService, @IContextViewService private readonly contextViewService: IContextViewService ) { super(); @@ -1466,7 +1467,10 @@ class SCMInputWidget extends Disposable { this._register(this.inputEditor); this._register(this.inputEditor.onDidFocusEditorText(() => { - this.input?.repository.setSelected(true); // TODO@joao: remove + if (this.input?.repository) { + this.scmViewService.focus(this.input.repository); + } + this.editorContainer.classList.add('synthetic-focus'); this.renderValidation(); })); @@ -1838,21 +1842,25 @@ export class SCMViewPane extends ViewPane { private async open(e: IOpenEvent): Promise { if (!e.element) { return; - } else if (isSCMRepository(e.element)) { // TODO@joao: remove - e.element.setSelected(true); + } else if (isSCMRepository(e.element)) { + this.scmViewService.focus(e.element); return; - } else if (isSCMResourceGroup(e.element)) { // TODO@joao: remove + } else if (isSCMResourceGroup(e.element)) { const provider = e.element.provider; const repository = this.scmService.repositories.find(r => r.provider === provider); - repository?.setSelected(true); + if (repository) { + this.scmViewService.focus(repository); + } return; - } else if (ResourceTree.isResourceNode(e.element)) { // TODO@joao: remove + } else if (ResourceTree.isResourceNode(e.element)) { const provider = e.element.context.provider; const repository = this.scmService.repositories.find(r => r.provider === provider); - repository?.setSelected(true); + if (repository) { + this.scmViewService.focus(repository); + } return; } else if (isSCMInput(e.element)) { - e.element.repository.setSelected(true); // TODO@joao: remove + this.scmViewService.focus(e.element.repository); const widget = this.inputRenderer.getRenderedInputWidget(e.element); @@ -1880,10 +1888,12 @@ export class SCMViewPane extends ViewPane { } } - // TODO@joao: remove const provider = e.element.resourceGroup.provider; const repository = this.scmService.repositories.find(r => r.provider === provider); - repository?.setSelected(true); + + if (repository) { + this.scmViewService.focus(repository); + } } private onListContextMenu(e: ITreeContextMenuEvent): void { diff --git a/src/vs/workbench/contrib/scm/browser/scmViewService.ts b/src/vs/workbench/contrib/scm/browser/scmViewService.ts index 1f2609eb975..2704f6a7bbe 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewService.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewService.ts @@ -49,6 +49,10 @@ export class SCMViewService implements ISCMViewService { this._visibleRepositories = visibleRepositories; this._visibleRepositoriesSet = set; this._onDidSetVisibleRepositories.fire({ added, removed }); + + if (this._focusedRepository && removed.has(this._focusedRepository)) { + this.focus(this._visibleRepositories[0]); + } } private _onDidChangeRepositories = new Emitter(); @@ -69,6 +73,15 @@ export class SCMViewService implements ISCMViewService { }, 0) ); + private _focusedRepository: ISCMRepository | undefined; + + get focusedRepository(): ISCMRepository | undefined { + return this._focusedRepository; + } + + private _onDidFocusRepository = new Emitter(); + readonly onDidFocusRepository = this._onDidFocusRepository.event; + constructor( @ISCMService private readonly scmService: ISCMService, @IInstantiationService instantiationService: IInstantiationService @@ -88,6 +101,10 @@ export class SCMViewService implements ISCMViewService { this._visibleRepositoriesSet.add(repository); this._onDidChangeRepositories.fire({ added: [repository], removed: Iterable.empty() }); + + if (!this._focusedRepository) { + this.focus(repository); + } } private onDidRemoveRepository(repository: ISCMRepository): void { @@ -109,6 +126,10 @@ export class SCMViewService implements ISCMViewService { this._onDidChangeRepositories.fire({ added, removed: [repository] }); } + + if (this._focusedRepository === repository) { + this.focus(this._visibleRepositories[0]); + } } isVisible(repository: ISCMRepository): boolean { @@ -136,6 +157,15 @@ export class SCMViewService implements ISCMViewService { } } + focus(repository: ISCMRepository | undefined): void { + if (repository && !this.visibleRepositories.includes(repository)) { + return; + } + + this._focusedRepository = repository; + this._onDidFocusRepository.fire(repository); + } + dispose(): void { this.disposables.dispose(); this._onDidChangeRepositories.dispose(); diff --git a/src/vs/workbench/contrib/scm/browser/util.ts b/src/vs/workbench/contrib/scm/browser/util.ts index 37af180bdee..1c0d1e0e3ad 100644 --- a/src/vs/workbench/contrib/scm/browser/util.ts +++ b/src/vs/workbench/contrib/scm/browser/util.ts @@ -19,7 +19,7 @@ import { Iterable } from 'vs/base/common/iterator'; import { reset } from 'vs/base/browser/dom'; export function isSCMRepository(element: any): element is ISCMRepository { - return !!(element as ISCMRepository).provider && typeof (element as ISCMRepository).setSelected === 'function'; + return !!(element as ISCMRepository).provider && !!(element as ISCMRepository).input; } export function isSCMInput(element: any): element is ISCMInput { diff --git a/src/vs/workbench/contrib/scm/common/scm.ts b/src/vs/workbench/contrib/scm/common/scm.ts index 30813d4c040..7ce0990afb9 100644 --- a/src/vs/workbench/contrib/scm/common/scm.ts +++ b/src/vs/workbench/contrib/scm/common/scm.ts @@ -114,11 +114,8 @@ export interface ISCMInput { } export interface ISCMRepository extends IDisposable { - readonly selected: boolean; - readonly onDidChangeSelection: Event; readonly provider: ISCMProvider; readonly input: ISCMInput; - setSelected(selected: boolean): void; } export interface ISCMService { @@ -168,4 +165,8 @@ export interface ISCMViewService { isVisible(repository: ISCMRepository): boolean; toggleVisibility(repository: ISCMRepository, visible?: boolean): void; + + readonly focusedRepository: ISCMRepository | undefined; + readonly onDidFocusRepository: Event; + focus(repository: ISCMRepository): void; } diff --git a/src/vs/workbench/contrib/scm/common/scmService.ts b/src/vs/workbench/contrib/scm/common/scmService.ts index 14e7a927239..4e8fdf7814a 100644 --- a/src/vs/workbench/contrib/scm/common/scmService.ts +++ b/src/vs/workbench/contrib/scm/common/scmService.ts @@ -185,10 +185,6 @@ export class SCMService implements ISCMService { get repositories(): ISCMRepository[] { return [...this._repositories]; } private providerCount: IContextKey; - private _selectedRepository: ISCMRepository | undefined; - - private readonly _onDidSelectRepository = new Emitter(); - readonly onDidSelectRepository: Event = this._onDidSelectRepository.event; private readonly _onDidAddProvider = new Emitter(); readonly onDidAddRepository: Event = this._onDidAddProvider.event; @@ -220,38 +216,18 @@ export class SCMService implements ISCMService { return; } - selectedDisposable.dispose(); this._providerIds.delete(provider.id); this._repositories.splice(index, 1); this._onDidRemoveProvider.fire(repository); - if (this._selectedRepository === repository) { - this.select(this._repositories[0]); - } - this.providerCount.set(this._repositories.length); }); const repository = new SCMRepository(provider, disposable, this.storageService); - 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); - } - this.providerCount.set(this._repositories.length); return repository; } - - private select(repository: ISCMRepository | undefined): void { - if (this._selectedRepository) { - this._selectedRepository.setSelected(false); - } - - this._selectedRepository = repository; - this._onDidSelectRepository.fire(this._selectedRepository); - } } -- GitLab