mirror of
https://github.com/kuhyx/todo-app.git
synced 2026-11-10 20:07:02 +01:00
Standardizes on the same stricter lint set + shared analysis_options.yaml used by diet-guard/app and the new habit_stack app. Fixes all 127 issues surfaced: dart fix --apply for imports/cascades/sorting, unawaited() on fire-and-forget Futures, bare catch(e) narrowed to on Exception catch(e) (matching diet_guard's existing pattern), one documented ignore for a deliberate TypeError catch around untrusted peer JSON, and missing public-member doc comments throughout. No behavior change: 174/174 tests pass, 100% line coverage maintained. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
142 lines
3.9 KiB
Dart
142 lines
3.9 KiB
Dart
/// Domain model for a single idea/note.
|
|
///
|
|
/// Notes are stored locally in a CRDT-backed SQLite table (see
|
|
/// [NoteRepository]). The CRDT layer manages its own metadata columns
|
|
/// (`hlc`, `node_id`, `modified`, `is_deleted`); the fields here are the
|
|
/// user-facing data only.
|
|
library;
|
|
|
|
/// Priority tier for a note, used for sorting and visual grouping.
|
|
///
|
|
/// Every note always has a priority (there is no "none"); [medium] is the
|
|
/// default. Stored as the integer [value] so ordering is trivial in SQL.
|
|
enum Priority {
|
|
/// Lowest priority tier.
|
|
low(1, 'Low'),
|
|
|
|
/// Default priority tier for a new note.
|
|
medium(2, 'Medium'),
|
|
|
|
/// Highest priority tier.
|
|
high(3, 'High');
|
|
|
|
const Priority(this.value, this.label);
|
|
|
|
/// The default applied to new notes and to any legacy/unknown value.
|
|
static const Priority defaultValue = Priority.medium;
|
|
|
|
/// Integer persisted in the database; higher means more important.
|
|
final int value;
|
|
|
|
/// Human-readable label for UI controls (pickers, filters, list rows).
|
|
final String label;
|
|
|
|
/// Rebuilds a [Priority] from its stored [value], defaulting to
|
|
/// [defaultValue] for any unknown/legacy value (e.g. the old `0` = none)
|
|
/// so reads never throw and pre-existing notes show as Medium.
|
|
static Priority fromValue(int? value) {
|
|
return Priority.values.firstWhere(
|
|
(p) => p.value == value,
|
|
orElse: () => defaultValue,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Workflow state of a note, independent of its [Priority].
|
|
///
|
|
/// Stored as the integer [value]. [todo] is the default (0) so existing
|
|
/// notes created before this field existed read back as "to do".
|
|
enum Status {
|
|
/// Default status for a new or legacy note.
|
|
todo(0, 'To do'),
|
|
|
|
/// Actively being worked on.
|
|
inProgress(1, 'In progress'),
|
|
|
|
/// Finished.
|
|
done(2, 'Done'),
|
|
|
|
/// Deliberately dropped, not finished.
|
|
abandoned(3, 'Abandoned');
|
|
|
|
const Status(this.value, this.label);
|
|
|
|
/// Integer persisted in the database.
|
|
final int value;
|
|
|
|
/// Human-readable label for UI controls.
|
|
final String label;
|
|
|
|
/// Rebuilds a [Status] from its stored [value], defaulting to [todo]
|
|
/// for any unknown/legacy value so reads never throw.
|
|
static Status fromValue(int? value) {
|
|
return Status.values.firstWhere(
|
|
(s) => s.value == value,
|
|
orElse: () => Status.todo,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// An immutable idea/note record.
|
|
class Note {
|
|
/// Creates a [Note] from its stored fields.
|
|
const Note({
|
|
required this.id,
|
|
required this.text,
|
|
required this.priority,
|
|
required this.status,
|
|
required this.createdAt,
|
|
required this.updatedAt,
|
|
});
|
|
|
|
/// Builds a [Note] from a raw CRDT query row.
|
|
///
|
|
/// Timestamps are stored as ISO-8601 strings for human-readable,
|
|
/// lexicographically sortable values.
|
|
factory Note.fromRow(Map<String, Object?> row) {
|
|
return Note(
|
|
id: row['id']! as String,
|
|
text: (row['text'] as String?) ?? '',
|
|
priority: Priority.fromValue(row['priority'] as int?),
|
|
status: Status.fromValue(row['status'] as int?),
|
|
createdAt: DateTime.parse(row['created_at']! as String),
|
|
updatedAt: DateTime.parse(row['updated_at']! as String),
|
|
);
|
|
}
|
|
|
|
/// Stable unique id (UUID v4). Also the CRDT primary key.
|
|
final String id;
|
|
|
|
/// The markdown body of the idea.
|
|
final String text;
|
|
|
|
/// Priority tier for sorting/filtering.
|
|
final Priority priority;
|
|
|
|
/// Workflow state (to do / in progress / done / abandoned).
|
|
final Status status;
|
|
|
|
/// When the note was first created (set once, never changed).
|
|
final DateTime createdAt;
|
|
|
|
/// When the note's content was last modified locally.
|
|
final DateTime updatedAt;
|
|
|
|
/// Returns a copy with selected fields replaced.
|
|
Note copyWith({
|
|
String? text,
|
|
Priority? priority,
|
|
Status? status,
|
|
DateTime? updatedAt,
|
|
}) {
|
|
return Note(
|
|
id: id,
|
|
text: text ?? this.text,
|
|
priority: priority ?? this.priority,
|
|
status: status ?? this.status,
|
|
createdAt: createdAt,
|
|
updatedAt: updatedAt ?? this.updatedAt,
|
|
);
|
|
}
|
|
}
|