Skip to content

Commit 4b9c19a

Browse files
committed
1 parent d430ffd commit 4b9c19a

7 files changed

Lines changed: 68 additions & 84 deletions

File tree

src/vs/workbench/api/browser/mainThreadSCM.ts

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import { URI, UriComponents } from 'vs/base/common/uri';
77
import { Event, Emitter } from 'vs/base/common/event';
88
import { assign } from 'vs/base/common/objects';
9-
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
9+
import { IDisposable, DisposableStore, combinedDisposable } from 'vs/base/common/lifecycle';
1010
import { ISCMService, ISCMRepository, ISCMProvider, ISCMResource, ISCMResourceGroup, ISCMResourceDecorations, IInputValidation } from 'vs/workbench/contrib/scm/common/scm';
1111
import { ExtHostContext, MainThreadSCMShape, ExtHostSCMShape, SCMProviderFeatures, SCMRawResourceSplices, SCMGroupFeatures, MainContext, IExtHostContext } from '../common/extHost.protocol';
1212
import { Command } from 'vs/editor/common/modes';
@@ -264,25 +264,22 @@ export class MainThreadSCM implements MainThreadSCMShape {
264264

265265
private readonly _proxy: ExtHostSCMShape;
266266
private _repositories = new Map<number, ISCMRepository>();
267-
private _inputDisposables = new Map<number, IDisposable>();
267+
private _repositoryDisposables = new Map<number, IDisposable>();
268268
private readonly _disposables = new DisposableStore();
269269

270270
constructor(
271271
extHostContext: IExtHostContext,
272272
@ISCMService private readonly scmService: ISCMService
273273
) {
274274
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostSCM);
275-
276-
Event.debounce(scmService.onDidChangeSelectedRepositories, (_, e) => e, 100)
277-
(this.onDidChangeSelectedRepositories, this, this._disposables);
278275
}
279276

280277
dispose(): void {
281278
this._repositories.forEach(r => r.dispose());
282279
this._repositories.clear();
283280

284-
this._inputDisposables.forEach(d => d.dispose());
285-
this._inputDisposables.clear();
281+
this._repositoryDisposables.forEach(d => d.dispose());
282+
this._repositoryDisposables.clear();
286283

287284
this._disposables.dispose();
288285
}
@@ -292,8 +289,16 @@ export class MainThreadSCM implements MainThreadSCMShape {
292289
const repository = this.scmService.registerSCMProvider(provider);
293290
this._repositories.set(handle, repository);
294291

295-
const inputDisposable = repository.input.onDidChange(value => this._proxy.$onInputBoxValueChange(handle, value));
296-
this._inputDisposables.set(handle, inputDisposable);
292+
const disposable = combinedDisposable(
293+
Event.filter(repository.onDidChangeSelection, selected => selected)(_ => this._proxy.$setSelectedSourceControl(handle)),
294+
repository.input.onDidChange(value => this._proxy.$onInputBoxValueChange(handle, value))
295+
);
296+
297+
if (repository.selected) {
298+
setTimeout(() => this._proxy.$setSelectedSourceControl(handle), 0);
299+
}
300+
301+
this._repositoryDisposables.set(handle, disposable);
297302
}
298303

299304
$updateSourceControl(handle: number, features: SCMProviderFeatures): void {
@@ -314,8 +319,8 @@ export class MainThreadSCM implements MainThreadSCMShape {
314319
return;
315320
}
316321

317-
this._inputDisposables.get(handle)!.dispose();
318-
this._inputDisposables.delete(handle);
322+
this._repositoryDisposables.get(handle)!.dispose();
323+
this._repositoryDisposables.delete(handle);
319324

320325
repository.dispose();
321326
this._repositories.delete(handle);
@@ -422,12 +427,4 @@ export class MainThreadSCM implements MainThreadSCMShape {
422427
repository.input.validateInput = async () => undefined;
423428
}
424429
}
425-
426-
private onDidChangeSelectedRepositories(repositories: ISCMRepository[]): void {
427-
const handles = repositories
428-
.filter(r => r.provider instanceof MainThreadSCMProvider)
429-
.map(r => (r.provider as MainThreadSCMProvider).handle);
430-
431-
this._proxy.$setSelectedSourceControls(handles);
432-
}
433430
}

