111 of 122 top-level src/utils/ files move into 16 topic folders (audio,
cache, cover, share, server, playback, playlist, deviceSync, waveform,
mix, format, export, changelog, ui, perf, componentHelpers). True
singletons with no cluster stay at the utils/ root.
Pure file-move: a path-aware codemod rewrote 539 relative-import
specifiers across 275 files; no logic touched. The hot-path coverage
gate list (.github/frontend-hot-path-files.txt) is updated to the new
paths for the 11 gated utils files — a mechanical consequence of the
move, not a CI change. tsc is green.
* refactor(internet-radio): G.86.1 — extract RadioToolbar + AlphabetFilterBar
First cut on InternetRadio.tsx: pulled the two header bars into
their own files under src/components/internetRadio/. RadioToolbar
exports the RadioSortBy type alias so the page state and the
toolbar share the same union. AlphabetFilterBar owns the
A-Z + # key list internally.
Pure code move.
* refactor(internet-radio): G.86.2 — extract RadioCard
Pulled the single radio-station card component (cover, live overlay,
play/delete buttons, name + edit/favourite/homepage chip row) into
its own file. It owns its drag source + the psy-drop listener that
fires onDropOnto with the cursor-side (before/after).
Pure code move.
* refactor(internet-radio): G.86.3 — extract RadioEditModal
Pulled the create/edit-station modal (cover preview + change/remove,
name + stream URL + homepage URL fields, save spinner) into its own
file. station=null means "create new". Pure code move.
* refactor(internet-radio): G.86.4 — extract RadioDirectoryModal
Pulled the radio-browser directory modal (top-stations preload,
debounced search, IntersectionObserver-driven pagination, favicon
+ add-station flow with cover upload from favicon URL) into its
own file. Pure code move.
InternetRadio.tsx is now 299 LOC — every subcomponent lives in
src/components/internetRadio/.