MoveLibrary
featureBreakdex::Arsenal::MoveLibrary
CRUD for breakdancing moves with video attachment
The atomic unit of the app. A move is one breakdancing technique with a name, category, optional video, and a learning state tracked by FSRS. Everything else — combos, reviews, flow graph — depends on moves existing first.
Relationships
Depends On 3
Reads From 3
Writes To 1
Renders With 3
Edited By 3
Configured By 3
Breaks If 3
Validated By 2
Data Access
Owns 1
Reads 3
Writes 1
Routes
/moves/moves/move/:idAnswers
States
| State | Behavior |
|---|---|
| archived | afterGrace: hard_delete gracePeriod: 30 days hiddenFrom: [
"move_list",
"review_queue",
"flow_graph"
] visibleIn: [
"recently_deleted_screen"
] |
| error | renders: error_text shows: sliver_fill_remaining |
| loading | renders: circular_progress_indicator shows: sliver_fill_remaining |
| no Moves | allows: [
"add_move_flow",
"import_from_photos"
] message: Tap + to add your first move shows: empty_illustration |
| no Video | allows: [
"name",
"category",
"review",
"combo_membership"
] blocks: [
"video_playback",
"video_export",
"move_analysis"
] fallsBackTo: category_color_card shows: placeholder_thumbnail |
| search No Results | message: No moves match your search shows: empty_state_variant |
Invariants
Move names are unique (case-insensitive) across moves AND combos
Enforced by: sqlite_trigger
Video paths stored as relative, resolved to absolute at read time
Enforced by: video_path_resolver
Every move gets an FSRS card on first review, not on creation
Enforced by: fsrs_cards_dao_ensure_card
Preferences
Prefer move_repository over moves_dao_direct
Repository wraps sync logging — DAO skips it
Prefer watch_all_stream over get_all_future
Streams auto-rebuild UI on database changes
Failure Modes
- Empty state if database connection fails on startup
Safe Change Notes
- UI layout changes in move_list_screen are isolated — no other screen imports it