Phase 2: persistence, and real pickers instead of cycling
The stored blob is now read once at startup through useReducer's lazy initialiser and written whenever it changes, so deck, direction, answering mode, context and the Leitner boxes all survive a restart. persistedState.ts is the only part that touches the browser; the parsing stays in domain/storage.ts. Every access is guarded, because localStorage throws rather than returning null in a private window, with site data blocked, or in a WebView that has not finished starting. That guard is now tested, along with the claim this whole migration rests on: a payload copied verbatim out of CapacitorStorage.xml on the phone loads back with its boxes intact. If that test ever fails, the React app has orphaned real drill progress. Also covered: damaged JSON, storage that throws, localStorage absent entirely, and a refused quota on write. Explore's pickers open a bottom sheet rather than cycling blindly through options, and the drill settings button is no longer dead - deck, direction and answering mode, each showing how many cards it selects. Sheet is shared by all three. Also fixed a silent one: .sheetLabel was used three times and did not exist. CSS modules are index-typed, so that compiles clean and renders with no class at all. 141 tests, typecheck clean. Sheets verified by rendering them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -99,3 +99,16 @@
|
||||
color: var(--on-accent);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* Group headings inside a sheet: Deck, Direction, Answering. */
|
||||
.sheetLabel {
|
||||
margin: 8px 0 2px;
|
||||
font-family: var(--mono);
|
||||
font-size: 9px;
|
||||
letter-spacing: 0.12em;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.sheetLabel:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user