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>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-01 18:42:25 +02:00
commit 0afc22d454
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -74,19 +74,26 @@ void main() {
expect(word.withField(CardField.meanings, const [' ']).isComplete, false);
});
test('matching: with targets, and items each in one of them', () {
CardContent sorting(int target) => CardContent(
test('matching: with two targets and two items at least, every item in '
'a target and no target empty', () {
CardContent sorting(List<int> targets) => CardContent(
type: CardType.matching,
front: none,
back: none,
matching: Matching(
targets: const ['mammal', 'bird'],
items: [MatchingItem(text: 'cat', target: target)],
items: [
for (final (i, target) in targets.indexed)
MatchingItem(text: 'animal $i', target: target),
],
),
);
expect(sorting(0).isComplete, true);
expect(sorting(2).isComplete, false);
expect(sorting([0, 1]).isComplete, true);
expect(sorting([0, 0]).isComplete, false);
expect(sorting([0, 2]).isComplete, false);
expect(sorting([0, -1, 1]).isComplete, false);
expect(sorting([0]).isComplete, false);
});
});