From 80b83d74d7a35815e818262fafa4b220f6628a3f Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Thu, 23 May 2024 21:59:37 +0200 Subject: [PATCH 1/9] SCM - refactor commands to focus input --- .../contrib/scm/browser/scm.contribution.ts | 29 +++++++- .../contrib/scm/browser/scmViewPane.ts | 72 ++++++++++--------- src/vs/workbench/contrib/scm/browser/util.ts | 8 +++ 3 files changed, 75 insertions(+), 34 deletions(-) diff --git a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts index 70892dfb7991a8..bceac6846e0982 100644 --- a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts +++ b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts @@ -24,7 +24,7 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ModesRegistry } from 'vs/editor/common/languages/modesRegistry'; import { Codicon } from 'vs/base/common/codicons'; import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; -import { SCMViewPane } from 'vs/workbench/contrib/scm/browser/scmViewPane'; +import { ContextKeys, SCMViewPane } from 'vs/workbench/contrib/scm/browser/scmViewPane'; import { SCMViewService } from 'vs/workbench/contrib/scm/browser/scmViewService'; import { SCMRepositoriesViewPane } from 'vs/workbench/contrib/scm/browser/scmRepositoriesViewPane'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; @@ -34,6 +34,7 @@ import { IQuickDiffService } from 'vs/workbench/contrib/scm/common/quickDiff'; import { QuickDiffService } from 'vs/workbench/contrib/scm/common/quickDiffService'; import { getActiveElement } from 'vs/base/browser/dom'; import { SCMWorkingSetController } from 'vs/workbench/contrib/scm/browser/workingSet'; +import { IViewsService } from 'vs/workbench/services/views/common/viewsService'; ModesRegistry.registerLanguage({ id: 'scminput', @@ -475,6 +476,32 @@ MenuRegistry.appendMenuItem(MenuId.SCMSourceControl, { when: ContextKeyExpr.and(ContextKeyExpr.equals('scmProviderHasRootUri', true), ContextKeyExpr.or(ContextKeyExpr.equals('config.terminal.sourceControlRepositoriesKind', 'integrated'), ContextKeyExpr.equals('config.terminal.sourceControlRepositoriesKind', 'both'))) }); +KeybindingsRegistry.registerCommandAndKeybindingRule({ + id: 'workbench.scm.action.focusPreviousInput', + weight: KeybindingWeight.WorkbenchContrib, + when: ContextKeys.RepositoryVisibilityCount.notEqualsTo(0), + handler: async accessor => { + const viewsService = accessor.get(IViewsService); + const scmView = await viewsService.openView(VIEW_PANE_ID); + if (scmView) { + scmView.focusPreviousInput(); + } + } +}); + +KeybindingsRegistry.registerCommandAndKeybindingRule({ + id: 'workbench.scm.action.focusNextInput', + weight: KeybindingWeight.WorkbenchContrib, + when: ContextKeys.RepositoryVisibilityCount.notEqualsTo(0), + handler: async accessor => { + const viewsService = accessor.get(IViewsService); + const scmView = await viewsService.openView(VIEW_PANE_ID); + if (scmView) { + scmView.focusNextInput(); + } + } +}); + registerSingleton(ISCMService, SCMService, InstantiationType.Delayed); registerSingleton(ISCMViewService, SCMViewService, InstantiationType.Delayed); registerSingleton(IQuickDiffService, QuickDiffService, InstantiationType.Delayed); diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index 185aa10316fc5a..c667e52dd1dc0d 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -24,7 +24,7 @@ import { MenuItemAction, IMenuService, registerAction2, MenuId, IAction2Options, import { IAction, ActionRunner, Action, Separator, IActionRunner } from 'vs/base/common/actions'; import { ActionBar, IActionViewItemProvider } from 'vs/base/browser/ui/actionbar/actionbar'; import { IThemeService, IFileIconTheme } from 'vs/platform/theme/common/themeService'; -import { isSCMResource, isSCMResourceGroup, connectPrimaryMenuToInlineActionBar, isSCMRepository, isSCMInput, collectContextMenuActions, getActionViewItemProvider, isSCMActionButton, isSCMViewService, isSCMHistoryItemGroupTreeElement, isSCMHistoryItemTreeElement, isSCMHistoryItemChangeTreeElement, toDiffEditorArguments, isSCMResourceNode, isSCMHistoryItemChangeNode, isSCMViewSeparator, connectPrimaryMenu } from './util'; +import { isSCMResource, isSCMResourceGroup, connectPrimaryMenuToInlineActionBar, isSCMRepository, isSCMInput, collectContextMenuActions, getActionViewItemProvider, isSCMActionButton, isSCMViewService, isSCMHistoryItemGroupTreeElement, isSCMHistoryItemTreeElement, isSCMHistoryItemChangeTreeElement, toDiffEditorArguments, isSCMResourceNode, isSCMHistoryItemChangeNode, isSCMViewSeparator, connectPrimaryMenu, getArrayPreviousIndex, getArrayNextIndex } from './util'; import { WorkbenchCompressibleAsyncDataTree, IOpenEvent } from 'vs/platform/list/browser/listService'; import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { disposableTimeout, Sequencer, ThrottledDelayer, Throttler } from 'vs/base/common/async'; @@ -38,7 +38,7 @@ import { FileKind } from 'vs/platform/files/common/files'; import { compareFileNames, comparePaths } from 'vs/base/common/comparers'; import { FuzzyScore, createMatches, IMatch } from 'vs/base/common/filters'; import { IViewDescriptorService, ViewContainerLocation } from 'vs/workbench/common/views'; -import { localize, localize2 } from 'vs/nls'; +import { localize } from 'vs/nls'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor'; import { SIDE_BAR_BACKGROUND, PANEL_BACKGROUND } from 'vs/workbench/common/theme'; @@ -109,7 +109,6 @@ import { IHoverService } from 'vs/platform/hover/browser/hover'; import { OpenScmGroupAction } from 'vs/workbench/contrib/multiDiffEditor/browser/scmMultiDiffSourceResolver'; import { HoverController } from 'vs/editor/contrib/hover/browser/hoverController'; import { ITextModel } from 'vs/editor/common/model'; -import { IViewsService } from 'vs/workbench/services/views/common/viewsService'; // type SCMResourceTreeNode = IResourceNode; // type SCMHistoryItemChangeResourceTreeNode = IResourceNode; @@ -1462,7 +1461,7 @@ const Menus = { ChangesSettings: new MenuId('SCMChangesSettings'), }; -const ContextKeys = { +export const ContextKeys = { SCMViewMode: new RawContextKey('scmViewMode', ViewMode.List), SCMViewSortKey: new RawContextKey('scmViewSortKey', ViewSortKey.Path), SCMViewAreAllRepositoriesCollapsed: new RawContextKey('scmViewAreAllRepositoriesCollapsed', false), @@ -1958,26 +1957,6 @@ class ExpandAllRepositoriesAction extends ViewAction { registerAction2(CollapseAllRepositoriesAction); registerAction2(ExpandAllRepositoriesAction); -registerAction2(class extends Action2 { - constructor() { - super({ - id: 'workbench.scm.action.focusInput', - title: { ...localize2('focusInput', "Focus Input") }, - category: localize2('source control', "Source Control"), - precondition: ContextKeys.RepositoryCount.notEqualsTo(0), - f1: true - }); - } - - override async run(accessor: ServicesAccessor) { - const viewsService = accessor.get(IViewsService); - const scmView = await viewsService.openView(VIEW_PANE_ID); - if (scmView) { - scmView.focusInput(); - } - } -}); - const enum SCMInputWidgetCommandId { CancelAction = 'scm.input.cancelAction' } @@ -3453,19 +3432,46 @@ export class SCMViewPane extends ViewPane { } } - focusInput(): void { - this.treeOperationSequencer.queue(() => { - return new Promise(resolve => { - if (this.scmViewService.focusedRepository) { - this.tree.reveal(this.scmViewService.focusedRepository.input, 0.5); - this.inputRenderer.getRenderedInputWidget(this.scmViewService.focusedRepository.input)?.focus(); - } + focusPreviousInput(): void { + this.treeOperationSequencer.queue(async () => { + this.focusInput(getArrayPreviousIndex); + }); + } - resolve(); - }); + focusNextInput(): void { + this.treeOperationSequencer.queue(async () => { + this.focusInput(getArrayNextIndex); }); } + private focusInput(getIndex: (index: number, length: number) => number): void { + if (!this.scmViewService.focusedRepository) { + return; + } + + const repositories = this.scmViewService.visibleRepositories; + + let input = this.scmViewService.focusedRepository.input; + let inputWidget = this.inputRenderer.getRenderedInputWidget(input); + + // One visible repository and the input is already focused + if (repositories.length === 1 && inputWidget?.hasFocus() === true) { + return; + } + + // Multiple visible repositories and the input already focused + if (repositories.length > 1 && inputWidget?.hasFocus() === true) { + const repositoryIndex = repositories.indexOf(this.scmViewService.focusedRepository); + const repositoryIndexNew = getIndex(repositoryIndex, repositories.length); + + input = repositories[repositoryIndexNew].input; + inputWidget = this.inputRenderer.getRenderedInputWidget(input); + } + + this.tree.reveal(input); + inputWidget?.focus(); + } + override shouldShowWelcome(): boolean { return this.scmService.repositoryCount === 0; } diff --git a/src/vs/workbench/contrib/scm/browser/util.ts b/src/vs/workbench/contrib/scm/browser/util.ts index 00c333886a6e3a..2bf93462061af0 100644 --- a/src/vs/workbench/contrib/scm/browser/util.ts +++ b/src/vs/workbench/contrib/scm/browser/util.ts @@ -173,3 +173,11 @@ export function getActionViewItemProvider(instaService: IInstantiationService): export function getProviderKey(provider: ISCMProvider): string { return `${provider.contextValue}:${provider.label}${provider.rootUri ? `:${provider.rootUri.toString()}` : ''}`; } + +export function getArrayPreviousIndex(index: number, length: number): number { + return index > 0 ? index - 1 : length - 1; +} + +export function getArrayNextIndex(index: number, length: number): number { + return index < length - 1 ? index + 1 : 0; +} From 5a1a7951b5db9755bffe990154573c5803bc6ba9 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Thu, 23 May 2024 22:08:35 +0200 Subject: [PATCH 2/9] Ensure that the input node is expanded in the tree --- .../contrib/scm/browser/scmViewPane.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index c667e52dd1dc0d..32c0c38b963fe7 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -3434,42 +3434,41 @@ export class SCMViewPane extends ViewPane { focusPreviousInput(): void { this.treeOperationSequencer.queue(async () => { - this.focusInput(getArrayPreviousIndex); + await this.focusInput(getArrayPreviousIndex); }); } focusNextInput(): void { this.treeOperationSequencer.queue(async () => { - this.focusInput(getArrayNextIndex); + await this.focusInput(getArrayNextIndex); }); } - private focusInput(getIndex: (index: number, length: number) => number): void { + private async focusInput(getIndex: (index: number, length: number) => number): Promise { if (!this.scmViewService.focusedRepository) { return; } - const repositories = this.scmViewService.visibleRepositories; - let input = this.scmViewService.focusedRepository.input; - let inputWidget = this.inputRenderer.getRenderedInputWidget(input); + const repositories = this.scmViewService.visibleRepositories; // One visible repository and the input is already focused - if (repositories.length === 1 && inputWidget?.hasFocus() === true) { + if (repositories.length === 1 && this.inputRenderer.getRenderedInputWidget(input)?.hasFocus() === true) { return; } // Multiple visible repositories and the input already focused - if (repositories.length > 1 && inputWidget?.hasFocus() === true) { + if (repositories.length > 1 && this.inputRenderer.getRenderedInputWidget(input)?.hasFocus() === true) { const repositoryIndex = repositories.indexOf(this.scmViewService.focusedRepository); const repositoryIndexNew = getIndex(repositoryIndex, repositories.length); input = repositories[repositoryIndexNew].input; - inputWidget = this.inputRenderer.getRenderedInputWidget(input); } + await this.tree.expandTo(input); + this.tree.reveal(input); - inputWidget?.focus(); + this.inputRenderer.getRenderedInputWidget(input)?.focus(); } override shouldShowWelcome(): boolean { From 7c0c857e694270e13092af03f2b947a27bfc5715 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Thu, 23 May 2024 22:12:08 +0200 Subject: [PATCH 3/9] getParent() should handle expanding the repository node --- src/vs/workbench/contrib/scm/browser/scmViewPane.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index 32c0c38b963fe7..7d4e3d16b090f2 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -3852,6 +3852,8 @@ class SCMTreeDataSource implements IAsyncDataSource Date: Thu, 23 May 2024 22:43:36 +0200 Subject: [PATCH 4/9] Use ArrayNavigator instead --- .../contrib/scm/browser/scmViewPane.ts | 29 +++++++++++++------ src/vs/workbench/contrib/scm/browser/util.ts | 8 ----- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index 7d4e3d16b090f2..a95550dafd75aa 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -24,7 +24,7 @@ import { MenuItemAction, IMenuService, registerAction2, MenuId, IAction2Options, import { IAction, ActionRunner, Action, Separator, IActionRunner } from 'vs/base/common/actions'; import { ActionBar, IActionViewItemProvider } from 'vs/base/browser/ui/actionbar/actionbar'; import { IThemeService, IFileIconTheme } from 'vs/platform/theme/common/themeService'; -import { isSCMResource, isSCMResourceGroup, connectPrimaryMenuToInlineActionBar, isSCMRepository, isSCMInput, collectContextMenuActions, getActionViewItemProvider, isSCMActionButton, isSCMViewService, isSCMHistoryItemGroupTreeElement, isSCMHistoryItemTreeElement, isSCMHistoryItemChangeTreeElement, toDiffEditorArguments, isSCMResourceNode, isSCMHistoryItemChangeNode, isSCMViewSeparator, connectPrimaryMenu, getArrayPreviousIndex, getArrayNextIndex } from './util'; +import { isSCMResource, isSCMResourceGroup, connectPrimaryMenuToInlineActionBar, isSCMRepository, isSCMInput, collectContextMenuActions, getActionViewItemProvider, isSCMActionButton, isSCMViewService, isSCMHistoryItemGroupTreeElement, isSCMHistoryItemTreeElement, isSCMHistoryItemChangeTreeElement, toDiffEditorArguments, isSCMResourceNode, isSCMHistoryItemChangeNode, isSCMViewSeparator, connectPrimaryMenu } from './util'; import { WorkbenchCompressibleAsyncDataTree, IOpenEvent } from 'vs/platform/list/browser/listService'; import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { disposableTimeout, Sequencer, ThrottledDelayer, Throttler } from 'vs/base/common/async'; @@ -109,6 +109,7 @@ import { IHoverService } from 'vs/platform/hover/browser/hover'; import { OpenScmGroupAction } from 'vs/workbench/contrib/multiDiffEditor/browser/scmMultiDiffSourceResolver'; import { HoverController } from 'vs/editor/contrib/hover/browser/hoverController'; import { ITextModel } from 'vs/editor/common/model'; +import { ArrayNavigator } from 'vs/base/common/navigator'; // type SCMResourceTreeNode = IResourceNode; // type SCMHistoryItemChangeResourceTreeNode = IResourceNode; @@ -3434,18 +3435,27 @@ export class SCMViewPane extends ViewPane { focusPreviousInput(): void { this.treeOperationSequencer.queue(async () => { - await this.focusInput(getArrayPreviousIndex); + const getRepository = (items: readonly ISCMRepository[], index: number): ISCMRepository | null => { + return new ArrayNavigator(items, 0, items.length, index).previous(); + }; + + await this.focusInput(getRepository); }); } focusNextInput(): void { this.treeOperationSequencer.queue(async () => { - await this.focusInput(getArrayNextIndex); + const getRepository = (items: readonly ISCMRepository[], index: number): ISCMRepository | null => { + return new ArrayNavigator(items, 0, items.length, index).next(); + }; + + await this.focusInput(getRepository); }); } - private async focusInput(getIndex: (index: number, length: number) => number): Promise { - if (!this.scmViewService.focusedRepository) { + private async focusInput(getRepository: (items: readonly ISCMRepository[], index: number) => ISCMRepository | null): Promise { + if (!this.scmViewService.focusedRepository || + this.scmViewService.visibleRepositories.length === 0) { return; } @@ -3459,10 +3469,11 @@ export class SCMViewPane extends ViewPane { // Multiple visible repositories and the input already focused if (repositories.length > 1 && this.inputRenderer.getRenderedInputWidget(input)?.hasFocus() === true) { - const repositoryIndex = repositories.indexOf(this.scmViewService.focusedRepository); - const repositoryIndexNew = getIndex(repositoryIndex, repositories.length); - - input = repositories[repositoryIndexNew].input; + const focusedRepositoryIndex = repositories.indexOf(this.scmViewService.focusedRepository); + const focusedRepositoryNew = getRepository(repositories, focusedRepositoryIndex); + if (focusedRepositoryNew) { + input = focusedRepositoryNew.input; + } } await this.tree.expandTo(input); diff --git a/src/vs/workbench/contrib/scm/browser/util.ts b/src/vs/workbench/contrib/scm/browser/util.ts index 2bf93462061af0..00c333886a6e3a 100644 --- a/src/vs/workbench/contrib/scm/browser/util.ts +++ b/src/vs/workbench/contrib/scm/browser/util.ts @@ -173,11 +173,3 @@ export function getActionViewItemProvider(instaService: IInstantiationService): export function getProviderKey(provider: ISCMProvider): string { return `${provider.contextValue}:${provider.label}${provider.rootUri ? `:${provider.rootUri.toString()}` : ''}`; } - -export function getArrayPreviousIndex(index: number, length: number): number { - return index > 0 ? index - 1 : length - 1; -} - -export function getArrayNextIndex(index: number, length: number): number { - return index < length - 1 ? index + 1 : 0; -} From a7a8feca2d5d48f553e03f521eed4890b1d78f11 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Thu, 23 May 2024 22:55:48 +0200 Subject: [PATCH 5/9] Add support for looping in the array navigator --- src/vs/base/common/navigator.ts | 9 ++++++++- src/vs/workbench/contrib/scm/browser/scmViewPane.ts | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/vs/base/common/navigator.ts b/src/vs/base/common/navigator.ts index ba7feffef573ab..25ca9cad75105c 100644 --- a/src/vs/base/common/navigator.ts +++ b/src/vs/base/common/navigator.ts @@ -17,7 +17,8 @@ export class ArrayNavigator implements INavigator { private readonly items: readonly T[], protected start: number = 0, protected end: number = items.length, - protected index = start - 1 + protected index: number = start - 1, + protected loop: boolean = false ) { } current(): T | null { @@ -30,11 +31,17 @@ export class ArrayNavigator implements INavigator { next(): T | null { this.index = Math.min(this.index + 1, this.end); + if (this.loop && this.index === this.end) { + this.index = this.start; + } return this.current(); } previous(): T | null { this.index = Math.max(this.index - 1, this.start - 1); + if (this.loop && this.index === this.start - 1) { + this.index = this.end - 1; + } return this.current(); } diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index a95550dafd75aa..34c1d2838ea5cd 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -3436,7 +3436,7 @@ export class SCMViewPane extends ViewPane { focusPreviousInput(): void { this.treeOperationSequencer.queue(async () => { const getRepository = (items: readonly ISCMRepository[], index: number): ISCMRepository | null => { - return new ArrayNavigator(items, 0, items.length, index).previous(); + return new ArrayNavigator(items, 0, items.length, index, true).previous(); }; await this.focusInput(getRepository); @@ -3446,7 +3446,7 @@ export class SCMViewPane extends ViewPane { focusNextInput(): void { this.treeOperationSequencer.queue(async () => { const getRepository = (items: readonly ISCMRepository[], index: number): ISCMRepository | null => { - return new ArrayNavigator(items, 0, items.length, index).next(); + return new ArrayNavigator(items, 0, items.length, index, true).next(); }; await this.focusInput(getRepository); From 09c45f3eddbda9d3e9bd586fb687a8091b105471 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Thu, 23 May 2024 23:12:34 +0200 Subject: [PATCH 6/9] =?UTF-8?q?=F0=9F=92=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/vs/base/common/navigator.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/vs/base/common/navigator.ts b/src/vs/base/common/navigator.ts index 25ca9cad75105c..e00e8d4923963b 100644 --- a/src/vs/base/common/navigator.ts +++ b/src/vs/base/common/navigator.ts @@ -30,18 +30,14 @@ export class ArrayNavigator implements INavigator { } next(): T | null { - this.index = Math.min(this.index + 1, this.end); - if (this.loop && this.index === this.end) { - this.index = this.start; - } + this.index = this.loop && this.index >= this.end - 1 ? + this.start : Math.min(this.index + 1, this.end); return this.current(); } previous(): T | null { - this.index = Math.max(this.index - 1, this.start - 1); - if (this.loop && this.index === this.start - 1) { - this.index = this.end - 1; - } + this.index = this.loop && this.index <= this.start ? + this.end - 1 : Math.max(this.index - 1, this.start - 1); return this.current(); } From ccde0a1acce67e215ae4bfa7799f328e8ae43ea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 24 May 2024 06:20:21 +0200 Subject: [PATCH 7/9] use rot instead of array navigator --- src/vs/base/common/navigator.ts | 9 +++----- .../contrib/scm/browser/scmViewPane.ts | 23 +++++-------------- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/src/vs/base/common/navigator.ts b/src/vs/base/common/navigator.ts index e00e8d4923963b..3e7a781f2d7561 100644 --- a/src/vs/base/common/navigator.ts +++ b/src/vs/base/common/navigator.ts @@ -17,8 +17,7 @@ export class ArrayNavigator implements INavigator { private readonly items: readonly T[], protected start: number = 0, protected end: number = items.length, - protected index: number = start - 1, - protected loop: boolean = false + protected index: number = start - 1 ) { } current(): T | null { @@ -30,14 +29,12 @@ export class ArrayNavigator implements INavigator { } next(): T | null { - this.index = this.loop && this.index >= this.end - 1 ? - this.start : Math.min(this.index + 1, this.end); + this.index = Math.min(this.index + 1, this.end); return this.current(); } previous(): T | null { - this.index = this.loop && this.index <= this.start ? - this.end - 1 : Math.max(this.index - 1, this.start - 1); + this.index = Math.max(this.index - 1, this.start - 1); return this.current(); } diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index 34c1d2838ea5cd..b54314716413ba 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -100,7 +100,7 @@ import { foreground, listActiveSelectionForeground, registerColor, transparent } import { IMenuWorkbenchToolBarOptions, MenuWorkbenchToolBar, WorkbenchToolBar } from 'vs/platform/actions/browser/toolbar'; import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { DropdownWithPrimaryActionViewItem } from 'vs/platform/actions/browser/dropdownWithPrimaryActionViewItem'; -import { clamp } from 'vs/base/common/numbers'; +import { clamp, rot } from 'vs/base/common/numbers'; import { ILogService } from 'vs/platform/log/common/log'; import { getDefaultHoverDelegate } from 'vs/base/browser/ui/hover/hoverDelegateFactory'; import { MarkdownString } from 'vs/base/common/htmlContent'; @@ -109,7 +109,6 @@ import { IHoverService } from 'vs/platform/hover/browser/hover'; import { OpenScmGroupAction } from 'vs/workbench/contrib/multiDiffEditor/browser/scmMultiDiffSourceResolver'; import { HoverController } from 'vs/editor/contrib/hover/browser/hoverController'; import { ITextModel } from 'vs/editor/common/model'; -import { ArrayNavigator } from 'vs/base/common/navigator'; // type SCMResourceTreeNode = IResourceNode; // type SCMHistoryItemChangeResourceTreeNode = IResourceNode; @@ -3435,25 +3434,17 @@ export class SCMViewPane extends ViewPane { focusPreviousInput(): void { this.treeOperationSequencer.queue(async () => { - const getRepository = (items: readonly ISCMRepository[], index: number): ISCMRepository | null => { - return new ArrayNavigator(items, 0, items.length, index, true).previous(); - }; - - await this.focusInput(getRepository); + await this.focusInput(-1); }); } focusNextInput(): void { this.treeOperationSequencer.queue(async () => { - const getRepository = (items: readonly ISCMRepository[], index: number): ISCMRepository | null => { - return new ArrayNavigator(items, 0, items.length, index, true).next(); - }; - - await this.focusInput(getRepository); + await this.focusInput(1); }); } - private async focusInput(getRepository: (items: readonly ISCMRepository[], index: number) => ISCMRepository | null): Promise { + private async focusInput(delta: number): Promise { if (!this.scmViewService.focusedRepository || this.scmViewService.visibleRepositories.length === 0) { return; @@ -3470,10 +3461,8 @@ export class SCMViewPane extends ViewPane { // Multiple visible repositories and the input already focused if (repositories.length > 1 && this.inputRenderer.getRenderedInputWidget(input)?.hasFocus() === true) { const focusedRepositoryIndex = repositories.indexOf(this.scmViewService.focusedRepository); - const focusedRepositoryNew = getRepository(repositories, focusedRepositoryIndex); - if (focusedRepositoryNew) { - input = focusedRepositoryNew.input; - } + const newFocusedRepositoryIndex = rot(focusedRepositoryIndex + delta, repositories.length); + input = repositories[newFocusedRepositoryIndex].input; } await this.tree.expandTo(input); From 2168b53fcd1f72eb2c645c5faf98fc2010b87f01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 24 May 2024 06:21:13 +0200 Subject: [PATCH 8/9] :lipstick: --- src/vs/base/common/navigator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/base/common/navigator.ts b/src/vs/base/common/navigator.ts index 3e7a781f2d7561..ba7feffef573ab 100644 --- a/src/vs/base/common/navigator.ts +++ b/src/vs/base/common/navigator.ts @@ -17,7 +17,7 @@ export class ArrayNavigator implements INavigator { private readonly items: readonly T[], protected start: number = 0, protected end: number = items.length, - protected index: number = start - 1 + protected index = start - 1 ) { } current(): T | null { From 529e481572b4006ef262ee72d3290fbbac8f6160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 24 May 2024 06:22:25 +0200 Subject: [PATCH 9/9] more :lipstick: --- src/vs/workbench/contrib/scm/browser/scmViewPane.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index b54314716413ba..d1f301eda14cf1 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -3433,15 +3433,11 @@ export class SCMViewPane extends ViewPane { } focusPreviousInput(): void { - this.treeOperationSequencer.queue(async () => { - await this.focusInput(-1); - }); + this.treeOperationSequencer.queue(() => this.focusInput(-1)); } focusNextInput(): void { - this.treeOperationSequencer.queue(async () => { - await this.focusInput(1); - }); + this.treeOperationSequencer.queue(() => this.focusInput(1)); } private async focusInput(delta: number): Promise {