|
function renderScheduledFooter(view: WidgetViewLike, footer: HTMLElement, card: CardRecord, graded: { rating: ReviewRating; at: number; meta: ReviewMeta | null } | null, ioLike: boolean) { |
|
// Reveal button (for basic/cloze when hidden) |
|
if ((card.type === "basic" || card.type === "reversed" || card.type === "reversed-child" || card.type === "combo-child" || isClozeLike(card) || ioLike) && !view.showAnswer && !graded) { |
|
const revealBtn = makeTextButton({ |
|
label: tx(view, "ui.widget.revealAnswer", "Reveal Answer"), |
|
title: "Reveal answer", |
|
className: "learnkit-btn-toolbar sprout-widget-btn sprout-widget-btn-full", |
|
onClick: () => { |
|
view.showAnswer = true; |
|
view.render(); |
|
view.containerEl.focus(); |
|
}, |
|
kbd: "↵", |
|
}); |
|
applyWidgetActionButtonStyles(revealBtn); |
|
footer.appendChild(revealBtn); |
|
} |
|
|
|
// Grading buttons row – 2×2 grid layout (Again+Hard, Good+Easy) |
|
if (!graded) { |
|
if ((card.type === "basic" || card.type === "reversed" || card.type === "reversed-child" || card.type === "combo-child" || isClozeLike(card) || ioLike) && view.showAnswer) { |
|
const fourButton = !!view.plugin.settings.study.fourButtonMode; |
|
const showIntervals = !!view.plugin.settings.study.showGradeIntervals; |
|
const previewNow = Date.now(); |
|
const previewState = showIntervals |
|
? view.plugin.store.ensureState(String(card.id), previewNow) |
|
: null; |
|
const getSubtitle = (rating: ReviewRating): string | undefined => { |
|
if (!previewState || !showIntervals) return undefined; |
|
return ( |
|
getRatingIntervalPreview({ |
|
state: previewState, |
|
rating, |
|
now: previewNow, |
|
scheduling: view.plugin.settings.scheduling, |
|
}) ?? undefined |
|
); |
|
}; |
|
let gradingGrid: HTMLElement; |
|
if (fourButton) { |
|
gradingGrid = el("div", "sprout-widget-grading-grid"); |
|
} else { |
|
gradingGrid = el("div", "sprout-widget-grading-row"); |
|
} |
|
|
|
// Always show Again |
|
const againBtn = makeTextButton({ |
|
label: tx(view, "ui.widget.grade.again", "Again"), |
|
subtitle: getSubtitle("again"), |
|
title: tx(view, "ui.widget.grade.againTooltip", "Not recalled easily (1)"), |
|
className: fourButton |
|
? "learnkit-btn-toolbar sprout-widget-btn sprout-widget-btn-full" |
|
: "learnkit-btn-toolbar sprout-widget-btn sprout-widget-btn-half", |
|
onClick: () => { |
|
void (async () => { |
|
await view.gradeCurrentRating("again", {}); |
|
view.render(); |
|
})(); |
|
}, |
|
kbd: fourButton ? "1" : "1", |
|
}); |
|
applyWidgetActionButtonStyles(againBtn); |
|
gradingGrid.appendChild(againBtn); |
|
|
|
if (fourButton) { |
|
const hardBtn = makeTextButton({ |
|
label: tx(view, "ui.widget.grade.hard", "Hard"), |
|
subtitle: getSubtitle("hard"), |
|
title: tx(view, "ui.widget.grade.hardTooltip", "Recalled with difficulty (2)"), |
|
className: "learnkit-btn-toolbar sprout-widget-btn sprout-widget-btn-full", |
|
onClick: () => { |
|
void (async () => { |
|
await view.gradeCurrentRating("hard", {}); |
|
view.render(); |
|
})(); |
|
}, |
|
kbd: "2", |
|
}); |
|
applyWidgetActionButtonStyles(hardBtn); |
|
gradingGrid.appendChild(hardBtn); |
|
} |
|
|
|
// Always show Good |
|
const goodBtn = makeTextButton({ |
|
label: tx(view, "ui.widget.grade.good", "Good"), |
|
subtitle: getSubtitle("good"), |
|
title: fourButton |
|
? tx(view, "ui.widget.grade.goodTooltipFour", "Recalled with effort (3)") |
|
: tx(view, "ui.widget.grade.goodTooltipTwo", "Recalled easily (2)"), |
|
className: fourButton |
|
? "learnkit-btn-toolbar sprout-widget-btn sprout-widget-btn-full" |
|
: "learnkit-btn-toolbar sprout-widget-btn sprout-widget-btn-half", |
|
onClick: () => { |
|
void (async () => { |
|
await view.gradeCurrentRating("good", {}); |
|
view.render(); |
|
})(); |
|
}, |
|
kbd: fourButton ? "3" : "2", |
|
}); |
|
applyWidgetActionButtonStyles(goodBtn); |
|
gradingGrid.appendChild(goodBtn); |
|
|
|
if (fourButton) { |
|
const easyBtn = makeTextButton({ |
|
label: tx(view, "ui.widget.grade.easy", "Easy"), |
|
subtitle: getSubtitle("easy"), |
|
title: tx(view, "ui.widget.grade.easyTooltip", "Recalled easily (4)"), |
|
className: "learnkit-btn-toolbar sprout-widget-btn sprout-widget-btn-full", |
|
onClick: () => { |
|
void (async () => { |
|
await view.gradeCurrentRating("easy", {}); |
|
view.render(); |
|
})(); |
|
}, |
|
kbd: "4", |
|
}); |
|
applyWidgetActionButtonStyles(easyBtn); |
|
gradingGrid.appendChild(easyBtn); |
|
} |
|
|
|
footer.appendChild(gradingGrid); |
|
} else if (card.type === "mcq") { |
|
const mcqNote = el("div", "text-muted-foreground w-full text-center sprout-widget-info"); |
|
mcqNote.textContent = isMultiAnswerMcq(card) |
|
? tx(view, "ui.widget.mcq.selectAllThenSubmit", "Select all correct answers, then submit") |
|
: tx(view, "ui.widget.mcq.selectOption", "Select an option"); |
|
footer.appendChild(mcqNote); |
|
} else if (card.type === "oq") { |
|
const oqSubmitBtn = makeTextButton({ |
|
label: tx(view, "ui.widget.oq.submitOrder", "Submit order"), |
|
className: "learnkit-btn-toolbar sprout-widget-btn sprout-widget-btn-full", |
|
onClick: () => { |
|
const oqMap = ensureWidgetOqOrderMap(view.session as unknown as Record<string, unknown>); |
|
const steps = Array.isArray(card.oqSteps) ? card.oqSteps : []; |
|
const currentOrder = oqMap[String(card.id)] || Array.from({ length: steps.length }, (_, i) => i); |
|
void view.answerOq(currentOrder.slice()); |
|
}, |
|
kbd: "\u21B5", |
|
}); |
|
applyWidgetActionButtonStyles(oqSubmitBtn); |
|
footer.appendChild(oqSubmitBtn); |
|
} |
|
} else { |
|
const nextBtn = makeTextButton({ |
|
label: tx(view, "ui.widget.next", "Next"), |
|
className: "learnkit-btn-toolbar sprout-widget-btn sprout-widget-btn-full", |
|
onClick: () => void view.nextCard(), |
|
kbd: "↵", |
|
}); |
|
applyWidgetActionButtonStyles(nextBtn); |
|
footer.appendChild(nextBtn); |
|
} |
Bug Description
Bug Description
When studying an Image Occlusion card, the card reveals correctly, but after revealing the answer the reviewer does not show any grading buttons.
Instead of showing
Again / Hard / Good / Easy, it only shows aNextbutton.This makes it impossible to manually grade the card from the UI.
Current Behaviour
Before reveal:
Show Answer.After pressing
Enter/Show Answer:Next.Enteragain continues to the next card, without giving me a chance to manually choose a grade.Screenshots:
Show Answerbutton visible.Nextbutton visible. NoAgain / Hard / Good / Easy.Settings Already Tried
I tried the related settings and the issue still happens:
Studying -> Auto-advance: offStudying -> Auto-advance after: checkedStudying -> Skip button: offStudying -> Grading buttons: Four buttonsFlashcards -> Image occlusion -> Reveal mode: checkedFlashcards -> Hotspot -> Hotspot interaction mode: checked / changedMultiple choice -> Auto-grade: checked, but this is not MCQOrdered questions -> Auto-grade: checked, but this is not OQNone of these made the grading buttons appear after revealing the Image Occlusion card.
Code Pointers
From looking at the code, the screenshot appears to match the widget/practice-style footer path.
In the widget render code, the practice footer shows
Show Answer, then after reveal it shows onlyNext:LearnKit/src/views/widget/view/render-session.ts
Lines 980 to 1015 in d5e7e2c
The scheduled footer, however, seems like it should show grading buttons when
showAnsweris true and the card is ungraded:LearnKit/src/views/widget/view/render-session.ts
Lines 1019 to 1171 in d5e7e2c
Specifically, this part looks like the expected grading path:
LearnKit/src/views/widget/view/render-session.ts
Lines 1037 to 1140 in d5e7e2c
So it looks like the Image Occlusion review is either:
There is also code where pressing
Nextcan auto-grade an ungraded scheduled card asagain:LearnKit/src/views/widget/session/session-actions.ts
Lines 360 to 365 in d5e7e2c
So the visible problem is: after reveal, the UI only offers
Next, not manual grading.Suggested Fix Direction
For Image Occlusion cards in a normal study/review session, after the answer is revealed and the card is still ungraded, the UI should render the standard grading buttons instead of
Next.If this is happening because the card/session is in practice mode, the UI should make that clearer, because from the user side it looks like a normal study session but grading is unavailable.
Steps to Reproduce
Show Answer.Enteror clickShow Answer.Next, not the manual grading buttons.Enteragain advances to the next card without allowing manual grading.Expected Behavior
Expected Behaviour
After revealing an Image Occlusion card, LearnKit should show the grading buttons:
Then the user should manually choose a grade before the card advances.
Expected flow:
Enter= reveal answer1,2,3, or4LearnKit Version
1.3.3
Obsidian Version
1.12.7
Operating System
macOS
Additional Context
Screenshots show the exact UI state: before reveal, the IO card has hidden labels and a
Show Answerbutton; after reveal, the answer appears but the footer only showsNext, with no manual grading buttons.