From c25ae4e0d1166ac06040cbbee925b88ae41893ec Mon Sep 17 00:00:00 2001 From: Krzysztof kuhy Rudnicki Date: Mon, 2 Nov 2026 09:38:52 +0100 Subject: [PATCH] Close dopamine-ux 06-todo, log partial Co-Authored-By: Claude Opus 5.5 (1M context) --- dopamine-ux/DOCS-dopamine-ux-index.md | 2 +- dopamine-ux/TODO-06-todo.md | 182 -------------------------- 2 files changed, 1 insertion(+), 183 deletions(-) delete mode 100644 dopamine-ux/TODO-06-todo.md diff --git a/dopamine-ux/DOCS-dopamine-ux-index.md b/dopamine-ux/DOCS-dopamine-ux-index.md index fd8e7c4..216002f 100644 --- a/dopamine-ux/DOCS-dopamine-ux-index.md +++ b/dopamine-ux/DOCS-dopamine-ux-index.md @@ -103,7 +103,7 @@ what remains instead. | 03-diet-guard.md | not started | — | — | | 04-screen-locker.md | DONE 2026-11-01 | `89c65bd` | Status window `_section_streak` + week-transition reward text (kept in `extra_benefits_state.json`); the dead 09:00 early-bird claim is not shown. Per kuhy: no daily-streak state, no shutdown time, no freezes. Commit is on a worktree branch, unpushed. | | 05-workout-app.md | DONE 2026-11-01 | `e938201` | Set/warmup `selectionClick`, finish `mediumImpact` + generated chime (music_theory, pinned tag) + dialog arrival, `AppDuration`/`AppCurve` in theme.dart, streak counts up, reduced motion honoured, one Settings "Sound" switch for chime and break-end (foreground service too). Worktree commits, unpushed; `62c1c2c` covers old export/import gaps. | -| 06-todo.md | not started | — | — | +| 06-todo.md | PARTIAL 2026-11-02 (step 1 DONE; step 2 sound REJECTED by kuhy) | `kuhyx/todo-app 2ffae26` | haptic + checkmark on capture, appRoute motion tokens, animated wizard bar; no sound by decision | | 07-dufs-theme.md | not started | — | — | | 08-dufs-motion.md | not started | — | — | | 09-wake-alarm.md | not started | — | — | diff --git a/dopamine-ux/TODO-06-todo.md b/dopamine-ux/TODO-06-todo.md deleted file mode 100644 index f3d19fb..0000000 --- a/dopamine-ux/TODO-06-todo.md +++ /dev/null @@ -1,182 +0,0 @@ -Adopt the motion tokens in todo, and make capture feel immediate - -## findings (3, ranked by value over effort) - -1. **Capture gives no confirmation** — a successful capture is indistinguishable - from a no-op unless you go looking for the note. -2. **Zero motion, zero haptics** — despite being the only app already wired to - the shared package, so adoption here is cheapest. -3. **The pinned `design_system` tag predates the motion tokens** — nothing - compiles until the ref is bumped. Easy to forget, fatal if skipped. - -## what - -`todo` is the only app in kuhy's fleet already wired to the shared -`design_system` package — it has **deliberately no local `theme.dart`** (the -pubspec comment says so: nothing to drift from the frozen table). That makes it -the cheapest place to adopt the motion tokens added by prompt 01, and the -reference implementation the other apps get compared against. - -Today it has **zero motion and zero haptics**. Verified 2026-08-16: no -`Animated*`, no `AnimationController`, no `HapticFeedback`, no audio. Its only -progress UI is the note-editor wizard bar. Capturing a note — the app's whole -purpose, and the thing that has to feel frictionless enough to actually do — -gives nothing back beyond a toast on error. - -Per kuhy's rule for this project: **reward the capture, never the completion -count.** A todo app that celebrates finishing things teaches you to log easy -things; one that celebrates *capturing* keeps the backlog honest. - -## where - -Repo: `~/src/todo`. - -**First step — bump the dependency.** `pubspec.yaml` pins `design_system` at git -ref `design_system-v0.1.0`, which predates the motion tokens. Bump it to -**`design_system-v0.2.0`** (cut by prompt 01) or the tag that prompt actually -printed. Without this, `AppDuration` does not exist and nothing else here compiles. - -Primary: -- `lib/ui/capture_screen.dart`, `lib/ui/capture_screen_widget.dart`, - `lib/ui/capture_screen_sync.dart` — the capture path. `showError` ~:76 and - `showToast` ~:78 in `capture_screen_sync.dart` are the fleet's only uses of the - shared feedback helpers. -- `lib/ui/capture_app_bar.dart` — progress indicators ~:66, :84. -- `lib/ui/note_editor.dart` — `showError` ~:115. -- `lib/ui/note_editor_step_page.dart` ~:80 — `LinearProgressIndicator(value: - (index+1)/total)`, the wizard step bar. The one honest progress surface. -- `lib/ui/notes_list_screen.dart` — `_searchDebounce = 250ms` ~:45 (**not** - animation; do not tokenise it). -- `lib/ui/notes_list_navigation.dart`, `lib/ui/settings_screen.dart` (2×), - `lib/ui/capture_screen.dart` — the `MaterialPageRoute` sites, all using the - default platform transition. - -Settings — **this app has the only working toggle in the fleet; it is the -pattern the other prompts copy**: -- `lib/ui/settings_screen.dart` ~:213-225 — `ValueListenableBuilder` - wrapping a `SwitchListTile`; setter ~:111-140 (logs an `AnalyticsEvent`, opens - a Firebase client, calls `withAdvancedMode`). -- `lib/data/app_settings.dart` — `AppSettings` immutable class, - `SharedPreferences` keys ~:38-39, `load()` ~:42, `withAdvancedMode` ~:60, - `reconcileWithRemote` ~:98, `adopt` ~:132 (last-writer-wins cross-device sync - via `settings/advancedMode` ~:20). Held app-wide as a `ValueNotifier`. - -Theme: no local file. `lib/main.dart` ~:4 imports `design_system`; ~:60-61 wires -`theme: buildLightTheme(), darkTheme: buildDarkTheme()`. Source of truth is -`~/src/utils/design_system/lib/src/theme.dart`. - -## must - -**Step 1 — motion + haptics (no new dependency).** - -- Bump `design_system` to the new tag **first**, and confirm `AppDuration` / - `AppCurve` resolve before writing any other code. -- Add `HapticFeedback.selectionClick()` (or the token vocabulary's "confirm" cue) - on **successful note capture**. `HapticFeedback` comes from - `package:flutter/services.dart` — no pubspec change. Add - `` to - `android/app/src/main/AndroidManifest.xml`; it is absent today. -- Fire the haptic **on the tap**, not after the Firebase sync returns. The whole - point of the micro-animation idea is that immediate feedback removes the - perceived latency; a cue gated on a network round-trip reintroduces it. -- Give the capture a visible confirmation — currently a successful capture is - indistinguishable from a no-op unless you go looking. -- Animate the wizard `LinearProgressIndicator` between steps rather than jumping. -- Apply the shared page-transition/motion tokens to the `MaterialPageRoute` sites - so navigation matches the rest of the system. -- Honour `MediaQuery.of(context).disableAnimations`: durations collapse to zero, - haptics still fire. - -**Step 2 — sound (separate, independently revertable).** - -- Add an audio dependency and an `assets:` block to `pubspec.yaml` (neither - exists) plus a short capture-confirm cue. -- Sound ships **on**, with an opt-out `SwitchListTile` — copy the - `advancedMode` pattern verbatim (widget ~:213-225, setter ~:111-140, field in - `app_settings.dart`). It is the fleet's proven toggle; do not invent a new one. -- Consider whether the sound preference should sync across devices like - `advancedMode` does, or stay local. Local is the safer default — a per-device - audio choice is usually what people mean. - -**Both steps:** - -- must not: reward **completing** a todo more than capturing one. No streak on - completions, no counter that makes finishing feel better than recording. The - backlog is only useful if capture stays frictionless and honest. -- must not: add a variable/random reward to capture. There is no real pool to - draw from here, so any variance would be manufactured — which fails the - project's second test. -- must not: fabricate progress. The wizard bar's `(index+1)/total` is true; keep - it that way. -- must not: hand-copy token values into a local `theme.dart`. This app - deliberately has none — that is a feature, and the pubspec comment says so. -- must not: add `# noqa`-equivalents or suppress analyzer warnings. - -- optional: animate the notes-list reordering/filtering, if it falls out cheaply - from the shared tokens. - -## done - -1. `pubspec.yaml` references the new `design_system` tag and `flutter pub get` - resolves it. -2. Capturing a note produces a haptic within ~50ms of the tap and a visible - confirmation. -3. Wizard step transitions and page navigation use shared motion tokens; no - inline `Duration` remains for animation purposes (the 250ms search debounce - and 5s auto-sync debounce stay as they are — they are not motion). -4. `cd ~/src/todo && flutter analyze` is clean. -5. `cd ~/src/todo && flutter test` passes. -6. With OS "remove animations" enabled, the app works and durations are zero. -7. Step 2: the sound toggle flips, persists across restart, and silences the cue. - -## verify - -**On the phone — todo is mobile-primary.** - -``` -adb devices # confirm 23181JEGR08034 -cd ~/src/todo -flutter build apk --release -adb install -r build/app/outputs/flutter-apk/app-release.apk -``` - -Never `flutter install`, never `adb uninstall`, never `pm clear` — those wipe -real notes. `adb install -r` preserves them. - -Then capture a real note on the device and report what the phone did. A haptic is -a physical outcome: say what you felt, do not infer it from code. Also step -through the note-editor wizard to confirm the progress bar animates. - -If the app also has a desktop/web surface deployed under `/opt/`, note that it -can go stale independently — but this prompt's done-condition is the phone. - -## read first - -- `lib/ui/settings_screen.dart` ~:213-225 and `lib/data/app_settings.dart` — the - toggle pattern, in full, before writing the sound switch. -- `lib/ui/capture_screen_sync.dart` ~:76-78 — how `showToast`/`showError` are - used today; the shared helpers live in - `~/src/utils/design_system/lib/src/feedback.dart`. -- `~/src/utils/design_system/lib/src/feedback.dart` — `showToast`/`showError`, `_show` - ~:50. `confirm.dart` beside it **already imports `flutter/services.dart`**, so - if prompt 01 added a shared haptic helper it lives near here. -- `~/src/utils/unified-design-system/motion.md` — the vocabulary from prompt 01. - **Prompt 01 must have run first, and its tag must be cut.** -- `pubspec.yaml` — read the comment explaining why there is no local theme. - -## context you would otherwise rediscover - -- `showToast` and `showError` already carry fixed dwell times in the shared - package (`_toastDuration = 3s`, `_errorDuration = 5s`, - `feedback.dart` ~:14, :18). Those are **not** motion tokens; leave them. -- This is the **only** app on `design_system`. diet-guard, workout_app and - wake_alarm hand-transcribe tokens into local theme files, so a widget copied - from this app into one of those will not compile unmodified. -- The app has no streaks, no rings, no history charts, and no completion counts - today. That is a deliberate starting point for this prompt, not an oversight to - fix wholesale. -- Settings sync cross-device last-writer-wins through Firebase - (`settings/advancedMode`). If you add a synced preference, follow - `reconcileWithRemote`/`adopt`; if local-only, skip that path entirely. - -REMOVE ME AFTER FINISH