Commit graph halkyon/halkyon_learn_flutter/test/feature/card/bloc
Author SHA1 Message Date
3b10922888
fix(app): a card's edit builds on what it started from
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>
2026-10-02 20:57:11 +02:00
0afc22d454
feat(app): the card composer, for many cards in one sitting
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>
2026-10-01 21:10:03 +02:00
a5515c13f7
feat(app): the card composer's state: many cards, saved on leaving
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>
2026-10-01 21:10:02 +02:00
927017bf15
feat(app): card types, whose fields merge separately
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>
2026-10-01 21:10:02 +02:00
9dc9b6a5ed
feat(app): choose, manage and filter by tags
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>
2026-10-01 17:40:10 +02:00
66886ef383
feat(app): flashcards on append-only revisions
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>
2026-09-30 20:38:17 +02:00