From 2ffd890744f51f3655ac290c3c7aa2bab010ad6a Mon Sep 17 00:00:00 2001 From: gjsjohnmurray Date: Wed, 29 Nov 2023 00:50:26 +0000 Subject: [PATCH 1/5] Preserve sort order when filtering Git branch / tag quickpicks (fix #199471) --- extensions/git/package.json | 3 ++- extensions/git/src/commands.ts | 25 +++++++++++++++---- .../vscode.proposed.quickPickSortByLabel.d.ts | 16 ++++++++++++ 3 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 extensions/git/src/typings/vscode.proposed.quickPickSortByLabel.d.ts diff --git a/extensions/git/package.json b/extensions/git/package.json index c7b3ec1fc96ee..8b25dfa956008 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -26,7 +26,8 @@ "contribMergeEditorMenus", "scmInputBoxActionButton", "scmInputBoxValueProvider", - "contribSourceControlInputBoxMenu" + "contribSourceControlInputBoxMenu", + "quickPickSortByLabel" ], "categories": [ "Other" diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index 3eb213ecea094..ac5ee51e9bdd6 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -2222,6 +2222,7 @@ export class CommandCenter { picks.push(... await createCheckoutItems(repository, opts?.detached)); quickpick.items = picks; quickpick.busy = false; + quickpick.sortByLabel = false; const choice = await new Promise(c => { quickpick.onDidAccept(() => c(quickpick.activeItems[0])); @@ -2410,6 +2411,20 @@ export class CommandCenter { await repository.branch(branchName, true, target); } + private async _unsortedQuickPick(items: Promise, placeHolder: string): Promise { + const quickPick = window.createQuickPick(); + quickPick.placeholder = placeHolder; + quickPick.sortByLabel = false; + quickPick.items = await items; + quickPick.onDidHide(() => quickPick.dispose()); + quickPick.show(); + const choice = await new Promise(resolve => { + quickPick.onDidAccept(() => resolve(quickPick.activeItems[0])); + }); + quickPick.hide(); + return choice; + } + @command('git.deleteBranch', { repository: true }) async deleteBranch(repository: Repository, name: string, force?: boolean): Promise { let run: (force?: boolean) => Promise; @@ -2424,7 +2439,7 @@ export class CommandCenter { }; const placeHolder = l10n.t('Select a branch to delete'); - const choice = await window.showQuickPick(getBranchPicks(), { placeHolder }); + const choice = await this._unsortedQuickPick(getBranchPicks(), placeHolder); if (!choice || !choice.branchName) { return; @@ -2496,7 +2511,7 @@ export class CommandCenter { }; const placeHolder = l10n.t('Select a branch to merge from'); - const choice = await window.showQuickPick(getBranchPicks(), { placeHolder }); + const choice = await this._unsortedQuickPick(getBranchPicks(), placeHolder); if (!choice) { return; @@ -2544,7 +2559,7 @@ export class CommandCenter { }; const placeHolder = l10n.t('Select a branch to rebase onto'); - const choice = await window.showQuickPick(getBranchPicks(), { placeHolder }); + const choice = await this._unsortedQuickPick(getBranchPicks(), placeHolder); if (!choice) { return; @@ -2583,7 +2598,7 @@ export class CommandCenter { }; const placeHolder = l10n.t('Select a tag to delete'); - const choice = await window.showQuickPick(tagPicks(), { placeHolder }); + const choice = await this._unsortedQuickPick(tagPicks(), placeHolder); if (choice && choice instanceof TagItem && choice.ref.name) { await repository.deleteTag(choice.ref.name); @@ -2732,7 +2747,7 @@ export class CommandCenter { }; const branchPlaceHolder = l10n.t('Pick a branch to pull from'); - const branchPick = await window.showQuickPick(getBranchPicks(), { placeHolder: branchPlaceHolder }); + const branchPick = await this._unsortedQuickPick(getBranchPicks(), branchPlaceHolder); if (!branchPick) { return; diff --git a/extensions/git/src/typings/vscode.proposed.quickPickSortByLabel.d.ts b/extensions/git/src/typings/vscode.proposed.quickPickSortByLabel.d.ts new file mode 100644 index 0000000000000..405d67671d78c --- /dev/null +++ b/extensions/git/src/typings/vscode.proposed.quickPickSortByLabel.d.ts @@ -0,0 +1,16 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module 'vscode' { + + // https://github.com/microsoft/vscode/issues/73904 + + export interface QuickPick extends QuickInput { + /** + * An optional flag to sort the final results by index of first query match in label. Defaults to true. + */ + sortByLabel: boolean; + } +} From 47ebf2de1e41df7ba0449ebdb6a8afc0532d5a76 Mon Sep 17 00:00:00 2001 From: gjsjohnmurray Date: Thu, 4 Jan 2024 23:51:01 +0000 Subject: [PATCH 2/5] Fix the merge --- extensions/git/package.json | 2 +- extensions/git/src/commands.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/git/package.json b/extensions/git/package.json index 1f1f723387b04..23b8914ca2ade 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -24,7 +24,7 @@ "tabInputTextMerge", "timeline", "contribMergeEditorMenus", - "contribSourceControlInputBoxMenu" + "contribSourceControlInputBoxMenu", "quickPickSortByLabel" ], "categories": [ diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index 787c6f73aa1fb..b8d4778edbdb9 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -2700,7 +2700,7 @@ export class CommandCenter { }; const placeHolder = l10n.t('Select a branch or tag to merge from'); - const choice = await this._unsortedQuickPick((getQuickPickItems(), placeHolder); + const choice = await this._unsortedQuickPick(getQuickPickItems(), placeHolder); if (choice instanceof MergeItem) { await choice.run(repository); @@ -2722,7 +2722,7 @@ export class CommandCenter { }; const placeHolder = l10n.t('Select a branch to rebase onto'); - const choice = await this._unsortedQuickPick(getQuickPickItems(), placeHolder); + const choice = await this._unsortedQuickPick(getQuickPickItems(), placeHolder); if (choice instanceof RebaseItem) { await choice.run(repository); From 3e44c1f89cb17e7dc28c0f5e348714906b33da8b Mon Sep 17 00:00:00 2001 From: gjsjohnmurray Date: Thu, 11 Jan 2024 18:49:48 +0000 Subject: [PATCH 3/5] Dispose quickpick listeners --- extensions/git/src/commands.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index b8d4778edbdb9..26ef7b5ac08a4 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -2608,14 +2608,18 @@ export class CommandCenter { } private async _unsortedQuickPick(items: Promise, placeHolder: string): Promise { + const listeners: Disposable[] = []; const quickPick = window.createQuickPick(); quickPick.placeholder = placeHolder; quickPick.sortByLabel = false; quickPick.items = await items; - quickPick.onDidHide(() => quickPick.dispose()); + listeners.push(quickPick.onDidHide(() => { + quickPick.dispose(); + listeners.forEach(d => d.dispose()); + })); quickPick.show(); const choice = await new Promise(resolve => { - quickPick.onDidAccept(() => resolve(quickPick.activeItems[0])); + listeners.push(quickPick.onDidAccept(() => resolve(quickPick.activeItems[0]))); }); quickPick.hide(); return choice; From 856b93dd00e14f8fd8ed0ccc622faf01fe939f40 Mon Sep 17 00:00:00 2001 From: gjsjohnmurray Date: Mon, 15 Jan 2024 10:35:38 +0000 Subject: [PATCH 4/5] Changes arising from PR feedback --- extensions/git/src/commands.ts | 12 ++++++------ .../vscode.proposed.quickPickSortByLabel.d.ts | 16 ---------------- extensions/git/tsconfig.json | 1 + 3 files changed, 7 insertions(+), 22 deletions(-) delete mode 100644 extensions/git/src/typings/vscode.proposed.quickPickSortByLabel.d.ts diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index ef92a724bb051..036327e82bdf6 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -2607,7 +2607,7 @@ export class CommandCenter { await repository.branch(branchName, true, target); } - private async _unsortedQuickPick(items: Promise, placeHolder: string): Promise { + private async pickRef(items: Promise, placeHolder: string): Promise { const listeners: Disposable[] = []; const quickPick = window.createQuickPick(); quickPick.placeholder = placeHolder; @@ -2639,7 +2639,7 @@ export class CommandCenter { }; const placeHolder = l10n.t('Select a branch to delete'); - const choice = await this._unsortedQuickPick(getBranchPicks(), placeHolder); + const choice = await this.pickRef(getBranchPicks(), placeHolder); if (!choice || !choice.refName) { return; @@ -2704,7 +2704,7 @@ export class CommandCenter { }; const placeHolder = l10n.t('Select a branch or tag to merge from'); - const choice = await this._unsortedQuickPick(getQuickPickItems(), placeHolder); + const choice = await this.pickRef(getQuickPickItems(), placeHolder); if (choice instanceof MergeItem) { await choice.run(repository); @@ -2726,7 +2726,7 @@ export class CommandCenter { }; const placeHolder = l10n.t('Select a branch to rebase onto'); - const choice = await this._unsortedQuickPick(getQuickPickItems(), placeHolder); + const choice = await this.pickRef(getQuickPickItems(), placeHolder); if (choice instanceof RebaseItem) { await choice.run(repository); @@ -2763,7 +2763,7 @@ export class CommandCenter { }; const placeHolder = l10n.t('Select a tag to delete'); - const choice = await this._unsortedQuickPick(tagPicks(), placeHolder); + const choice = await this.pickRef(tagPicks(), placeHolder); if (choice instanceof TagDeleteItem) { @@ -2912,7 +2912,7 @@ export class CommandCenter { }; const branchPlaceHolder = l10n.t('Pick a branch to pull from'); - const branchPick = await this._unsortedQuickPick(getBranchPicks(), branchPlaceHolder); + const branchPick = await this.pickRef(getBranchPicks(), branchPlaceHolder); if (!branchPick || !branchPick.refName) { return; diff --git a/extensions/git/src/typings/vscode.proposed.quickPickSortByLabel.d.ts b/extensions/git/src/typings/vscode.proposed.quickPickSortByLabel.d.ts deleted file mode 100644 index 405d67671d78c..0000000000000 --- a/extensions/git/src/typings/vscode.proposed.quickPickSortByLabel.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -declare module 'vscode' { - - // https://github.com/microsoft/vscode/issues/73904 - - export interface QuickPick extends QuickInput { - /** - * An optional flag to sort the final results by index of first query match in label. Defaults to true. - */ - sortByLabel: boolean; - } -} diff --git a/extensions/git/tsconfig.json b/extensions/git/tsconfig.json index b9658b046668c..48b9d4227f047 100644 --- a/extensions/git/tsconfig.json +++ b/extensions/git/tsconfig.json @@ -11,6 +11,7 @@ "src/**/*", "../../src/vscode-dts/vscode.d.ts", "../../src/vscode-dts/vscode.proposed.diffCommand.d.ts", + "../../src/vscode-dts/vscode.proposed.quickPickSortByLabel.d.ts", "../../src/vscode-dts/vscode.proposed.scmActionButton.d.ts", "../../src/vscode-dts/vscode.proposed.scmHistoryProvider.d.ts", "../../src/vscode-dts/vscode.proposed.scmSelectedProvider.d.ts", From 1385cea7ae70b3eedd8e1177bb50e452d2e236e6 Mon Sep 17 00:00:00 2001 From: gjsjohnmurray Date: Mon, 15 Jan 2024 11:32:39 +0000 Subject: [PATCH 5/5] Rework listener disposal --- extensions/git/src/commands.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index f9a6c8047238a..2d08c885bfad6 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -2660,15 +2660,13 @@ export class CommandCenter { quickPick.placeholder = placeHolder; quickPick.sortByLabel = false; quickPick.items = await items; - listeners.push(quickPick.onDidHide(() => { - quickPick.dispose(); - listeners.forEach(d => d.dispose()); - })); quickPick.show(); const choice = await new Promise(resolve => { + listeners.push(quickPick.onDidHide(() => resolve(undefined))); listeners.push(quickPick.onDidAccept(() => resolve(quickPick.activeItems[0]))); }); - quickPick.hide(); + quickPick.dispose(); + listeners.forEach(d => d.dispose()); return choice; }