fix: skip browser open on tray restart, add WLED rename TODO
Some checks failed
Lint & Test / test (push) Failing after 30s

Set WLED_RESTART=1 env var on tray restart so __main__.py skips
opening a new browser tab — the user already has one open.

Add important TODO item to eliminate WLED naming throughout the app
(package rename, i18n, build scripts, etc.).
This commit is contained in:
2026-03-24 14:21:27 +03:00
parent 40e951c882
commit b63944bb34
3 changed files with 120 additions and 6 deletions

106
TODO-css-improvements.md Normal file
View File

@@ -0,0 +1,106 @@
# TODO
## IMPORTANT: Remove WLED naming throughout the app
- [ ] Rename all references to "WLED" in user-facing strings, class names, module names, config keys, file paths, and documentation
- [ ] The app is **LedGrab** — not tied to WLED specifically. WLED is just one of many supported output protocols
- [ ] Audit: i18n keys, page titles, tray labels, installer text, pyproject.toml description, README, CLAUDE.md, context files, API docs
- [ ] Rename `wled_controller` package → decide on new package name (e.g. `ledgrab`)
- [ ] Update import paths, entry points, config references, build scripts, Docker, CI/CD
- [ ] **Migration required** if renaming storage paths or config keys (see data migration policy in CLAUDE.md)
---
# Color Strip Source Improvements
## New Source Types
- [ ] **`weather`** — Weather-reactive ambient: maps weather conditions (rain, snow, clear, storm) to colors/animations via API
- [ ] **`music_sync`** — Beat-synced patterns: BPM detection, energy envelope, drop detection (higher-level than raw `audio`)
- [ ] **`math_wave`** — Mathematical wave generator: user-defined sine/triangle/sawtooth expressions, superposition
- [ ] **`text_scroll`** — Scrolling text marquee: bitmap font rendering, static text or RSS/API data source *(delayed)*
### Discuss: `home_assistant`
Need to research HAOS communication options first (WebSocket API, REST API, MQTT, etc.) before deciding scope.
### Deferred
- `image` — Static image sampler *(not now)*
- `clock` — Time display *(not now)*
## Improvements to Existing Sources
### `effect` (now 12 types)
- [x] Add effects: rain, comet, bouncing ball, fireworks, sparkle rain, lava lamp, wave interference
- [x] Custom palette support: user-defined [[pos,R,G,B],...] stops via JSON textarea
- [ ] Custom palette editor: replace raw JSON textarea with a proper visual editor (reuse gradient editor pattern with color pickers + position sliders)
### `gradient`
- [x] Noise-perturbed gradient: value noise displacement on stop positions (`noise_perturb` animation type)
- [x] Gradient hue rotation: `hue_rotate` animation type — preserves S/V, rotates H
- [x] Easing functions between stops: linear, ease_in_out (smoothstep), step, cubic
### `audio`
- [ ] New audio source type: band extractor (bass/mid/treble split) — responsibility of audio source layer, not CSS
- [ ] Peak hold indicator: global option on audio source (not per-mode), configurable decay time
### `daylight`
- [x] Longitude support for accurate solar position (NOAA solar equations)
- [x] Season awareness (day-of-year drives sunrise/sunset via solar declination)
### `candlelight`
- [x] Wind simulation: correlated flicker bursts across all candles (wind_strength 0.0-2.0)
- [x] Candle type presets: taper (steady), votive (flickery), bonfire (chaotic) — applied at render time
- [x] Wax drip effect: localized brightness dips with fade-in/fade-out recovery
### `composite`
- [ ] Allow nested composites (with cycle detection)
- [ ] More blend modes: overlay, soft light, hard light, difference, exclusion
- [ ] Per-layer LED range masks
### `notification`
- [x] Chase effect (light bounces across strip with glowing tail)
- [x] Gradient flash (bright center fades to edges, exponential decay)
- [x] Queue priority levels (color_override = high priority, interrupts current)
### `api_input`
- [ ] Crossfade transition when new data arrives
- [ ] Interpolation when incoming LED count differs from strip count
- [ ] Last-write-wins from any client (no multi-source blending)
## Architectural / Pipeline
### Processing Templates (CSPT)
- [x] HSL shift filter (hue rotation + lightness adjustment)
- [x] ~~Color temperature filter~~ — already exists as `color_correction`
- [x] Contrast filter
- [x] ~~Saturation filter~~ — already exists
- [x] ~~Pixelation filter~~ — already exists as `pixelate`
- [x] Temporal blur filter (blend frames over time)
### Transition Engine
Needs deeper design discussion. Likely a new entity type `ColorStripSourceTransition` that defines how source switches happen (crossfade, wipe, etc.). Interacts with automations when they switch a target's active source.
### Deferred
- Global BPM sync *(not sure)*
- Recording/playback *(not now)*
- Source preview in editor modal *(not needed — overlay preview on devices is sufficient)*
---
## Remaining Open Discussion
1. **`home_assistant` source** — Need to research HAOS communication protocols first
2. **Transition engine** — Design as `ColorStripSourceTransition` entity: what transition types? (crossfade, wipe, dissolve?) How does a target reference its transition config? How do automations trigger it?

View File

@@ -5,6 +5,7 @@ shows a system-tray icon with **Show UI** / **Exit** actions.
""" """
import asyncio import asyncio
import os
import sys import sys
import threading import threading
import time import time
@@ -36,6 +37,11 @@ def _open_browser(port: int, delay: float = 2.0) -> None:
webbrowser.open(f"http://localhost:{port}") webbrowser.open(f"http://localhost:{port}")
def _is_restart() -> bool:
"""Detect if this is a restart (vs first launch)."""
return os.environ.get("WLED_RESTART", "") == "1"
def main() -> None: def main() -> None:
config = get_config() config = get_config()
@@ -60,7 +66,8 @@ def main() -> None:
) )
server_thread.start() server_thread.start()
# Browser after a short delay # Browser after a short delay (skip on restart — user already has a tab)
if not _is_restart():
threading.Thread( threading.Thread(
target=_open_browser, target=_open_browser,
args=(config.server.port,), args=(config.server.port,),

View File

@@ -65,6 +65,7 @@ class TrayManager:
return return
self._icon.stop() self._icon.stop()
self._on_exit() self._on_exit()
os.environ["WLED_RESTART"] = "1"
os.execv(sys.executable, [sys.executable, "-m", "wled_controller"]) os.execv(sys.executable, [sys.executable, "-m", "wled_controller"])
def _shutdown(self, icon: "pystray.Icon", item: "pystray.MenuItem") -> None: def _shutdown(self, icon: "pystray.Icon", item: "pystray.MenuItem") -> None: