From 8daa90bba9a98885a3582b57bd3794c79b395368 Mon Sep 17 00:00:00 2001 From: ronzulu <75528127+ronzulu@users.noreply.github.com> Date: Sun, 1 Oct 2023 22:33:08 +1100 Subject: [PATCH] In flashcard modal, allow user to click across entire tree item rectangle https://github.com/st3v3nmw/obsidian-spaced-repetition/issues/709 --- src/gui/flashcard-modal.tsx | 19 +- tests/unit/FlashcardReviewSequencer.test.ts | 458 +++++++++++--------- 2 files changed, 259 insertions(+), 218 deletions(-) diff --git a/src/gui/flashcard-modal.tsx b/src/gui/flashcard-modal.tsx index 92787b1d..c32f2e80 100644 --- a/src/gui/flashcard-modal.tsx +++ b/src/gui/flashcard-modal.tsx @@ -183,7 +183,6 @@ export class FlashcardModal extends Modal { renderDeck(deck: Deck, containerEl: HTMLElement, modal: FlashcardModal): void { const deckView: HTMLElement = containerEl.createDiv("tree-item"); - // console.log(`renderDeck3: ${deck.deckName}`); const deckViewSelf: HTMLElement = deckView.createDiv( "tree-item-self tag-pane-tag is-clickable", @@ -200,10 +199,6 @@ export class FlashcardModal extends Modal { } const deckViewInner: HTMLElement = deckViewSelf.createDiv("tree-item-inner"); - deckViewInner.addEventListener("click", () => { - /* modal.plugin.data.historyDeck = deck.deckName; */ - this.startReviewOfDeck(deck); - }); const deckViewInnerText: HTMLElement = deckViewInner.createDiv("tag-pane-tag-text"); deckViewInnerText.innerHTML += {deck.deckName}; const deckViewOuter: HTMLElement = deckViewSelf.createDiv("tree-item-flair-outer"); @@ -234,7 +229,7 @@ export class FlashcardModal extends Modal { const deckViewChildren: HTMLElement = deckView.createDiv("tree-item-children"); deckViewChildren.style.display = collapsed ? "none" : "block"; if (deck.subdecks.length > 0) { - collapseIconEl.addEventListener("click", () => { + collapseIconEl.addEventListener("click", (e) => { if (collapsed) { (collapseIconEl.childNodes[0] as HTMLElement).style.transform = ""; deckViewChildren.style.display = "block"; @@ -243,9 +238,21 @@ export class FlashcardModal extends Modal { "rotate(-90deg)"; deckViewChildren.style.display = "none"; } + + // We stop the propagation of the event so that the click event for deckViewSelf doesn't get called + // if the user clicks on the collapse icon + e.stopPropagation(); collapsed = !collapsed; }); } + + // Add the click handler to deckViewSelf instead of deckViewInner so that it activates + // over the entire rectangle of the tree item, not just the text of the topic name + // https://github.com/st3v3nmw/obsidian-spaced-repetition/issues/709 + deckViewSelf.addEventListener("click", () => { + this.startReviewOfDeck(deck); + }); + for (const subdeck of deck.subdecks) { this.renderDeck(subdeck, deckViewChildren, modal); } diff --git a/tests/unit/FlashcardReviewSequencer.test.ts b/tests/unit/FlashcardReviewSequencer.test.ts index d2c90e0f..7bfc6f92 100644 --- a/tests/unit/FlashcardReviewSequencer.test.ts +++ b/tests/unit/FlashcardReviewSequencer.test.ts @@ -498,263 +498,297 @@ describe("processReview", () => { describe("updateCurrentQuestionText", () => { let space: string = " "; - describe("Single line card type; Settings - schedule on following line", () => { - test("Question has schedule on following line before/after update", async () => { - let text: string = ` -#flashcards Q1::A1 + describe("Checking update to file", () => { -#flashcards Q2::A2 - + describe("Single line card type; Settings - schedule on following line", () => { + test("Question has schedule on following line before/after update", async () => { + let text: string = ` + #flashcards Q1::A1 -#flashcards Q3::A3`; + #flashcards Q2::A2 + - let updatedQ: string = "A much more in depth question::A much more detailed answer"; - let originalStr: string = `#flashcards Q2::A2 -`; - let updatedStr: string = `#flashcards A much more in depth question::A much more detailed answer -`; - await checkUpdateCurrentQuestionText( - text, - updatedQ, - originalStr, - updatedStr, - DEFAULT_SETTINGS, - ); - }); + #flashcards Q3::A3`; - test("Question has schedule on same line (but pushed to following line due to settings)", async () => { - let text: string = ` -#flashcards Q1::A1 + let updatedQ: string = "A much more in depth question::A much more detailed answer"; + let originalStr: string = `#flashcards Q2::A2 + `; + let updatedStr: string = `#flashcards A much more in depth question::A much more detailed answer + `; + await checkUpdateCurrentQuestionText( + text, + updatedQ, + originalStr, + updatedStr, + DEFAULT_SETTINGS, + ); + }); -#flashcards Q2::A2 + test("Question has schedule on same line (but pushed to following line due to settings)", async () => { + let text: string = ` + #flashcards Q1::A1 -#flashcards Q3::A3`; + #flashcards Q2::A2 + + #flashcards Q3::A3`; - let updatedQ: string = "A much more in depth question::A much more detailed answer"; - let originalStr: string = `#flashcards Q2::A2 `; - let expectedUpdatedStr: string = `#flashcards A much more in depth question::A much more detailed answer -`; - await checkUpdateCurrentQuestionText( - text, - updatedQ, - originalStr, - expectedUpdatedStr, - DEFAULT_SETTINGS, - ); + let updatedQ: string = "A much more in depth question::A much more detailed answer"; + let originalStr: string = `#flashcards Q2::A2 `; + let expectedUpdatedStr: string = `#flashcards A much more in depth question::A much more detailed answer + `; + await checkUpdateCurrentQuestionText( + text, + updatedQ, + originalStr, + expectedUpdatedStr, + DEFAULT_SETTINGS, + ); + }); }); - }); - describe("Single line card type; Settings - schedule on same line", () => { - let settings: SRSettings = { ...DEFAULT_SETTINGS }; - settings.cardCommentOnSameLine = true; + describe("Single line card type; Settings - schedule on same line", () => { + let settings: SRSettings = { ...DEFAULT_SETTINGS }; + settings.cardCommentOnSameLine = true; - test("Question has schedule on same line before/after", async () => { - let text1: string = ` -#flashcards Q1::A1 + test("Question has schedule on same line before/after", async () => { + let text1: string = ` + #flashcards Q1::A1 -#flashcards Q2::A2 + #flashcards Q2::A2 -#flashcards Q3::A3`; + #flashcards Q3::A3`; - let updatedQ: string = "A much more in depth question::A much more detailed answer"; - let originalStr: string = `#flashcards Q2::A2 `; - let updatedStr: string = `#flashcards A much more in depth question::A much more detailed answer `; - await checkUpdateCurrentQuestionText( - text1, - updatedQ, - originalStr, - updatedStr, - settings, - ); - }); + let updatedQ: string = "A much more in depth question::A much more detailed answer"; + let originalStr: string = `#flashcards Q2::A2 `; + let updatedStr: string = `#flashcards A much more in depth question::A much more detailed answer `; + await checkUpdateCurrentQuestionText( + text1, + updatedQ, + originalStr, + updatedStr, + settings, + ); + }); - test("Question has schedule on following line (but placed on same line due to settings)", async () => { - let text: string = ` -#flashcards Q1::A1 + test("Question has schedule on following line (but placed on same line due to settings)", async () => { + let text: string = ` + #flashcards Q1::A1 -#flashcards Q2::A2 - + #flashcards Q2::A2 + -#flashcards Q3::A3`; + #flashcards Q3::A3`; - let updatedQ: string = "A much more in depth question::A much more detailed answer"; - let originalStr: string = `#flashcards Q2::A2 -`; - let updatedStr: string = `#flashcards A much more in depth question::A much more detailed answer `; - await checkUpdateCurrentQuestionText(text, updatedQ, originalStr, updatedStr, settings); + let updatedQ: string = "A much more in depth question::A much more detailed answer"; + let originalStr: string = `#flashcards Q2::A2 + `; + let updatedStr: string = `#flashcards A much more in depth question::A much more detailed answer `; + await checkUpdateCurrentQuestionText(text, updatedQ, originalStr, updatedStr, settings); + }); }); - }); - describe("Multiline card type; Settings - schedule on following line", () => { - test("Question starts immediately after tag; Existing schedule present", async () => { - let originalStr: string = `Q2 -? -A2 -`; + describe("Multiline card type; Settings - schedule on following line", () => { + test("Question starts immediately after tag; Existing schedule present", async () => { + let originalStr: string = `Q2 + ? + A2 + `; - let text: string = ` -#flashcards Q1::A1 + let text: string = ` + #flashcards Q1::A1 -#flashcards ${originalStr} + #flashcards ${originalStr} -#flashcards Q3::A3`; + #flashcards Q3::A3`; - let updatedQ: string = `Multiline question -Question starting immediately after tag -? -A2 (answer now includes more detail) -extra answer line 2`; - - let expectedUpdatedStr: string = `Multiline question -Question starting immediately after tag -? -A2 (answer now includes more detail) -extra answer line 2 -`; - - await checkUpdateCurrentQuestionText( - text, - updatedQ, - originalStr, - expectedUpdatedStr, - DEFAULT_SETTINGS, - ); - }); + let updatedQ: string = `Multiline question + Question starting immediately after tag + ? + A2 (answer now includes more detail) + extra answer line 2`; - test("Question starts on same line as tag (after two spaces); Existing schedule present", async () => { - let originalStr: string = `Q2 -? -A2 -`; + let expectedUpdatedStr: string = `Multiline question + Question starting immediately after tag + ? + A2 (answer now includes more detail) + extra answer line 2 + `; - let text: string = ` -#flashcards Q1::A1 + await checkUpdateCurrentQuestionText( + text, + updatedQ, + originalStr, + expectedUpdatedStr, + DEFAULT_SETTINGS, + ); + }); -#flashcards${space}${space}${originalStr} + test("Question starts on same line as tag (after two spaces); Existing schedule present", async () => { + let originalStr: string = `Q2 + ? + A2 + `; -#flashcards Q3::A3`; + let text: string = ` + #flashcards Q1::A1 - let updatedQ: string = `Multiline question -Question starting immediately after tag -? -A2 (answer now includes more detail) -extra answer line 2`; - - let expectedUpdatedStr: string = `Multiline question -Question starting immediately after tag -? -A2 (answer now includes more detail) -extra answer line 2 -`; - - await checkUpdateCurrentQuestionText( - text, - updatedQ, - originalStr, - expectedUpdatedStr, - DEFAULT_SETTINGS, - ); - }); + #flashcards${space}${space}${originalStr} - test("Question starts line after tag; Existing schedule present", async () => { - let originalStr: string = `#flashcards -Q2 -? -A2 -`; + #flashcards Q3::A3`; - let text: string = ` -#flashcards Q1::A1 + let updatedQ: string = `Multiline question + Question starting immediately after tag + ? + A2 (answer now includes more detail) + extra answer line 2`; -${originalStr} + let expectedUpdatedStr: string = `Multiline question + Question starting immediately after tag + ? + A2 (answer now includes more detail) + extra answer line 2 + `; -#flashcards Q3::A3`; + await checkUpdateCurrentQuestionText( + text, + updatedQ, + originalStr, + expectedUpdatedStr, + DEFAULT_SETTINGS, + ); + }); - let updatedQ: string = `Multiline question -Question starting line after tag -? -A2 (answer now includes more detail) -extra answer line 2`; - - let expectedUpdatedStr: string = `#flashcards -Multiline question -Question starting line after tag -? -A2 (answer now includes more detail) -extra answer line 2 -`; - - await checkUpdateCurrentQuestionText( - text, - updatedQ, - originalStr, - expectedUpdatedStr, - DEFAULT_SETTINGS, - ); - }); + test("Question starts line after tag; Existing schedule present", async () => { + let originalStr: string = `#flashcards + Q2 + ? + A2 + `; - test("Question starts line after tag (no white space after tag); New card", async () => { - let originalQuestionStr: string = `#flashcards -Q2 -? -A2`; + let text: string = ` + #flashcards Q1::A1 - let fileText: string = ` -${originalQuestionStr} + ${originalStr} -#flashcards Q1::A1 + #flashcards Q3::A3`; -#flashcards Q3::A3`; + let updatedQ: string = `Multiline question + Question starting line after tag + ? + A2 (answer now includes more detail) + extra answer line 2`; - let updatedQuestionText: string = `Multiline question -Question starting immediately after tag -? -A2 (answer now includes more detail) -extra answer line 2`; - - let expectedUpdatedStr: string = `#flashcards -${updatedQuestionText}`; - - await checkUpdateCurrentQuestionText( - fileText, - updatedQuestionText, - originalQuestionStr, - expectedUpdatedStr, - DEFAULT_SETTINGS, - ); - }); + let expectedUpdatedStr: string = `#flashcards + Multiline question + Question starting line after tag + ? + A2 (answer now includes more detail) + extra answer line 2 + `; + + await checkUpdateCurrentQuestionText( + text, + updatedQ, + originalStr, + expectedUpdatedStr, + DEFAULT_SETTINGS, + ); + }); - test("Question starts line after tag (single space after tag before newline); New card", async () => { - let originalQuestionStr: string = `#flashcards${space} -Q2 -? -A2`; + test("Question starts line after tag (no white space after tag); New card", async () => { + let originalQuestionStr: string = `#flashcards + Q2 + ? + A2`; - let fileText: string = ` -${originalQuestionStr} + let fileText: string = ` + ${originalQuestionStr} -#flashcards Q1::A1 + #flashcards Q1::A1 -#flashcards Q3::A3`; + #flashcards Q3::A3`; + + let updatedQuestionText: string = `Multiline question + Question starting immediately after tag + ? + A2 (answer now includes more detail) + extra answer line 2`; + + let expectedUpdatedStr: string = `#flashcards + ${updatedQuestionText}`; + + await checkUpdateCurrentQuestionText( + fileText, + updatedQuestionText, + originalQuestionStr, + expectedUpdatedStr, + DEFAULT_SETTINGS, + ); + }); + + test("Question starts line after tag (single space after tag before newline); New card", async () => { + let originalQuestionStr: string = `#flashcards${space} + Q2 + ? + A2`; - let updatedQuestionText: string = `Multiline question -Question starting immediately after tag -? -A2 (answer now includes more detail) -extra answer line 2`; - - let expectedUpdatedStr: string = `#flashcards -${updatedQuestionText}`; - - await checkUpdateCurrentQuestionText( - fileText, - updatedQuestionText, - originalQuestionStr, - expectedUpdatedStr, - DEFAULT_SETTINGS, - ); + let fileText: string = ` + ${originalQuestionStr} + + #flashcards Q1::A1 + + #flashcards Q3::A3`; + + let updatedQuestionText: string = `Multiline question + Question starting immediately after tag + ? + A2 (answer now includes more detail) + extra answer line 2`; + + let expectedUpdatedStr: string = `#flashcards + ${updatedQuestionText}`; + + await checkUpdateCurrentQuestionText( + fileText, + updatedQuestionText, + originalQuestionStr, + expectedUpdatedStr, + DEFAULT_SETTINGS, + ); + }); }); }); + + test("Checking updates to the current card", () => { + let originalQuestionStr: string = `#flashcards + Q2 + ? + A2`; + + let fileText: string = ` + ${originalQuestionStr} + + #flashcards Q1::A1 + + #flashcards Q3::A3`; + + let updatedQuestionText: string = `Multiline question + Question starting immediately after tag + ? + A2 (answer now includes more detail) + extra answer line 2`; + + let expectedUpdatedStr: string = `#flashcards + ${updatedQuestionText}`; + + await checkUpdateCurrentQuestionText( + fileText, + updatedQuestionText, + originalQuestionStr, + expectedUpdatedStr, + DEFAULT_SETTINGS, + ); + }); }); describe("Sequences", () => {