With two notes or more, Reorder beside the tabs gives each note a grip
in place of its options, as paths have, until Done; e.g. to follow a
reading order. A note's position was stored already; the repository
now moves it (only that column changes, and it syncs).
The notes' bloc sits with the studyset's other lists now, above the
tabs, so the button knows how many there are. The position helpers the
paths kept to themselves are shared (core/sync/fractional_position.dart),
and so is the grip (ReorderGrip).
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 Notes tab beside Flashcards lists a studyset's notes in order: the
title ("Untitled note" without one) and when each was last edited
("Edited 5 minutes ago", by the calendar from yesterday on, the date
after a week); Edit and Delete behind its options. Deleting asks,
then offers Undo for a moment (`NoteDeletions`). With none, the tab
says so.
- "Create a note" in Add material opens a new note over the tabs; so
does a note of the list. The note: a title, its tags once it exists,
and its text at reading width; the app bar says how saving stands.
- `NoteEditorBloc` saves after 5 seconds without typing, when the app
goes to the background, and when the note is closed (the bloc saves
as it closes, so leaving never waits, and the write outlives the
screen). Each save builds on the revisions the editor started from;
another device's change takes over a note with nothing unsaved, and
merges with one that has. A note changed differently on two devices
is read-only until the person keeps a version of each field in
conflict. A new note is created by its first save, never when left
blank; a note deleted elsewhere says it no longer exists.
- The editor gains a format bar, docked below it while it has the
focus (`RichContentEditor(formatBar: true)`): alignment, bold,
italic, underline, superscript and subscript. It takes no focus, so
the selection stays. Superscript and subscript are inline marks of
their own, drawn by the font's raised and lowered glyphs in editors
and read-only text alike.
- The library's and the topics' counts include notes (a studyset with
what is inside it, as for cards).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
Server: three synced tables, only additions (migration
20261002191122122-notes): `note` (its studyset, a fractional position),
`note_revision` (append-only, as a card's: parents, author, report,
the payload {schemaVersion, title, body}) and `note_tag` (one row per
assignment, never updated, as `card_tag`). Each indexes `spaceId`, and
everything goes with its space, studyset, note or tag. A migration of
synced tables locks app builds from before it out of syncing (ADR 0002,
rule 3): cheap now, before the first release.
App, `feature/note`:
- `NoteContent` is a title and rich text, merged apart (ADR 0003): a
title changed on one device and the body on another both survive, a
body changed on two is a conflict.
- `NoteRepository` creates a note at the end of its studyset, saves an
edit on the revisions it started from (`saveEdit`, as the card
composer now does), says when a note was last edited (its newest
head's UUID v7), counts notes per studyset, and deletes a note's
revisions blanked first (ADR 0002, rule 2).
- Notes share the person's tags: `setTagsOfNote`, and folding tags of
one name or undoing a tag's deletion covers notes too.
- The delayed deletion with its Undo moves to `core/async`
(`DelayedDeletions`): `StudysetDeletions` builds on it and now takes
a studyset's notes too; `NoteDeletions` deletes a single note.
Tests: content, merge, payload, repository, deletions, tags, the device
migration guard, and sync tests against the server (four).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>