mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-28 10:06:47 +00:00
8ff630cb5c
* refactor(queue-panel): H4 — extract helpers + Save/LoadPlaylistModal Pure code-move: formatTime, formatQueueReplayGainParts, renderStars and the DurationMode type → utils/queuePanelHelpers.tsx; the two playlist modals → own files under components/queuePanel/. QueuePanel.tsx: 1256 → 1104 LOC. * refactor(queue-panel): H4 — extract QueueHeader Pure code-move: the title/count/duration/collapse-button header → its own component file. No prop or behaviour changes. QueuePanel.tsx: 1104 → 1004 LOC. * refactor(queue-panel): H4 — extract QueueCurrentTrack + QueueLufsTargetMenu The currently-playing track block (cover, info, replay-gain / LUFS badge with its target-listbox portal) moves into two own files. Pure code-move via prop plumbing. setLoudnessTargetLufs is typed as LoudnessLufsPreset throughout the new components. QueuePanel.tsx: 1004 → 812 LOC. * refactor(queue-panel): H4 — extract useQueuePanelDrag hook Moves the psy-drag wiring (hit-test registration, drop-inside dispatch for song/songs/album/queue_reorder payloads, drop-outside removal) into its own hook. Drops the dead isRadioDrag variable since the parsedData.type === 'radio' guard inside onPsyDrop already handles that case. QueuePanel.tsx: 812 → 715 LOC. * refactor(queue-panel): H4 — extract useQueueLufsTgtPopover hook Pulls the LUFS-target popover open-state, button/menu refs, fixed-position recompute on open/resize/scroll, and auto-close-when-RG-collapses out of QueuePanel. QueuePanel.tsx: 715 → 662 LOC. * refactor(queue-panel): H4 — extract QueueToolbar The toolbar-button switch (shuffle/save/load/share/clear/gapless/crossfade/ infinite) and the crossfade popover (with its close-on-outside-click effect) move into one component. crossfadeBtnRef / crossfadePopoverRef and showCrossfadePopover state are now component-local — QueuePanel no longer sees them. QueuePanel.tsx: 662 → 541 LOC. * refactor(queue-panel): H4 — extract QueueList The OverlayScrollArea + queue.map block (with track rows, lucky-mix dice overlay, and radio/auto-added section dividers) moves into its own component. PlayerState['contextMenu'] + PlayerState['playTrack'] are re-used for prop typing, the local StartDrag alias matches the DragDropContext signature. QueuePanel.tsx: 541 → 434 LOC. * refactor(queue-panel): H4 — extract QueueTabBar + useQueueAutoScroll, final cleanup QueueTabBar is the bottom queue/lyrics/info tab switcher. useQueueAutoScroll groups the three list-scroll effects (publish scrollTop reader, restore pending snapshot, scroll next track into view on advance). Drops the dead toggleQueue and replayGainMode selectors plus the now-unused Play, Radio, MicVocal, ListMusic, Info imports and OverlayScrollArea. QueuePanel.tsx: 434 → 383 LOC. Every new file under 400.
66 lines
1.8 KiB
TypeScript
66 lines
1.8 KiB
TypeScript
import React from 'react';
|
|
import { createPortal } from 'react-dom';
|
|
import type { LoudnessLufsPreset } from '../../store/authStoreTypes';
|
|
|
|
interface Props {
|
|
menuRef: React.RefObject<HTMLDivElement | null>;
|
|
popStyle: React.CSSProperties;
|
|
authLoudnessTargetLufs: LoudnessLufsPreset;
|
|
setLoudnessTargetLufs: (v: LoudnessLufsPreset) => void;
|
|
onClose: () => void;
|
|
}
|
|
|
|
const LUFS_TARGETS: readonly LoudnessLufsPreset[] = [-10, -12, -14, -16] as const;
|
|
|
|
export function QueueLufsTargetMenu({
|
|
menuRef, popStyle, authLoudnessTargetLufs, setLoudnessTargetLufs, onClose,
|
|
}: Props) {
|
|
return createPortal(
|
|
<div
|
|
ref={menuRef}
|
|
className="queue-lufs-tgt-menu"
|
|
style={{
|
|
...popStyle,
|
|
background: 'var(--bg-card)',
|
|
border: '1px solid var(--border, rgba(255,255,255,0.12))',
|
|
borderRadius: 8,
|
|
boxShadow: '0 6px 24px rgba(0,0,0,0.35)',
|
|
padding: 6,
|
|
overflow: 'auto',
|
|
}}
|
|
role="listbox"
|
|
aria-label="LUFS target"
|
|
onClick={e => e.stopPropagation()}
|
|
>
|
|
{LUFS_TARGETS.map((v) => (
|
|
<button
|
|
key={v}
|
|
type="button"
|
|
onClick={e => {
|
|
e.stopPropagation();
|
|
if (v !== authLoudnessTargetLufs) {
|
|
setLoudnessTargetLufs(v);
|
|
}
|
|
onClose();
|
|
}}
|
|
style={{
|
|
display: 'block',
|
|
width: '100%',
|
|
textAlign: 'left',
|
|
padding: '6px 8px',
|
|
borderRadius: 6,
|
|
border: 'none',
|
|
background: v === authLoudnessTargetLufs ? 'color-mix(in srgb, var(--accent) 18%, transparent)' : 'transparent',
|
|
color: 'var(--text-primary)',
|
|
cursor: 'pointer',
|
|
font: 'inherit',
|
|
}}
|
|
>
|
|
{v} LUFS
|
|
</button>
|
|
))}
|
|
</div>,
|
|
document.body,
|
|
);
|
|
}
|