todo-app/lib/data/note_record.dart
Krzysztof kuhy Rudnicki 9349747629
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
file-length / file length <= 250 lines (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
release-apk / release (APK) (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
Repo tasks: repo/done_check/by/evidence fields, filter chips, CLI close/list/search
Four optional note fields (repo, done_check, by, evidence) in the crdt_sync
record, written only when set, so editing a plain idea stays wire-identical
to v3 (note_repository_sync_compat_test). The log is schemaless: no stored
schema version; the legacy sqlite reader stays at v3.

NoteFilter gains a sources facet (ideas / every repo task / one repo);
search also matches the repo. The notes list shows only open ideas by
default (no badge); the filter sheet adds Ideas, Repo tasks and one chip
per repo when repo tasks exist. The per-note sheet shows the task fields
read-only. BACKLOG.md markers carry the new attributes, entity-escaped.

CLI: --repo --done-check --by on add, --close <id> --evidence (refused
without), --list [--repo] [--status], --search, and every id flag takes a
unique 8-character prefix. --list prints id8, status, priority, repo, title.

install_hooks.sh: the wrapper finds pre-commit's generated hook next to
itself, so commits from a git worktree (where .git is a file) work.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 08:26:26 +01:00

51 lines
1.7 KiB
Dart

/// Note <-> crdt_sync [Record] mapping; re-exported by `note_repository.dart`.
library;
import 'package:crdt_sync/crdt_sync.dart';
import 'package:todo/data/note.dart';
const _text = 'text';
const _priority = 'priority';
const _status = 'status';
const _createdAt = 'created_at';
const _updatedAt = 'updated_at';
const _repo = 'repo';
const _doneCheck = 'done_check';
const _by = 'by';
const _evidence = 'evidence';
/// Record fields for [note], all at [hlc]. Unset task fields are omitted, so
/// an idea's record is exactly the v3 field set (and cannot clear a peer's).
Map<String, Field> noteFields(Note note, Hlc hlc) => {
_text: (note.text, hlc),
_priority: (note.priority.value, hlc),
_status: (note.status.value, hlc),
_createdAt: (note.createdAt.toIso8601String(), hlc),
_updatedAt: (note.updatedAt.toIso8601String(), hlc),
if (note.repo case final v?) _repo: (v, hlc),
if (note.doneCheck case final v?) _doneCheck: (v, hlc),
if (note.by case final v?) _by: (v, hlc),
if (note.evidence case final v?) _evidence: (v, hlc),
};
/// Reads [record] as a [Note], ignoring unknown fields.
Note noteFromRecord(Record record) {
final fields = record.fields;
String? str(String name) => fields[name]?.$1 as String?;
return Note(
id: record.id,
text: str(_text) ?? '',
priority: Priority.fromValue(fields[_priority]?.$1 as int?),
status: Status.fromValue(fields[_status]?.$1 as int?),
createdAt: _parseDate(str(_createdAt)),
updatedAt: _parseDate(str(_updatedAt)),
repo: str(_repo),
doneCheck: str(_doneCheck),
by: str(_by),
evidence: str(_evidence),
);
}
DateTime _parseDate(String? iso) =>
iso == null ? DateTime.fromMillisecondsSinceEpoch(0) : DateTime.parse(iso);