soulsync/webui
Broque Thomas 9f63280677 Extract source-picker into shared createSearchController factory
Both the Search page and the global search widget ran the same source-
picker state machine (query, activeSource, per-query cache, fallbacks,
loading set, configured-source discovery, NDJSON streaming for YouTube,
default-source fall-forward). That was ~380 lines of near-duplicated
logic split across search.js and downloads.js, which meant every bug fix
or behavior tweak had to land twice and inevitably drifted.

createSearchController in shared-helpers.js now owns all of that. Each
surface passes per-surface wiring — a source-row DOM element, a CSS
class prefix, and callbacks for Soulseek handoff + unconfigured-source
redirect — and consumes the controller's state via an onStateChange
callback. The surface files shrink to their actual responsibilities:
results rendering, click handlers, and surface-specific visibility.

Zero UX change. Every keystroke, icon click, cache hit, rate-limit
fallback, and unconfigured-source redirect behaves identically to before
— verified via full pytest suite (395 passed) and node --check on all
three files.

WHATS_NEW entry added under the 2.40 unified-search bucket.
2026-04-23 17:28:16 -07:00
..
static Extract source-picker into shared createSearchController factory 2026-04-23 17:28:16 -07:00
index.html Global search bar: ambient accent-glow aura under the pill 2026-04-23 17:28:16 -07:00