Both are still in progress and shouldn't be reachable in production
(or local dev) yet - hide every entry point (nav sidebar, the
dashboard's "dynamic concepts due" review card, and the CCS Cases
mode card on the study selector) unless step3/deployment_environment
is "uat", the same setting that already drives the UAT badge. Added
Brand.is_uat_environment() as the shared check.
Two real gaps meant the account-synced zoom (from the previous
"sync through the account" change) never reached the screen:
_load_cache() updated AccountProfileService.preferences but never
emitted profile_changed, so question_player.gd/ccs_service.gd (already
built and listening before login even happens) never found out a
cached value had loaded. And nothing forced a server refresh
right after login - it only fired if the user happened to open the
profile/progress screen, so a fresh device/session had no path to
the true synced value at all.
main.gd now calls AccountProfileService.refresh() once per login
(not on every silent token refresh) so the real preferences GET
always runs right after signing in, on any device.
Also added Question bank/CCS case text size steppers to the Settings
screen next to dark mode, per user request, reusing the same
AccountProfileService/CCSService plumbing as the in-screen A-/A+
buttons.
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.
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.