The sidebar wrote a front and a back only. It now holds the composer's
editor with a bloc of its own: every kind of card (multiple choice,
vocabulary with Look up, matching, a map, a character), tags, hints and
the explanation, pinning, duplicating and deleting. A new card is tied
to the page shown, which it can be moved to the current one, and waits
for its chapter's tag by name until it is created; text sent from the
pages goes into its front or its answer, as its kind keeps one. Create
saves it once it is complete, as the composer does; going back asks
before discarding what was written.
The screenshot of the pages has a button at the end of the format bar,
outside its scrolling, where an editor's place is for it
(InsertableBlock.inFormatBar); the Insert menu still lists it.
A new card no longer shows twice in the composer when its stored copy
arrives while it is saved.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMm7usAo6q9ZZRoPkWjoxi
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
Browse beside the flashcards' tab opens the studyset's cards over the
tabs (with everything inside it when it has sub-studysets), laid out as
the older design had it:
- a grid of tiles (each card's two sides) or one card at a time beside
the list (on a phone above a strip of them, swiped through), as last
left for the studyset on this device;
- a search over front, back, reading, meanings, hints, explanation and
tag names, katakana found as hiragana and kana by romaji;
- sorting by own order, newest, oldest, A–Z (words by reading), due
first; a filter sheet by kind, tag and state (new, learning, due,
buried, reported);
- choosing cards (a toggle; shift-click or long-press for a range,
select all) to move into another or a new studyset, add or remove
tags, start afresh, or delete with Undo; the actions in the row on
wide windows, in a bar at the foot below.
Moving cards between studysets is new in the card repository and its
gateway (studysetId and position written, named columns).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMm7usAo6q9ZZRoPkWjoxi
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
- A word tapped twice, or added while a level is being added, makes one
card: adds run one at a time, and the word counts as in the studyset
at once. The adder reads the studyset's cards once rather than for
every word.
- Adding that fails says so, and a level shows "Making the cards…" once
its words have come.
- Finding a studyset's dictionary tells finding, none and unreachable
apart: the dictionary screen says there is none or offers Retry, and
an instance unreachable at start is asked again once a sync goes
through (Look up and From the dictionary appear then).
- Look up's tags wait on the card by name and are made when it is saved:
leaving the card at once no longer saves it untagged, a word replaced
leaves no tag behind, and a new word replaces any level or word class
on the card, pinned ones too. Look up marks words already made into
cards of the studyset.
- The tag picker's Create keeps the case typed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMm7usAo6q9ZZRoPkWjoxi
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
A vocabulary card filled through Look up in the composer got the word but
none of its tags, while the dictionary screen tags every word with its
JLPT level and word class. Both now take the tags from the word itself
(DictionaryWord.tagNames). Looking another word up on the same card swaps
the tags the word before brought; tags the person gave the card stay.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMm7usAo6q9ZZRoPkWjoxi
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
Studying breaks the order of due cards anyway; what follows the list
order is new cards and cramming, and that order comes from creating and
importing, with sub-studysets putting lessons in order. No one drags a
card among a thousand (decided 2026-10-08).
Gone: Reorder and the grip on flashcards, CardListEventMoved,
CardRepository.move and the gateway's updatePosition, with their tests.
Each card keeps its stored position, so the order stays the same on
every device. liftWhileDragged is Material's plain lift again, for the
lists that keep Reorder.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMm7usAo6q9ZZRoPkWjoxi
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
Finding today's burials in the review log meant reading every review the
cards ever had, once more in the library's progress, the card list and
each round. card.buriedAt holds it instead, read with the cards those
screens read anyway. The sync engine merges a row's fields one by one, so
a burial and a move of the same card on two devices both stand (a sync
test checks it). The review log's bury mode is gone.
The migration adds one nullable column, on the server and on devices:
ALTER TABLE "card" ADD COLUMN "buriedAt" (timestamp without time zone on
the server, INTEGER in SQLite); existing rows read as not buried. Apps
built before it stop syncing until they are updated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
Deleting a card, from the list or while studying, asks first ("Delete
flashcard?"), then offers Undo for a few seconds ("Flashcard deleted").
Meanwhile the card leaves every list and session; once the time to
undo is over, its revisions are blanked and it is deleted for good, as
notes and studysets already are (CardDeletions, a DelayedDeletions).
Undo while studying puts the card back into the round where it was.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
- "Report an error", from a card's menu while studying or in the list:
a category (typo, grammar, content, other) and a note. The card is
marked to be fixed, and still studied; the list shows the category
(the note on hover), and "Resolve report" takes it back. A report is
a revision of the card, so it follows it to every device.
- The list buries a card until tomorrow and brings it back ("Unbury"),
showing "Buried" meanwhile.
- Each of these says so with an Undo.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
The composer saved a stored card with the card's current heads as its
parents, so whatever had arrived meanwhile was replaced, not merged:
- another device's change to the side the person left alone was
overwritten silently;
- an edit made while saving, saved before the card was read back,
stood beside the first save: a conflict with itself;
- a new card left again before it was read back wasn't written at
all, while it showed as saved.
A draft now keeps the revisions its content came from (`base`): taken
with the stored content while the person hasn't changed it, and its own
revision after each save. A save replaces exactly those
(`CardRepository.saveEdit`), so what another device wrote meanwhile
stays a head of its own and merges per side (ADR 0003): a side only it
changed comes through, a side both changed is a conflict to settle. A
changed draft takes new conflicts only once it is saved.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
Create flashcards, and tapping a card, open the composer: the stack of
cards on the left (New flashcard on top, the new ones, then the stored
ones; collapsible), the card being written on the right, saved as the
person leaves it (another card, the pane, the screen, the app). The
title says how saving stands; leaving with cards that couldn't be saved
asks first. A card has its tags and their pin, an action menu
(duplicate, clear, delete), the type switch (flashcard, vocabulary,
matching), the front, and below a line its answer side: one answer or
several to mark right or wrong, the reading and meanings, or categories
and items. Fields changed differently on two devices show every version
to keep one. The single-card editor goes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
A bloc holding a studyset's cards as drafts, new ones on top and the
stored ones below. A card is saved when the person leaves it, once it
changed and has everything its type asks for, only its type's fields
stored; a failed save waits for the next leaving. A new card takes the
type of the card before it and what is pinned of it (front, answer,
tags); duplicating, clearing and deleting; a card devices changed
differently first needs a version chosen for every field in conflict.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
A card has a type: front/back, multiple choice (drawn on a map when it
names one), vocabulary or matching, and the fields of that type. The card
payload's schema 2 holds the type and the fields in use; schema 1 reads
as front/back. Revisions merge per field rather than per side (ADR 0003,
amended): a field one device changed takes the change, a field changed
differently is a conflict, lists included as a whole.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
The card editor offers its tags: a picker that searches by the start of
a name, creates a tag (name and colour) and chooses it, and saves the
choice with the card. A sheet lists every tag with its count, to add,
rename (merging into a tag of that name), recolour and delete them, with
an undo. The card list shows each card's tags and narrows to one tag.
The editor closed twice once tags changed after saving; it now closes
on becoming done only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
A studyset's screen lists its cards (reorderable; a marker on cards changed on two devices) and opens a card's screen with an editor for each side. Saving appends a revision whose parents are all current heads. mergeRevisions merges several heads per side against their newest common ancestor, as decided: different sides merge automatically, the same side changed differently is a conflict. The card screen then shows every version of that side with "Keep this", and saving is possible once each conflicted side is settled, which resolves the conflict for every device. Nothing is merged silently inside a side.
CardRepository watches a studyset's cards, creates at the end and moves by fractional index (fractional_indexing_dart, checked against the reference algorithm's test vectors), and deletes by blanking every revision first (ADR 0002, rule 2). Deleting a studyset now deletes its cards the same way before the studyset goes. Every person gets a CardRepository whose revisions name them as author. RichContent gains plainText for the list's previews.
Tests: the merge (chains, different and same sides, conflicts, resolving, three heads, missing parents, arrival order), the payload, the repository against a fake gateway, both blocs, and the widgets, including that cancelling a delete keeps the card. The sync tests, which need the running server, cover merging and conflicts across two devices and blank revisions on the server; their device helper is now shared in test/sync/support. AGENTS.md describes the revision pattern, the fractional order, and two tooling traps.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>