From 83bf8323e2ff721567b1d215c7eb0a4335b0d340 Mon Sep 17 00:00:00 2001 From: afiqzudinhadi Date: Wed, 5 Aug 2026 19:11:53 +0800 Subject: [PATCH] =?UTF-8?q?fix(library):=20picker=20choice=20lost=20?= =?UTF-8?q?=E2=80=94=20Obsidian=20close()=20precedes=20onChooseItem,=20def?= =?UTF-8?q?er=20dismiss-settle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/obsidian/src/library/CandidatePickerModal.ts | 5 ++++- tests/library-candidate-picker-modal.test.ts | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/obsidian/src/library/CandidatePickerModal.ts b/packages/obsidian/src/library/CandidatePickerModal.ts index 0daab33..063d195 100644 --- a/packages/obsidian/src/library/CandidatePickerModal.ts +++ b/packages/obsidian/src/library/CandidatePickerModal.ts @@ -55,7 +55,10 @@ export class CandidatePickerModal extends FuzzySuggestModal { } onClose(): void { - this.settle(null); // dismissed without choosing -> treat as skip + // Obsidian's selectSuggestion() calls close() BEFORE onChooseItem(), so settling here + // synchronously would discard a real choice. Defer one tick: a choice made in the same + // tick settles first and this becomes a no-op; a genuine dismissal settles as skip. + window.setTimeout(() => this.settle(null), 0); this.contentEl.empty(); } diff --git a/tests/library-candidate-picker-modal.test.ts b/tests/library-candidate-picker-modal.test.ts index 7f5f5a1..b59988a 100644 --- a/tests/library-candidate-picker-modal.test.ts +++ b/tests/library-candidate-picker-modal.test.ts @@ -117,4 +117,13 @@ describe('CandidatePickerModal', () => { modal.onClose(); // Obsidian calls onClose() after a choice too -- must not clobber the resolved value expect(await result).toBe(0); }); + + test('REAL Obsidian order — close() fires BEFORE onChooseItem: choice still wins over dismiss-skip', async () => { + const modal = new CandidatePickerModal(fakeApp(), 'Some Note.md', CANDIDATES); + const result = modal.pick(); + // selectSuggestion() in Obsidian calls close() (→ onClose) first, THEN onChooseItem + modal.onClose(); + modal.onChooseItem({ label: 'Foo (2020)', index: 0 }, {} as MouseEvent); + expect(await result).toBe(0); + }); });