diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index 7a921e0..108599b 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -10,13 +10,15 @@ {"_type":"issue","id":"omarchy-wled-bgv","title":"Core: send color to WLED via HTTP API","description":"Send RGB color to WLED device using /json/state API endpoint. Accept IP at runtime.","status":"closed","priority":1,"issue_type":"task","assignee":"Eric Dahl","owner":"dahl.eric@gmail.com","created_at":"2026-05-01T03:23:31Z","created_by":"Eric Dahl","updated_at":"2026-05-01T15:38:06Z","started_at":"2026-05-01T03:23:41Z","closed_at":"2026-05-01T03:24:12Z","close_reason":"Closed","external_ref":"https://github.com/ericdahl-dev/omarchy-wled/issues/22","dependencies":[{"issue_id":"omarchy-wled-bgv","depends_on_id":"omarchy-wled-p8g","type":"blocks","created_at":"2026-04-30T23:23:34Z","created_by":"Eric Dahl","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0} {"_type":"issue","id":"omarchy-wled-iqx","title":"Core: watch for theme changes and update WLED","description":"Use inotify (watchdog) to detect changes to ~/.config/omarchy/current/theme/colors.toml and push new accent color to WLED automatically.","status":"closed","priority":1,"issue_type":"feature","assignee":"Eric Dahl","owner":"dahl.eric@gmail.com","created_at":"2026-05-01T03:23:30Z","created_by":"Eric Dahl","updated_at":"2026-05-01T15:38:06Z","started_at":"2026-05-01T03:24:13Z","closed_at":"2026-05-01T03:24:17Z","close_reason":"Closed","external_ref":"https://github.com/ericdahl-dev/omarchy-wled/issues/23","dependencies":[{"issue_id":"omarchy-wled-iqx","depends_on_id":"omarchy-wled-bgv","type":"blocks","created_at":"2026-04-30T23:23:35Z","created_by":"Eric Dahl","metadata":"{}"},{"issue_id":"omarchy-wled-iqx","depends_on_id":"omarchy-wled-p8g","type":"blocks","created_at":"2026-04-30T23:23:35Z","created_by":"Eric Dahl","metadata":"{}"}],"dependency_count":2,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"omarchy-wled-p8g","title":"Core: read accent color from Omarchy theme","description":"Parse accent color from ~/.config/omarchy/current/theme/colors.toml and return as RGB tuple. This is the foundation all other features depend on.","status":"closed","priority":1,"issue_type":"task","assignee":"Eric Dahl","owner":"dahl.eric@gmail.com","created_at":"2026-05-01T03:23:30Z","created_by":"Eric Dahl","updated_at":"2026-05-01T15:38:07Z","started_at":"2026-05-01T03:23:40Z","closed_at":"2026-05-01T03:24:12Z","close_reason":"Closed","external_ref":"https://github.com/ericdahl-dev/omarchy-wled/issues/24","dependency_count":0,"dependent_count":2,"comment_count":0} -{"_type":"issue","id":"omarchy-wled-5a1","title":"Revisit: Python TUI vs Go core duplication","description":"ADR-0005 keeps Go as core; Python TUI may duplicate colour logic. Options: document intentional drift boundary or have TUI delegate reads to Go binary.","notes":"Direction (2026-05): long-term plan is to port the TUI to a Go-compatible stack so colour/WLED logic stays in one language; short-term drift vs delegate-to-binary is lower priority until that port is scheduled.","status":"closed","priority":2,"issue_type":"task","owner":"dahl.eric@gmail.com","created_at":"2026-05-03T04:01:32Z","created_by":"Eric Dahl","updated_at":"2026-05-03T04:37:38Z","closed_at":"2026-05-03T04:37:38Z","close_reason":"Go TUI shipped as omarchy-wled tui; Python deprecation is follow-up (R1 docs, R2 remove)","labels":["architecture"],"dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"omarchy-wled-3fq","title":"Deepen: Sentinel/poll fallback adapter","description":"Align with ADR-0003: explicit adapter for poll path + sentinel callable so new ColorSources cannot silently omit poll support.","status":"open","priority":2,"issue_type":"task","owner":"dahl.eric@gmail.com","created_at":"2026-05-03T04:01:31Z","created_by":"Eric Dahl","updated_at":"2026-05-03T04:01:31Z","labels":["architecture"],"dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"omarchy-wled-u66","title":"Revisit: split main.go into packages","description":"Conflicts CONTEXT.md single-file layout and ADR-0001 spirit for small tools. Proceed only if navigation friction outweighs ADR-0005 simplicity; update CONTEXT + ADR if split happens.","status":"closed","priority":2,"issue_type":"decision","owner":"dahl.eric@gmail.com","created_at":"2026-05-03T04:01:31Z","created_by":"Eric Dahl","updated_at":"2026-05-03T05:01:21Z","closed_at":"2026-05-03T05:01:21Z","close_reason":"Go core split into internal/paths, color, config, wallpaper, wled, source, daemon; ADR-0006 + CONTEXT/AGENTS updated. main.go is CLI wiring only.","labels":["architecture"],"dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"omarchy-wled-hud","title":"Deepen: push orchestration (dedupe, gradient vs solid, saturation)","description":"Isolate pushTracker + pushIfChanged policy from transport. Clear test surface for when we send and gradient dedupe without spinning HTTP.","status":"open","priority":2,"issue_type":"task","owner":"dahl.eric@gmail.com","created_at":"2026-05-03T04:01:30Z","created_by":"Eric Dahl","updated_at":"2026-05-03T04:01:30Z","labels":["architecture"],"dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"omarchy-wled-y7u","title":"Deepen: Wallpaper/background color pipeline module","description":"Group readBgColor, column average row, LED resampling, gamma helpers under one path→colors module. Goal: locality for linear/gamma math and image decode bounds.","status":"closed","priority":2,"issue_type":"task","assignee":"Eric Dahl","owner":"dahl.eric@gmail.com","created_at":"2026-05-03T04:01:29Z","created_by":"Eric Dahl","updated_at":"2026-05-03T04:09:42Z","started_at":"2026-05-03T04:08:18Z","closed_at":"2026-05-03T04:09:42Z","close_reason":"Extracted wled.go (HTTP solid + spatial + LED count) and wallpaper.go (γ pipeline + column strip); main.go keeps orchestration. go test ./... green.","labels":["architecture"],"dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"omarchy-wled-gyg","title":"Deepen: WLED sync module (HTTP + solid + spatial + LED count)","description":"Consolidate sendColorToWLED, sendSpatialGradientToWLED, fetch/resolve LED count, wledJSONURL/override behind one narrow seam. Goal: locality for fx/frz/chunking and firmware quirks; single fake surface for tests.","status":"closed","priority":2,"issue_type":"task","assignee":"Eric Dahl","owner":"dahl.eric@gmail.com","created_at":"2026-05-03T04:01:27Z","created_by":"Eric Dahl","updated_at":"2026-05-03T04:09:42Z","started_at":"2026-05-03T04:08:18Z","closed_at":"2026-05-03T04:09:42Z","close_reason":"Extracted wled.go (HTTP solid + spatial + LED count) and wallpaper.go (γ pipeline + column strip); main.go keeps orchestration. go test ./... green.","labels":["architecture"],"dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"omarchy-wled-4dk","title":"Add -gradient for bg + WLED Gradient effect","description":"CLI -gradient and -gradient-fx; read left/right wallpaper halves; send seg fx+col; config.toml keys","status":"closed","priority":2,"issue_type":"feature","owner":"dahl.eric@gmail.com","created_at":"2026-05-03T03:23:22Z","created_by":"Eric Dahl","updated_at":"2026-05-03T03:23:29Z","closed_at":"2026-05-03T03:23:29Z","close_reason":"Implemented gradient flag, WLED JSON path, tests, README","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"omarchy-wled-jip","title":"tui: fix misleading RGB variable names in View swatch","description":"In tui.go non-gradient preview branch, the third channel is named `c` but holds blue (B). Rename to `r, g, b` (or `b`) so readers do not confuse with generic color. No behavior change.","status":"open","priority":2,"issue_type":"task","owner":"dahl.eric@gmail.com","created_at":"2026-05-04T02:28:26Z","created_by":"Eric Dahl","updated_at":"2026-05-04T02:28:26Z","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"omarchy-wled-5a1","title":"Revisit: Python TUI vs Go core duplication","description":"ADR-0005 keeps Go as core; Python TUI may duplicate colour logic. Options: document intentional drift boundary or have TUI delegate reads to Go binary.","notes":"Direction (2026-05): long-term plan is to port the TUI to a Go-compatible stack so colour/WLED logic stays in one language; short-term drift vs delegate-to-binary is lower priority until that port is scheduled.","status":"closed","priority":2,"issue_type":"task","owner":"dahl.eric@gmail.com","created_at":"2026-05-03T04:01:32Z","created_by":"Eric Dahl","updated_at":"2026-05-04T02:24:20Z","closed_at":"2026-05-03T04:37:38Z","close_reason":"Go TUI shipped as omarchy-wled tui; Python deprecation is follow-up (R1 docs, R2 remove)","external_ref":"https://github.com/ericdahl-dev/omarchy-wled/issues/39","labels":["architecture"],"dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"omarchy-wled-3fq","title":"Deepen: Sentinel/poll fallback adapter","description":"Align with ADR-0003: explicit adapter for poll path + sentinel callable so new ColorSources cannot silently omit poll support.","status":"open","priority":2,"issue_type":"task","owner":"dahl.eric@gmail.com","created_at":"2026-05-03T04:01:31Z","created_by":"Eric Dahl","updated_at":"2026-05-04T02:24:21Z","external_ref":"https://github.com/ericdahl-dev/omarchy-wled/issues/40","labels":["architecture"],"dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"omarchy-wled-u66","title":"Revisit: split main.go into packages","description":"Conflicts CONTEXT.md single-file layout and ADR-0001 spirit for small tools. Proceed only if navigation friction outweighs ADR-0005 simplicity; update CONTEXT + ADR if split happens.","status":"closed","priority":2,"issue_type":"decision","owner":"dahl.eric@gmail.com","created_at":"2026-05-03T04:01:31Z","created_by":"Eric Dahl","updated_at":"2026-05-04T02:24:21Z","closed_at":"2026-05-03T05:01:21Z","close_reason":"Go core split into internal/paths, color, config, wallpaper, wled, source, daemon; ADR-0006 + CONTEXT/AGENTS updated. main.go is CLI wiring only.","external_ref":"https://github.com/ericdahl-dev/omarchy-wled/issues/41","labels":["architecture"],"dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"omarchy-wled-hud","title":"Deepen: push orchestration (dedupe, gradient vs solid, saturation)","description":"Isolate pushTracker + pushIfChanged policy from transport. Clear test surface for when we send and gradient dedupe without spinning HTTP.","status":"open","priority":2,"issue_type":"task","owner":"dahl.eric@gmail.com","created_at":"2026-05-03T04:01:30Z","created_by":"Eric Dahl","updated_at":"2026-05-04T02:24:22Z","external_ref":"https://github.com/ericdahl-dev/omarchy-wled/issues/42","labels":["architecture"],"dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"omarchy-wled-y7u","title":"Deepen: Wallpaper/background color pipeline module","description":"Group readBgColor, column average row, LED resampling, gamma helpers under one path→colors module. Goal: locality for linear/gamma math and image decode bounds.","status":"closed","priority":2,"issue_type":"task","assignee":"Eric Dahl","owner":"dahl.eric@gmail.com","created_at":"2026-05-03T04:01:29Z","created_by":"Eric Dahl","updated_at":"2026-05-04T02:24:22Z","started_at":"2026-05-03T04:08:18Z","closed_at":"2026-05-03T04:09:42Z","close_reason":"Extracted wled.go (HTTP solid + spatial + LED count) and wallpaper.go (γ pipeline + column strip); main.go keeps orchestration. go test ./... green.","external_ref":"https://github.com/ericdahl-dev/omarchy-wled/issues/43","labels":["architecture"],"dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"omarchy-wled-gyg","title":"Deepen: WLED sync module (HTTP + solid + spatial + LED count)","description":"Consolidate sendColorToWLED, sendSpatialGradientToWLED, fetch/resolve LED count, wledJSONURL/override behind one narrow seam. Goal: locality for fx/frz/chunking and firmware quirks; single fake surface for tests.","status":"closed","priority":2,"issue_type":"task","assignee":"Eric Dahl","owner":"dahl.eric@gmail.com","created_at":"2026-05-03T04:01:27Z","created_by":"Eric Dahl","updated_at":"2026-05-04T02:24:23Z","started_at":"2026-05-03T04:08:18Z","closed_at":"2026-05-03T04:09:42Z","close_reason":"Extracted wled.go (HTTP solid + spatial + LED count) and wallpaper.go (γ pipeline + column strip); main.go keeps orchestration. go test ./... green.","external_ref":"https://github.com/ericdahl-dev/omarchy-wled/issues/44","labels":["architecture"],"dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"omarchy-wled-4dk","title":"Add -gradient for bg + WLED Gradient effect","description":"CLI -gradient and -gradient-fx; read left/right wallpaper halves; send seg fx+col; config.toml keys","status":"closed","priority":2,"issue_type":"feature","owner":"dahl.eric@gmail.com","created_at":"2026-05-03T03:23:22Z","created_by":"Eric Dahl","updated_at":"2026-05-04T02:24:23Z","closed_at":"2026-05-03T03:23:29Z","close_reason":"Implemented gradient flag, WLED JSON path, tests, README","external_ref":"https://github.com/ericdahl-dev/omarchy-wled/issues/45","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"omarchy-wled-1777861457041-2-0e62f6f2","title":"more streamlined install","description":"would redoing this in Go create a better installation experience for Omarchy users who install via AUR?","status":"closed","priority":2,"issue_type":"task","assignee":"Copilot","created_at":"2026-05-02T21:27:48Z","updated_at":"2026-05-03T04:17:46Z","closed_at":"2026-05-03T04:17:47Z","external_ref":"https://github.com/ericdahl-dev/omarchy-wled/issues/34","source_system":"github:https://github.com/ericdahl-dev/omarchy-wled/issues/34:34","metadata":null,"dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"omarchy-wled-q0k","title":"refactor: inject sender into _refresh_color_preview for testability","description":"_refresh_color_preview hardcodes make_source, source.read(), and send_color_to_wled with bare except:pass. All handlers that call it require live filesystem and network. Injectable sender = testable preview + no HTTP on startup.","status":"closed","priority":2,"issue_type":"task","assignee":"Eric Dahl","owner":"dahl.eric@gmail.com","created_at":"2026-05-02T20:15:32Z","created_by":"Eric Dahl","updated_at":"2026-05-02T21:25:20Z","started_at":"2026-05-02T20:18:05Z","closed_at":"2026-05-02T20:22:56Z","close_reason":"Closed","external_ref":"https://github.com/ericdahl-dev/omarchy-wled/issues/27","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"omarchy-wled-wp3","title":"refactor: move systemctl call out of widget constructor in _build_main","description":"ServiceController(ip).is_active() runs systemctl synchronously during compose(). The injectable runner= seam on ServiceController is never used at this call site. Constructor should stay pure; service check async.","status":"closed","priority":2,"issue_type":"task","assignee":"Eric Dahl","owner":"dahl.eric@gmail.com","created_at":"2026-05-02T20:15:28Z","created_by":"Eric Dahl","updated_at":"2026-05-02T21:25:20Z","started_at":"2026-05-02T20:18:05Z","closed_at":"2026-05-02T20:22:55Z","close_reason":"Closed","external_ref":"https://github.com/ericdahl-dev/omarchy-wled/issues/28","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"omarchy-wled-bmi","title":"refactor: deduplicate Omarchy path constants between core and TUI","description":"COLORS_TOML and THEME_NAME_FILE are defined verbatim in both omarchy_wled.py and omarchy_wled_tui.py. Path changes require two edits. TUI should import from core.","status":"closed","priority":2,"issue_type":"task","assignee":"Eric Dahl","owner":"dahl.eric@gmail.com","created_at":"2026-05-02T20:15:19Z","created_by":"Eric Dahl","updated_at":"2026-05-02T21:25:21Z","started_at":"2026-05-02T20:18:04Z","closed_at":"2026-05-02T20:22:54Z","close_reason":"Closed","external_ref":"https://github.com/ericdahl-dev/omarchy-wled/issues/29","dependency_count":0,"dependent_count":0,"comment_count":0} @@ -30,6 +32,13 @@ {"_type":"issue","id":"omarchy-wled-1777649880013-3-2a984396","title":"refactor: remove shallow read_accent_color / read_foreground_color wrappers","description":"## Problem\n\n`read_accent_color` and `read_foreground_color` (L76–83) are thin wrappers over `_read_color_key`. They're only referenced in tests and imply a stable public API that doesn't exist. Deletion test passes — removing them concentrates no complexity.\n\n## Fix\n\nRemove both functions. Tests should use `ThemeColorSource` or `_read_color_key` directly.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-05-01T15:03:51Z","updated_at":"2026-05-01T15:26:38Z","closed_at":"2026-05-01T15:26:39Z","external_ref":"https://github.com/ericdahl-dev/omarchy-wled/issues/6","source_system":"github:https://github.com/ericdahl-dev/omarchy-wled/issues/6:6","metadata":null,"dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"omarchy-wled-1777649879832-2-e2c09327","title":"bug: watch() ignores source.watch_path() — BgColorSource never triggers","description":"## Problem\n\n`watch()` hardcodes `THEME_NAME_FILE.parent` as the watched directory regardless of the active source. `BgColorSource` (and any future source) never fires because the observer watches the wrong directory.\n\n```python\n# L224 — always watches theme dir\nobserver.schedule(Handler(), str(THEME_NAME_FILE.parent), recursive=False)\n# should be:\nobserver.schedule(Handler(), str(source.watch_path().parent), recursive=False)\n```\n\nThe `watch_path()` seam exists on the `ColorSource` protocol precisely for this — it's just unused.\n\n## Fix\n\nReplace the hardcoded path with `source.watch_path().parent`.","status":"closed","priority":2,"issue_type":"bug","assignee":"Copilot","created_at":"2026-05-01T15:03:46Z","updated_at":"2026-05-01T15:20:53Z","closed_at":"2026-05-01T15:20:54Z","external_ref":"https://github.com/ericdahl-dev/omarchy-wled/issues/5","source_system":"github:https://github.com/ericdahl-dev/omarchy-wled/issues/5:5","metadata":null,"labels":["bug"],"dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"omarchy-wled-1777649879686-1-13dd76b4","title":"AUR release","description":"Can we get AUR releases happening from GitHub via tags? Research how, implement and make a PR","status":"closed","priority":2,"issue_type":"task","assignee":"Copilot","created_at":"2026-05-01T11:32:17Z","updated_at":"2026-05-01T14:22:02Z","closed_at":"2026-05-01T14:22:03Z","external_ref":"https://github.com/ericdahl-dev/omarchy-wled/issues/2","source_system":"github:https://github.com/ericdahl-dev/omarchy-wled/issues/2:2","metadata":null,"dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"omarchy-wled-6i0","title":"source: clarify Source interface methods for polling vs fsnotify","description":"Expand package or interface doc comments for Sentinel() (poll fingerprint string) and IsTrigger(path) (whether this path should trigger a color refresh). Optional follow-up: consider renaming to ChangeFingerprint / PathTriggersRefresh if willing to touch the interface.","status":"open","priority":3,"issue_type":"task","owner":"dahl.eric@gmail.com","created_at":"2026-05-04T02:28:29Z","created_by":"Eric Dahl","updated_at":"2026-05-04T02:28:29Z","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"omarchy-wled-507","title":"tui: document or rename preview debounce fields (previewGen/previewArm)","description":"tuiModel uses previewGen and previewArm for debounced preview scheduling. Add a short comment block above the fields explaining the generation/token pattern, or rename to clearer names (e.g. previewRequestSeq / previewAcceptedSeq).","status":"open","priority":3,"issue_type":"task","owner":"dahl.eric@gmail.com","created_at":"2026-05-04T02:28:28Z","created_by":"Eric Dahl","updated_at":"2026-05-04T02:28:28Z","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"omarchy-wled-t7t","title":"tui: replace magic index 2 for wallpaper source with named constant","description":"tui.go uses `sourceIx == 2` throughout for wallpaper/Wallpaper avg. Introduce a named constant (e.g. sourceIndexWallpaper) next to sourceMaxIdx/sourceLabels so intent is obvious without counting UI rows.","status":"open","priority":3,"issue_type":"task","owner":"dahl.eric@gmail.com","created_at":"2026-05-04T02:28:28Z","created_by":"Eric Dahl","updated_at":"2026-05-04T02:28:28Z","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"omarchy-wled-8pr","title":"refactor: extract Handler class from watch() closure for testability","description":"Handler is embedded inside watch() as a closure. Cannot be instantiated in tests. _maybe_push behavior (is_trigger, sleep, push_if_changed) is untested. Extract as top-level class taking source/state/ip/brightness/saturation.","status":"closed","priority":3,"issue_type":"task","assignee":"Eric Dahl","owner":"dahl.eric@gmail.com","created_at":"2026-05-02T20:15:30Z","created_by":"Eric Dahl","updated_at":"2026-05-02T21:25:25Z","started_at":"2026-05-02T20:18:06Z","closed_at":"2026-05-02T20:22:56Z","close_reason":"Closed","external_ref":"https://github.com/ericdahl-dev/omarchy-wled/issues/32","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"omarchy-wled-l8w","title":"refactor: debounce WLED HTTP sends on brightness/saturation keystrokes","description":"Every keystroke in brightness/saturation fields fires a blocking HTTP POST to WLED via _refresh_color_preview. No debounce means typing '128' sends 3 requests. Add ~300ms debounce.","status":"closed","priority":3,"issue_type":"task","owner":"dahl.eric@gmail.com","created_at":"2026-05-02T20:15:29Z","created_by":"Eric Dahl","updated_at":"2026-05-02T21:26:24Z","started_at":"2026-05-02T20:18:06Z","closed_at":"2026-05-02T21:26:24Z","close_reason":"Closed","external_ref":"https://github.com/ericdahl-dev/omarchy-wled/issues/33","metadata":null,"dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"omarchy-wled-2fk","title":"docs: extend CONTEXT.md with Omarchy paths and WLED/sentinel glossary","description":"Per readability review: add short glossary entries to CONTEXT.md for Omarchy paths (colors.toml, theme.name, background symlink), WLED concepts (seg.i spatial gradient, bri), and watcher vs Sentinel polling so code can stay terse without losing new readers. Only if CONTEXT.md already exists and project wants narrative docs.","status":"open","priority":4,"issue_type":"task","owner":"dahl.eric@gmail.com","created_at":"2026-05-04T02:28:37Z","created_by":"Eric Dahl","updated_at":"2026-05-04T02:28:37Z","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"omarchy-wled-4np","title":"color: unpack regex submatches in NamedHexFromColorsToml","description":"In internal/color/color.go loop over FindAllStringSubmatch, replace opaque m[1]/m[2] with named locals (e.g. key, hexDigits) for scanability. No logic change.","status":"open","priority":4,"issue_type":"task","owner":"dahl.eric@gmail.com","created_at":"2026-05-04T02:28:32Z","created_by":"Eric Dahl","updated_at":"2026-05-04T02:28:32Z","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"omarchy-wled-zhj","title":"daemon/wled: internal naming polish for readability","description":"Small renames/comments: daemon PushCurrentColorIfChanged printf vars `a, z` -\u003e strip endpoints (e.g. firstRGB/lastRGB); gradientSent struct -\u003e clearer last-gradient cache name; wled jsonGETURL / seg.i `iArr` add one-line comment that payload follows WLED seg.i (offset + hex per LED). Keep behavior identical.","status":"open","priority":4,"issue_type":"task","owner":"dahl.eric@gmail.com","created_at":"2026-05-04T02:28:31Z","created_by":"Eric Dahl","updated_at":"2026-05-04T02:28:31Z","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"omarchy-wled-94c","title":"tests: align main_test.go section headers with current API names","description":"main_test.go section comments still reference legacy labels (readColorKey, applySaturation, sendColorToWLED, makeSource). Update headers to match actual symbols (NamedHexFromColorsToml, ScaleSaturation, PostSolidJSON, FromFlag, etc.) for grep/nav consistency.","status":"open","priority":4,"issue_type":"task","owner":"dahl.eric@gmail.com","created_at":"2026-05-04T02:28:30Z","created_by":"Eric Dahl","updated_at":"2026-05-04T02:28:30Z","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"memory","key":"always-write-code-that-is-self-documenting-a","value":"always write code that is self documenting. a human should be able to understand the code by reading it."} diff --git a/tui.go b/tui.go index 8a60603..d3ccffa 100644 --- a/tui.go +++ b/tui.go @@ -60,7 +60,12 @@ const ( focusQuit ) -const sourceMaxIdx = 2 +const ( + sourceIndexAccent = 0 + sourceIndexForeground = 1 + sourceIndexWallpaper = 2 + sourceMaxIdx = sourceIndexWallpaper +) var sourceLabels = []string{"Accent", "Foreground", "Wallpaper avg"} @@ -86,7 +91,7 @@ func sourceIdxToName(idx int) string { } } -type previewTickMsg struct{ gen int } +type previewTickMsg struct{ scheduleID int } type serviceActiveMsg struct{ active bool } @@ -113,8 +118,9 @@ type tuiModel struct { toast string // save / service messages toastErr bool - previewGen int - previewArm int + // previewScheduleID increments on each schedulePreview; the tick message carries a copy. + // A tick is stale if its ID does not match (a newer preview was scheduled). + previewScheduleID int errSetup string } @@ -137,7 +143,7 @@ func newTuiModel(initial *tuiConfig) *tuiModel { mt.CharLimit = 255 mt.Focus() - grad := initial.Gradient && sourceIdxFromName(initial.Source) == 2 + grad := initial.Gradient && sourceIdxFromName(initial.Source) == sourceIndexWallpaper m := &tuiModel{ screen: tuiScreenMain, mainTI: mt, @@ -212,7 +218,7 @@ func (m *tuiModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, nil case previewTickMsg: - if msg.gen != m.previewArm { + if msg.scheduleID != m.previewScheduleID { return m, nil } return m.runPreview() @@ -307,7 +313,7 @@ func (m *tuiModel) updateMainKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) { if m.sourceIx < 0 { m.sourceIx = sourceMaxIdx } - if m.sourceIx != 2 { + if m.sourceIx != sourceIndexWallpaper { m.gradientOn = false } m.resetPreviewTracker() @@ -318,7 +324,7 @@ func (m *tuiModel) updateMainKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) { if m.sourceIx > sourceMaxIdx { m.sourceIx = 0 } - if m.sourceIx != 2 { + if m.sourceIx != sourceIndexWallpaper { m.gradientOn = false } m.resetPreviewTracker() @@ -380,7 +386,7 @@ func (m *tuiModel) syncFocus() tea.Cmd { func (m *tuiModel) focusSequence() []tuiFocus { seq := []tuiFocus{focusIP, focusSource} - if m.sourceIx == 2 { + if m.sourceIx == sourceIndexWallpaper { seq = append(seq, focusGradient) } seq = append(seq, focusBrightness, focusSaturation, focusService, focusSave, focusQuit) @@ -401,14 +407,14 @@ func (m *tuiModel) cycleFocus(dir int) { } func (m *tuiModel) ensureValidFocus() { - if m.focus == focusGradient && m.sourceIx != 2 { + if m.focus == focusGradient && m.sourceIx != sourceIndexWallpaper { m.focus = focusSource } } func (m *tuiModel) currentConfigFromForm() tuiConfig { ip := strings.TrimSpace(m.mainTI.Value()) - grad := m.gradientOn && m.sourceIx == 2 + grad := m.gradientOn && m.sourceIx == sourceIndexWallpaper return tuiConfig{ IP: ip, Source: sourceIdxToName(m.sourceIx), @@ -424,11 +430,10 @@ func (m *tuiModel) resetPreviewTracker() { } func (m *tuiModel) schedulePreview() tea.Cmd { - m.previewGen++ - m.previewArm = m.previewGen - g := m.previewGen + m.previewScheduleID++ + id := m.previewScheduleID return tea.Tick(80*time.Millisecond, func(t time.Time) tea.Msg { - return previewTickMsg{gen: g} + return previewTickMsg{scheduleID: id} }) } @@ -562,7 +567,7 @@ func (m *tuiModel) View() string { b.WriteString(lipgloss.NewStyle().Foreground(accent).Bold(true).Render("Configuration") + "\n") b.WriteString(m.renderLabeled("WLED IP / Host", m.mainTI.View(), m.focus == focusIP) + "\n") b.WriteString(m.renderLabeled("Color source", m.renderSourceRow(), m.focus == focusSource) + "\n") - if m.sourceIx == 2 { + if m.sourceIx == sourceIndexWallpaper { glabel := "Off" if m.gradientOn { glabel = "On (left→right strip)" @@ -592,10 +597,10 @@ func (m *tuiModel) View() string { s1.Render(fmt.Sprintf("rgb(%d,%d,%d) %s", r1, g1, b1, h1)) b.WriteString(" " + line + "\n\n") } else { - r, g, c := m.previewRGB[0], m.previewRGB[1], m.previewRGB[2] - hex := fmt.Sprintf("#%02x%02x%02x", r, g, c) + r0, g0, b0 := m.previewRGB[0], m.previewRGB[1], m.previewRGB[2] + hex := fmt.Sprintf("#%02x%02x%02x", r0, g0, b0) swatch := lipgloss.NewStyle().Foreground(lipgloss.Color(hex)).Bold(true) - b.WriteString(swatch.Render(fmt.Sprintf(" rgb(%d, %d, %d) %s", r, g, c, hex)) + "\n\n") + b.WriteString(swatch.Render(fmt.Sprintf(" rgb(%d, %d, %d) %s", r0, g0, b0, hex)) + "\n\n") } saveBtn := "[ Save ]"