Unselected/eliminated choices now sit in a flat list with a thin
bottom divider instead of each getting its own bordered box, and only
the selected/correct/wrong choice pops out as a rounded, tinted card -
closer to the reference mockup and less visually busy than every
option looking like an separate boxed card.
A choice that was crossed out (right-click) and also happened to be
locked as the submitted-wrong choice, or revealed as the correct
answer, silently lost its strikethrough because the percentage-badge
branches took precedence over the elimination check in the same
if/elif chain. Decoupled the two so a choice can show both the
strikethrough and its reveal percentage at once.
The warning was purely a token-expiry countdown with no concept of
user activity, so it interrupted people who had been clicking through
questions the whole time. AuthState now tracks real input activity
globally and silently refreshes the session in the background when
the user has interacted recently, only surfacing the "Stay logged in?"
dialog for sessions that are genuinely idle. A failed background
refresh still surfaces the dialog rather than silently logging the
user out.
Flagged questions disappear from every student-facing surface (search,
exam simulation sampling, the missed-question review queue, bookmarks,
direct fetch) while staying published - flagging and unpublishing are
now separate, reversible actions with their own audit trail (who
flagged it, when, why). Backend-only for now: SUPER-only flag/unflag/
list endpoints, no client UI. Includes a one-time CLI sweep
(flag-media-questions) to flag every existing question with an image
so they can be reviewed.
Matches the mockup: the "Show Answer" button is replaced by an in-card
"Tap card to reveal answer" hint, and clicking anywhere on the card
reveals it (guarded the same way Space already was - only while at the
live card and not yet revealed).
System decks/notes are owned by a reserved sentinel user id, reusing
all existing per-user store/index plumbing unchanged. Regular users
see them under a separate "Official Decks" section, can study them
with fully independent per-user FSRS progress (lazily materialized on
first visit), but can never edit or archive them - enforced both in
the client (no Edit/Archive controls) and server-side (ownership guard
on every mutating endpoint). Includes a small idempotent seed command
(`dotnet run -- seed-flashcards`) for testing, since there's no in-app
authoring UI yet.
The study screen was still treated as a fullscreen immersive view (like
the question player), hiding the main nav sidebar entirely. The mockup
and the user's request both call for keeping the app's left menu while
studying, with the deck panel living inside the screen alongside it.
Add real session-history navigation (Previous/Next/Shuffle), compact
side panels, and a segmented progress row to match the mockup layout.
Flashcards now opens straight into Study, with library management
moved into the Options menu ("Manage Flashcards") and Export hidden
from the UI (Import stays). Shuffle is backed by a real, due-before-new
randomized pick on the backend, not a decorative toggle.
Study screen now matches the provided mockup's layout: a "Current
Deck" panel with a circular mastery-progress ring, and a "Spaced
Repetition" panel (New/Due/Learning/Review counts, streak, daily
goal) on either side of the card. Kept the app's real global sidebar
rather than the mockup's own nav, per direction.
Mastery/Streak/Daily Goal weren't tracked anywhere, so this adds real
backend support rather than showing fabricated numbers:
- Mastered = graduated to review state AND FSRS stability >= 21 days
(FlashcardScheduleStore.MasteryStabilityDaysThreshold), stricter
than the plain Review-state count
- CurrentStreakDays = consecutive UTC days with a review, computed
from review-log timestamps in the new pure FlashcardScheduling
.ComputeStreakDays (unit tested, habit-streak semantics: doesn't
reset to 0 the instant a new day starts before today's first review)
- DailyGoal/ReviewsToday reuse the account's existing ReviewsPerDay
setting rather than inventing a new one
Also removes the exit "X" button in favor of the same Escape/pause
menu the question-player flow uses (main.gd's shared app_menu, with
an "Exit Study Session" action), and adds a new circular_progress.gd
reusable ring control plus a real "Options" menu (bury/suspend the
current card) wired to schedule endpoints that had no UI before.
Compared side-by-side against Dashboard, the library screen used
entirely different visual primitives: a gradient primary button
Dashboard doesn't use anywhere, per-row bordered cards with low
contrast against the dark background, and a translucent pill badge
instead of the icon-circle pattern used everywhere else (stat tiles,
review queue, recent activity).
- Study/Save/Commit import now use Dashboard's actual primary button
style (flat ROYAL_BLUE, not the login/session-dialog gradient)
- Added a stat-tile row (Due today / New available / Decks) using
Dashboard's exact icon-circle + value + label construction, replacing
the due/new counts previously crammed into the deck dropdown's text
- The note list now lives in one bordered card with a section title
(matching Dashboard's chart/list panels) instead of each row being
its own separate low-contrast card
- Per-row card-type indicator is now an icon circle (clipboard-list /
notebook-pen) matching the Recent Activity list pattern, instead of
a translucent color-coded pill badge
refresh_theme_controls() colored the divider and the ANSWER/KEY
TAKEAWAY captions, but it only ran on an actual theme toggle - never
at initial build. Confirmed live: the divider was invisible (default
white on a white card) and the captions rendered as plain body text
instead of the intended accent color until you toggled dark mode
once. Call refresh_theme_controls() once at the end of _build() so
the correct colors apply immediately, which also fixes the same
latent gap in empty_label's color.
Study card: label the answer and "key takeaway" as distinct sections
with a real visible divider (previously an all-but-invisible
HSeparator) instead of one undifferentiated block of text. Also fixes
a real gap where a cloze card's extra field was silently dropped,
since only basic notes combined answer+extra into one label. Bigger
card, gradient Show-Answer button matching the app's signature CTA
style instead of a duller flat teal, and the Undo button now hides
itself when there's nothing to undo instead of sitting there disabled
looking identical to a real action.
Library: colored type badge per card (Basic/Cloze) instead of plain
gray text, more breathing room inside each row, Study promoted to the
same gradient CTA style, and Edit/Archive given a real secondary
button treatment instead of default theme buttons. Note editor fields
renamed ("Back / Extra takeaway" + a separate "Extra" field was
genuinely confusing) and now show which deck a card is being saved to.
They only closed via their own trigger button or a menu item -
clicking outside, pressing Escape, or opening the other dropdown
while one was open left it stuck on screen (confirmed opening both
stacked on top of each other). Add a shared invisible backdrop
(mirroring main.gd's drawer-backdrop pattern) that closes whichever
dropdown is open on outside click or Escape, and have opening one
close the other first.
current_study_day_start_utc() passed use_space=true to
Time.get_datetime_string_from_unix_time(), producing "2026-07-21
00:00:00Z" (space separator) instead of ISO-8601. The server's
System.Text.Json DateTime converter rejects that with a 400, which
the client surfaces as a generic "could not be loaded" error -
blocking every study session. Confirmed against the live API: the
space-separated value 400s, the corrected T-separated value returns
a card.
The panel's shared Brand.panel_box background is ~80% opaque, which
compounded with the dialog's own dim backdrop let the screen behind
show through and washed out the card against it. Force full opacity
on this dialog's panel specifically, since other panel_box overlays
still rely on the shared translucency.
Import and export were stubbed with status-text placeholders; wire them
to the existing backend endpoints with a real file picker (web JS
bridge or native FileDialog) and browser/desktop download, plus an
import preview with create/update/skip/error counts before commit.
Also fix the library and study screens' theme-refresh handlers, which
were no-op stubs so cards never restyled on a theme toggle, and add
responsive layout handling for narrow viewports.
Adds a full flashcards system: FSRS-based scheduling, cloze/basic
card types, CSV import/export, media storage, and study UI, wired
into navigation and the dashboard alongside existing question flows.