Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SCM - Add commands to focus each resource group #213255

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 57 additions & 2 deletions src/vs/workbench/api/browser/mainThreadSCM.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

import { URI, UriComponents } from 'vs/base/common/uri';
import { Event, Emitter } from 'vs/base/common/event';
import { IDisposable, DisposableStore, combinedDisposable, dispose, Disposable } from 'vs/base/common/lifecycle';
import { ISCMService, ISCMRepository, ISCMProvider, ISCMResource, ISCMResourceGroup, ISCMResourceDecorations, IInputValidation, ISCMViewService, InputValidationType, ISCMActionButtonDescriptor } from 'vs/workbench/contrib/scm/common/scm';
import { IDisposable, DisposableStore, combinedDisposable, dispose, Disposable, ReferenceCollection, DisposableMap, toDisposable } from 'vs/base/common/lifecycle';
import { ISCMService, ISCMRepository, ISCMProvider, ISCMResource, ISCMResourceGroup, ISCMResourceDecorations, IInputValidation, ISCMViewService, InputValidationType, ISCMActionButtonDescriptor, VIEW_PANE_ID } from 'vs/workbench/contrib/scm/common/scm';
import { ExtHostContext, MainThreadSCMShape, ExtHostSCMShape, SCMProviderFeatures, SCMRawResourceSplices, SCMGroupFeatures, MainContext, SCMHistoryItemGroupDto } from '../common/extHost.protocol';
import { Command } from 'vs/editor/common/languages';
import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers';
Expand All @@ -25,6 +25,11 @@ import { IModelService } from 'vs/editor/common/services/model';
import { ITextModelContentProvider, ITextModelService } from 'vs/editor/common/services/resolverService';
import { Schemas } from 'vs/base/common/network';
import { ITextModel } from 'vs/editor/common/model';
import { Action2, registerAction2 } from 'vs/platform/actions/common/actions';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { localize2 } from 'vs/nls';
import { IViewsService } from 'vs/workbench/services/views/common/viewsService';
import { SCMViewPane } from 'vs/workbench/contrib/scm/browser/scmViewPane';

function getIconFromIconDto(iconDto?: UriComponents | { light: UriComponents; dark: UriComponents } | ThemeIcon): URI | { light: URI; dark: URI } | ThemeIcon | undefined {
if (iconDto === undefined) {
Expand Down Expand Up @@ -58,6 +63,33 @@ class SCMInputBoxContentProvider extends Disposable implements ITextModelContent
}
}

class SCMResourceGroupActionReferenceCollection extends ReferenceCollection<IDisposable> {
protected override createReferencedObject(key: string, ...args: any[]): IDisposable {
return registerAction2(class extends Action2 {
constructor() {
super({
id: `workbench.scm.action.resourceGroup.focus.${key}`,
title: { ...localize2('focusResourceGroup', "Focus on {0} Source Control Resource Group", args[0] as string) },
category: localize2('source control', "Source Control"),
f1: true
});
}

override async run(accessor: ServicesAccessor) {
const viewsService = accessor.get(IViewsService);
const scmView = await viewsService.openView<SCMViewPane>(VIEW_PANE_ID);
if (scmView) {
scmView.focusResourceGroup(key);
}
}
});
}

protected override destroyReferencedObject(key: string, object: IDisposable): void {
object.dispose();
}
}

class MainThreadSCMResourceGroup implements ISCMResourceGroup {

readonly resources: ISCMResource[] = [];
Expand Down Expand Up @@ -443,6 +475,8 @@ export class MainThreadSCM implements MainThreadSCMShape {
private readonly _proxy: ExtHostSCMShape;
private _repositories = new Map<number, ISCMRepository>();
private _repositoryDisposables = new Map<number, IDisposable>();
private _resourceGroupActions = new SCMResourceGroupActionReferenceCollection();
private _resourceGroupDisposables = new Map<number, DisposableMap<number>>();
private readonly _disposables = new DisposableStore();

constructor(
Expand Down Expand Up @@ -494,6 +528,7 @@ export class MainThreadSCM implements MainThreadSCMShape {
}

this._repositoryDisposables.set(handle, disposable);
this._resourceGroupDisposables.set(handle, new DisposableMap<number>());
}

$updateSourceControl(handle: number, features: SCMProviderFeatures): void {
Expand All @@ -514,6 +549,9 @@ export class MainThreadSCM implements MainThreadSCMShape {
return;
}

this._resourceGroupDisposables.get(handle)!.dispose();
this._resourceGroupDisposables.delete(handle);

this._repositoryDisposables.get(handle)!.dispose();
this._repositoryDisposables.delete(handle);

Expand All @@ -531,6 +569,16 @@ export class MainThreadSCM implements MainThreadSCMShape {
const provider = repository.provider as MainThreadSCMProvider;
provider.$registerGroups(groups);
provider.$spliceGroupResourceStates(splices);

const resourceGroupDisposables = this._resourceGroupDisposables.get(sourceControlHandle);
if (!resourceGroupDisposables) {
return;
}

for (const group of groups) {
const ref = this._resourceGroupActions.acquire(group[1], group[2]);
resourceGroupDisposables.set(group[0], toDisposable(ref.dispose));
}
}

$updateGroup(sourceControlHandle: number, groupHandle: number, features: SCMGroupFeatures): void {
Expand Down Expand Up @@ -575,6 +623,13 @@ export class MainThreadSCM implements MainThreadSCMShape {

const provider = repository.provider as MainThreadSCMProvider;
provider.$unregisterGroup(handle);

const resourceGroupDisposables = this._resourceGroupDisposables.get(sourceControlHandle);
if (!resourceGroupDisposables) {
return;
}

resourceGroupDisposables.deleteAndDispose(handle);
}

$setInputBoxValue(sourceControlHandle: number, value: string): void {
Expand Down
21 changes: 20 additions & 1 deletion src/vs/workbench/contrib/scm/browser/scmViewPane.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1962,7 +1962,7 @@ registerAction2(class extends Action2 {
constructor() {
super({
id: 'workbench.scm.action.focusInput',
title: { ...localize2('focusInput', "Focus Input") },
title: { ...localize2('focusInput', "Focus on Source Control Input") },
category: localize2('source control', "Source Control"),
precondition: ContextKeys.RepositoryCount.notEqualsTo(0),
f1: true
Expand Down Expand Up @@ -3466,6 +3466,25 @@ export class SCMViewPane extends ViewPane {
});
}

focusResourceGroup(id: string): void {
this.treeOperationSequencer.queue(() => {
return new Promise<void>(resolve => {
if (this.scmViewService.focusedRepository) {
const resourceGroup = this.scmViewService.focusedRepository.provider.groups.find(g => g.id === id);
if (resourceGroup && this.tree.hasElement(resourceGroup)) {
this.tree.reveal(resourceGroup, 0.5);

this.tree.setSelection([resourceGroup]);
this.tree.setFocus([resourceGroup]);
this.tree.domFocus();
}
}

resolve();
});
});
}

override shouldShowWelcome(): boolean {
return this.scmService.repositoryCount === 0;
}
Expand Down
Loading