src/vs/workbench/api/common/extHost.protocol.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1437,7 +1437,7 @@ export interface ExtHostSCMShape {
14371437
$onInputBoxValueChange(sourceControlHandle: number, value: string): void;
14381438
$executeResourceCommand(sourceControlHandle: number, groupHandle: number, handle: number, preserveFocus: boolean): Promise<void>;
14391439
$validateInput(sourceControlHandle: number, value: string, cursorPosition: number): Promise<[string, number] | undefined>;
1440-
$setSelectedSourceControls(selectedSourceControlHandles: number[]): Promise<void>;
1440+
$setSelectedSourceControl(selectedSourceControlHandle: number | undefined): Promise<void>;
14411441
}
14421442

14431443
export interface ExtHostTaskShape {

src/vs/workbench/api/common/extHostSCM.ts

Lines changed: 9 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,7 @@ export class ExtHostSCM implements ExtHostSCMShape {
536536
private readonly _onDidChangeActiveProvider = new Emitter<vscode.SourceControl>();
537537
get onDidChangeActiveProvider(): Event<vscode.SourceControl> { return this._onDidChangeActiveProvider.event; }
538538

539-
private _selectedSourceControlHandles = new Set<number>();
539+
private _selectedSourceControlHandle: number | undefined;
540540

541541
constructor(
542542
mainContext: IMainContext,
@@ -681,40 +681,18 @@ export class ExtHostSCM implements ExtHostSCMShape {
681681
});
682682
}
683683

684-
$setSelectedSourceControls(selectedSourceControlHandles: number[]): Promise<void> {
685-
this.logService.trace('ExtHostSCM#$setSelectedSourceControls', selectedSourceControlHandles);
684+
$setSelectedSourceControl(selectedSourceControlHandle: number | undefined): Promise<void> {
685+
this.logService.trace('ExtHostSCM#$setSelectedSourceControl', selectedSourceControlHandle);
686686

687-
const set = new Set<number>();
688-
689-
for (const handle of selectedSourceControlHandles) {
690-
set.add(handle);
687+
if (selectedSourceControlHandle !== undefined) {
688+
this._sourceControls.get(selectedSourceControlHandle)?.setSelectionState(true);
691689
}
692690

693-
set.forEach(handle => {
694-
if (!this._selectedSourceControlHandles.has(handle)) {
695-
const sourceControl = this._sourceControls.get(handle);
696-
697-
if (!sourceControl) {
698-
return;
699-
}
700-
701-
sourceControl.setSelectionState(true);
702-
}
703-
});
704-
705-
this._selectedSourceControlHandles.forEach(handle => {
706-
if (!set.has(handle)) {
707-
const sourceControl = this._sourceControls.get(handle);
708-
709-
if (!sourceControl) {
710-
return;
711-
}
712-
713-
sourceControl.setSelectionState(false);
714-
}
715-
});
691+
if (this._selectedSourceControlHandle !== undefined) {
692+
this._sourceControls.get(this._selectedSourceControlHandle)?.setSelectionState(false);
693+
}
716694

717-
this._selectedSourceControlHandles = set;
695+
this._selectedSourceControlHandle = selectedSourceControlHandle;
718696
return Promise.resolve(undefined);
719697
}
720698
}

src/vs/workbench/contrib/scm/browser/activity.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export class SCMStatusController implements IWorkbenchContribution {
9292
}
9393

9494
private onDidAddRepository(repository: ISCMRepository): void {
95-
const focusDisposable = repository.onDidFocus(() => this.focusRepository(repository));
95+
const selectedDisposable = Event.filter(repository.onDidChangeSelection, selected => selected)(() => this.focusRepository(repository));
9696

9797
const onDidChange = Event.any(repository.provider.onDidChange, repository.provider.onDidChangeResources);
9898
const changeDisposable = onDidChange(() => this.renderActivityCount());
@@ -104,14 +104,12 @@ export class SCMStatusController implements IWorkbenchContribution {
104104

105105
if (this.scmService.repositories.length === 0) {
106106
this.focusRepository(undefined);
107-
} else if (this.focusedRepository === repository) {
108-
this.scmService.repositories[0].focus();
109107
}
110108

111109
this.renderActivityCount();
112110
});
113111

114-
const disposable = combinedDisposable(focusDisposable, changeDisposable, removeDisposable);
112+
const disposable = combinedDisposable(selectedDisposable, changeDisposable, removeDisposable);
115113
this.disposables.push(disposable);
116114

117115
if (this.focusedRepository) {

src/vs/workbench/contrib/scm/browser/scmViewPane.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1381,6 +1381,7 @@ class SCMInputWidget extends Disposable {
13811381
this._register(this.inputEditor);
13821382

13831383
this._register(this.inputEditor.onDidFocusEditorText(() => {
1384+
this.input?.repository.setSelected(true); // TODO@joao: remove
13841385
addClass(this.editorContainer, 'synthetic-focus');
13851386
this.renderValidation();
13861387
}));
@@ -1665,11 +1666,24 @@ export class SCMViewPane extends ViewPane {
16651666
}
16661667

16671668
private async open(e: IOpenEvent<TreeElement | null>): Promise<void> {
1668-
if (!e.element || isSCMRepository(e.element) || isSCMResourceGroup(e.element) || ResourceTree.isResourceNode(e.element)) {
1669+
if (!e.element) {
16691670
return;
1670-
}
1671+
} else if (isSCMRepository(e.element)) { // TODO@joao: remove
1672+
e.element.setSelected(true);
1673+
return;
1674+
} else if (isSCMResourceGroup(e.element)) { // TODO@joao: remove
1675+
const provider = e.element.provider;
1676+
const repository = this.scmService.repositories.find(r => r.provider === provider);
1677+
repository?.setSelected(true);
1678+
return;
1679+
} else if (ResourceTree.isResourceNode(e.element)) { // TODO@joao: remove
1680+
const provider = e.element.context.provider;
1681+
const repository = this.scmService.repositories.find(r => r.provider === provider);
1682+
repository?.setSelected(true);
1683+
return;
1684+
} else if (isSCMInput(e.element)) {
1685+
e.element.repository.setSelected(true); // TODO@joao: remove
16711686

1672-
if (isSCMInput(e.element)) {
16731687
const widget = this.inputRenderer.getRenderedInputWidget(e.element);
16741688

16751689
if (widget) {
@@ -1685,6 +1699,7 @@ export class SCMViewPane extends ViewPane {
16851699
return;
16861700
}
16871701

1702+
// ISCMResource
16881703
await e.element.open(!!e.editorOptions.preserveFocus);
16891704

16901705
if (e.editorOptions.pinned) {
@@ -1694,6 +1709,11 @@ export class SCMViewPane extends ViewPane {
16941709
activeEditorPane.group.pinEditor(activeEditorPane.input);
16951710
}
16961711
}
1712+
1713+
// TODO@joao: remove
1714+
const provider = e.element.resourceGroup.provider;
1715+
const repository = this.scmService.repositories.find(r => r.provider === provider);
1716+
repository?.setSelected(true);
16971717
}
16981718

16991719
private onListContextMenu(e: ITreeContextMenuEvent<TreeElement | null>): void {

src/vs/workbench/contrib/scm/common/scm.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,10 @@ export interface ISCMInput {
9696
}
9797

9898
export interface ISCMRepository extends IDisposable {
99-
readonly onDidFocus: Event<void>;
10099
readonly selected: boolean;
101100
readonly onDidChangeSelection: Event<boolean>;
102101
readonly provider: ISCMProvider;
103102
readonly input: ISCMInput;
104-
focus(): void;
105103
setSelected(selected: boolean): void;
106104
}
107105

@@ -110,10 +108,7 @@ export interface ISCMService {
110108
readonly _serviceBrand: undefined;
111109
readonly onDidAddRepository: Event<ISCMRepository>;
112110
readonly onDidRemoveRepository: Event<ISCMRepository>;
113-
114111
readonly repositories: ISCMRepository[];
115-
readonly selectedRepositories: ISCMRepository[];
116-
readonly onDidChangeSelectedRepositories: Event<ISCMRepository[]>;
117112

118113
registerSCMProvider(provider: ISCMProvider): ISCMRepository;
119114
}

src/vs/workbench/contrib/scm/common/scmService.ts

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
77
import { Event, Emitter } from 'vs/base/common/event';
88
import { ISCMService, ISCMProvider, ISCMInput, ISCMRepository, IInputValidator } from './scm';
99
import { ILogService } from 'vs/platform/log/common/log';
10-
import { equals } from 'vs/base/common/arrays';
1110

1211
class SCMInput implements ISCMInput {
1312

@@ -76,9 +75,6 @@ class SCMInput implements ISCMInput {
7675

7776
class SCMRepository implements ISCMRepository {
7877

79-
private readonly _onDidFocus = new Emitter<void>();
80-
readonly onDidFocus: Event<void> = this._onDidFocus.event;
81-
8278
private _selected = false;
8379
get selected(): boolean {
8480
return this._selected;
@@ -94,10 +90,6 @@ class SCMRepository implements ISCMRepository {
9490
private disposable: IDisposable
9591
) { }
9692

97-
focus(): void {
98-
this._onDidFocus.fire();
99-
}
100-
10193
setSelected(selected: boolean): void {
10294
if (this._selected === selected) {
10395
return;
@@ -121,11 +113,10 @@ export class SCMService implements ISCMService {
121113
private _repositories: ISCMRepository[] = [];
122114
get repositories(): ISCMRepository[] { return [...this._repositories]; }
123115

124-
private _selectedRepositories: ISCMRepository[] = [];
125-
get selectedRepositories(): ISCMRepository[] { return [...this._selectedRepositories]; }
116+
private _selectedRepository: ISCMRepository | undefined;
126117

127-
private readonly _onDidChangeSelectedRepositories = new Emitter<ISCMRepository[]>();
128-
readonly onDidChangeSelectedRepositories: Event<ISCMRepository[]> = this._onDidChangeSelectedRepositories.event;
118+
private readonly _onDidSelectRepository = new Emitter<ISCMRepository | undefined>();
119+
readonly onDidSelectRepository: Event<ISCMRepository | undefined> = this._onDidSelectRepository.event;
129120

130121
private readonly _onDidAddProvider = new Emitter<ISCMRepository>();
131122
readonly onDidAddRepository: Event<ISCMRepository> = this._onDidAddProvider.event;
@@ -155,26 +146,31 @@ export class SCMService implements ISCMService {
155146
this._providerIds.delete(provider.id);
156147
this._repositories.splice(index, 1);
157148
this._onDidRemoveProvider.fire(repository);
158-
this.onDidChangeSelection();
149+
150+
if (this._selectedRepository === repository) {
151+
this.select(this._repositories[0]);
152+
}
159153
});
160154

161155
const repository = new SCMRepository(provider, disposable);
162-
const selectedDisposable = repository.onDidChangeSelection(this.onDidChangeSelection, this);
156+
const selectedDisposable = Event.map(Event.filter(repository.onDidChangeSelection, selected => selected), _ => repository)(this.select, this);
163157

164158
this._repositories.push(repository);
165159
this._onDidAddProvider.fire(repository);
166160

161+
if (!this._selectedRepository) {
162+
repository.setSelected(true);
163+
}
164+
167165
return repository;
168166
}
169167

170-
private onDidChangeSelection(): void {
171-
const selectedRepositories = this._repositories.filter(r => r.selected);
172-
173-
if (equals(this._selectedRepositories, selectedRepositories)) {
174-
return;
168+
private select(repository: ISCMRepository | undefined): void {
169+
if (this._selectedRepository) {
170+
this._selectedRepository.setSelected(false);
175171
}
176172

177-
this._selectedRepositories = this._repositories.filter(r => r.selected);
178-
this._onDidChangeSelectedRepositories.fire(this.selectedRepositories);
173+
this._selectedRepository = repository;
174+
this._onDidSelectRepository.fire(this._selectedRepository);
179175
}
180176
}

0 commit comments

Comments
 (0)