fixes #101277
This commit is contained in:
parent
d430ffd9cd
commit
4b9c19ab03
7 changed files with 68 additions and 84 deletions
|
@ -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<number, ISCMRepository>();
|
||||
private _inputDisposables = new Map<number, IDisposable>();
|
||||
private _repositoryDisposables = new Map<number, IDisposable>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1437,7 +1437,7 @@ export interface ExtHostSCMShape {
|
|||
$onInputBoxValueChange(sourceControlHandle: number, value: string): void;
|
||||
$executeResourceCommand(sourceControlHandle: number, groupHandle: number, handle: number, preserveFocus: boolean): Promise<void>;
|
||||
$validateInput(sourceControlHandle: number, value: string, cursorPosition: number): Promise<[string, number] | undefined>;
|
||||
$setSelectedSourceControls(selectedSourceControlHandles: number[]): Promise<void>;
|
||||
$setSelectedSourceControl(selectedSourceControlHandle: number | undefined): Promise<void>;
|
||||
}
|
||||
|
||||
export interface ExtHostTaskShape {
|
||||
|
|
|
@ -536,7 +536,7 @@ export class ExtHostSCM implements ExtHostSCMShape {
|
|||
private readonly _onDidChangeActiveProvider = new Emitter<vscode.SourceControl>();
|
||||
get onDidChangeActiveProvider(): Event<vscode.SourceControl> { return this._onDidChangeActiveProvider.event; }
|
||||
|
||||
private _selectedSourceControlHandles = new Set<number>();
|
||||
private _selectedSourceControlHandle: number | undefined;
|
||||
|
||||
constructor(
|
||||
mainContext: IMainContext,
|
||||
|
@ -681,40 +681,18 @@ export class ExtHostSCM implements ExtHostSCMShape {
|
|||
});
|
||||
}
|
||||
|
||||
$setSelectedSourceControls(selectedSourceControlHandles: number[]): Promise<void> {
|
||||
this.logService.trace('ExtHostSCM#$setSelectedSourceControls', selectedSourceControlHandles);
|
||||
$setSelectedSourceControl(selectedSourceControlHandle: number | undefined): Promise<void> {
|
||||
this.logService.trace('ExtHostSCM#$setSelectedSourceControl', selectedSourceControlHandle);
|
||||
|
||||
const set = new Set<number>();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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<TreeElement | null>): Promise<void> {
|
||||
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<TreeElement | null>): void {
|
||||
|
|
|
@ -96,12 +96,10 @@ export interface ISCMInput {
|
|||
}
|
||||
|
||||
export interface ISCMRepository extends IDisposable {
|
||||
readonly onDidFocus: Event<void>;
|
||||
readonly selected: boolean;
|
||||
readonly onDidChangeSelection: Event<boolean>;
|
||||
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<ISCMRepository>;
|
||||
readonly onDidRemoveRepository: Event<ISCMRepository>;
|
||||
|
||||
readonly repositories: ISCMRepository[];
|
||||
readonly selectedRepositories: ISCMRepository[];
|
||||
readonly onDidChangeSelectedRepositories: Event<ISCMRepository[]>;
|
||||
|
||||
registerSCMProvider(provider: ISCMProvider): ISCMRepository;
|
||||
}
|
||||
|
|
|
@ -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<void>();
|
||||
readonly onDidFocus: Event<void> = 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<ISCMRepository[]>();
|
||||
readonly onDidChangeSelectedRepositories: Event<ISCMRepository[]> = this._onDidChangeSelectedRepositories.event;
|
||||
private readonly _onDidSelectRepository = new Emitter<ISCMRepository | undefined>();
|
||||
readonly onDidSelectRepository: Event<ISCMRepository | undefined> = this._onDidSelectRepository.event;
|
||||
|
||||
private readonly _onDidAddProvider = new Emitter<ISCMRepository>();
|
||||
readonly onDidAddRepository: Event<ISCMRepository> = 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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue