refactor(utils): group utils/ files into topic folders (Phase L, part 1) (#689)

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.
This commit is contained in:
Frank Stellmacher
2026-05-14 14:27:44 +02:00
committed by GitHub
parent 2409a1fec8
commit 7a7a9f5e6b
324 changed files with 551 additions and 551 deletions
+161
View File
@@ -0,0 +1,161 @@
import { useSyncExternalStore } from 'react';
export type PerfProbeFlags = {
/** On-screen rAF-based FPS counter (Performance Probe). */
showFpsOverlay: boolean;
disableWaveformCanvas: boolean;
disablePlayerProgressUi: boolean;
disableMarqueeScroll: boolean;
disableBackdropBlur: boolean;
disableCssAnimations: boolean;
disableOverlayScrollbars: boolean;
disableTooltipPortal: boolean;
disableQueuePanelMount: boolean;
disableBackgroundPolling: boolean;
disableMainRouteContentMount: boolean;
disableMainstageHero: boolean;
disableMainstageRails: boolean;
disableMainstageGridCards: boolean;
disableMainstageVirtualLists: boolean;
disableMainstageStickyHeader: boolean;
disableMainstageHeroBackdrop: boolean;
disableMainstageRailArtwork: boolean;
disableMainstageRailInteractivity: boolean;
disableHomeAlbumRows: boolean;
disableHomeSongRails: boolean;
disableHomeRailArtwork: boolean;
disableHomeArtworkFx: boolean;
disableHomeArtworkClip: boolean;
};
const STORAGE_KEY = 'psysonic_perf_probe_flags_v1';
const DEFAULT_FLAGS: PerfProbeFlags = {
showFpsOverlay: false,
disableWaveformCanvas: false,
disablePlayerProgressUi: false,
disableMarqueeScroll: false,
disableBackdropBlur: false,
disableCssAnimations: false,
disableOverlayScrollbars: false,
disableTooltipPortal: false,
disableQueuePanelMount: false,
disableBackgroundPolling: false,
disableMainRouteContentMount: false,
disableMainstageHero: false,
disableMainstageRails: false,
disableMainstageGridCards: false,
disableMainstageVirtualLists: false,
disableMainstageStickyHeader: false,
disableMainstageHeroBackdrop: false,
disableMainstageRailArtwork: false,
disableMainstageRailInteractivity: false,
disableHomeAlbumRows: false,
disableHomeSongRails: false,
disableHomeRailArtwork: false,
disableHomeArtworkFx: false,
disableHomeArtworkClip: false,
};
let flags: PerfProbeFlags = { ...DEFAULT_FLAGS };
const listeners = new Set<() => void>();
function safeParseFlags(raw: string | null): Partial<PerfProbeFlags> {
if (!raw) return {};
try {
const parsed = JSON.parse(raw) as Partial<PerfProbeFlags>;
return parsed ?? {};
} catch {
return {};
}
}
function applyFlagsToDom(next: PerfProbeFlags): void {
if (typeof document === 'undefined') return;
const root = document.documentElement;
root.dataset.perfDisableWaveform = next.disableWaveformCanvas ? 'true' : 'false';
root.dataset.perfDisablePlayerProgressUi = next.disablePlayerProgressUi ? 'true' : 'false';
root.dataset.perfDisableMarquee = next.disableMarqueeScroll ? 'true' : 'false';
root.dataset.perfDisableBlur = next.disableBackdropBlur ? 'true' : 'false';
root.dataset.perfDisableAnimations = next.disableCssAnimations ? 'true' : 'false';
root.dataset.perfDisableOverlayScroll = next.disableOverlayScrollbars ? 'true' : 'false';
root.dataset.perfDisableTooltipPortal = next.disableTooltipPortal ? 'true' : 'false';
root.dataset.perfDisableQueuePanel = next.disableQueuePanelMount ? 'true' : 'false';
root.dataset.perfDisableBackgroundPolling = next.disableBackgroundPolling ? 'true' : 'false';
root.dataset.perfDisableMainRoute = next.disableMainRouteContentMount ? 'true' : 'false';
root.dataset.perfDisableMainstageHero = next.disableMainstageHero ? 'true' : 'false';
root.dataset.perfDisableMainstageRails = next.disableMainstageRails ? 'true' : 'false';
root.dataset.perfDisableMainstageGrid = next.disableMainstageGridCards ? 'true' : 'false';
root.dataset.perfDisableMainstageVirtual = next.disableMainstageVirtualLists ? 'true' : 'false';
root.dataset.perfDisableMainstageHeader = next.disableMainstageStickyHeader ? 'true' : 'false';
root.dataset.perfDisableMainstageHeroBackdrop = next.disableMainstageHeroBackdrop ? 'true' : 'false';
root.dataset.perfDisableMainstageRailArtwork = next.disableMainstageRailArtwork ? 'true' : 'false';
root.dataset.perfDisableMainstageRailInteractivity = next.disableMainstageRailInteractivity ? 'true' : 'false';
root.dataset.perfDisableHomeAlbumRows = next.disableHomeAlbumRows ? 'true' : 'false';
root.dataset.perfDisableHomeSongRails = next.disableHomeSongRails ? 'true' : 'false';
root.dataset.perfDisableHomeRailArtwork = next.disableHomeRailArtwork ? 'true' : 'false';
root.dataset.perfDisableHomeArtworkFx = next.disableHomeArtworkFx ? 'true' : 'false';
root.dataset.perfDisableHomeArtworkClip = next.disableHomeArtworkClip ? 'true' : 'false';
}
function persistFlags(next: PerfProbeFlags): void {
if (typeof window === 'undefined') return;
try {
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(next));
} catch {
// Ignore storage errors; runtime state still works.
}
}
function emit(): void {
listeners.forEach(fn => fn());
}
function setFlags(next: PerfProbeFlags): void {
flags = next;
applyFlagsToDom(flags);
persistFlags(flags);
emit();
}
function initFlags(): void {
if (typeof window === 'undefined') return;
const fromStorage = safeParseFlags(window.localStorage.getItem(STORAGE_KEY));
flags = {
...DEFAULT_FLAGS,
...fromStorage,
};
applyFlagsToDom(flags);
}
initFlags();
export function getPerfProbeFlags(): PerfProbeFlags {
return flags;
}
export function subscribePerfProbeFlags(cb: () => void): () => void {
listeners.add(cb);
return () => listeners.delete(cb);
}
export function setPerfProbeFlag<K extends keyof PerfProbeFlags>(key: K, value: PerfProbeFlags[K]): void {
setFlags({ ...flags, [key]: value });
}
export function resetPerfProbeFlags(): void {
setFlags({ ...DEFAULT_FLAGS });
}
export function usePerfProbeFlags(): PerfProbeFlags {
return useSyncExternalStore(subscribePerfProbeFlags, getPerfProbeFlags, () => DEFAULT_FLAGS);
}
/** Subscribe to a single probe flag so unrelated toggles do not re-render the consumer. */
export function usePerfProbeFlag<K extends keyof PerfProbeFlags>(key: K): PerfProbeFlags[K] {
return useSyncExternalStore(
subscribePerfProbeFlags,
() => getPerfProbeFlags()[key],
() => DEFAULT_FLAGS[key],
);
}
+25
View File
@@ -0,0 +1,25 @@
/**
* Hot-path counters for the Performance Probe modal. In production builds these
* no-op unless the probe is open (`data-psy-perf-probe-open` on the root), so
* normal playback does not pay for object churn. Dev builds always record.
*/
const ROOT_FLAG = 'psyPerfProbeOpen';
export function setPerfProbeTelemetryActive(active: boolean): void {
if (typeof document === 'undefined') return;
if (active) document.documentElement.dataset[ROOT_FLAG] = 'true';
else delete document.documentElement.dataset[ROOT_FLAG];
}
function shouldRecordPerfCounters(): boolean {
if (import.meta.env.DEV) return true;
if (typeof document === 'undefined') return false;
return document.documentElement.dataset[ROOT_FLAG] === 'true';
}
export function bumpPerfCounter(name: string): void {
if (!shouldRecordPerfCounters()) return;
const w = globalThis as unknown as { __psyPerfCounters?: Record<string, number> };
const c = w.__psyPerfCounters ?? (w.__psyPerfCounters = Object.create(null) as Record<string, number>);
c[name] = (c[name] ?? 0) + 1;
}