mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-22 14:35:41 +00:00
fix(settings): lyrics-sources DnD survives mode toggle
The psy-drop listener was attached in a useEffect keyed only on
setLyricsSources, so when the container was unmounted by the
{lyricsMode === 'standard' && …} wrapper (switching to YouLyPlus and
back), the listener stayed bound to the old DOM node and drag-to-reorder
silently did nothing.
Switch the container ref to a callback-ref stored in state, so the
effect re-runs on mount/unmount and always listens on the current DOM
node.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+10
-9
@@ -2684,7 +2684,9 @@ function LyricsSourcesCustomizer() {
|
|||||||
const lyricsStaticOnly = useAuthStore(s => s.lyricsStaticOnly);
|
const lyricsStaticOnly = useAuthStore(s => s.lyricsStaticOnly);
|
||||||
const setLyricsStaticOnly = useAuthStore(s => s.setLyricsStaticOnly);
|
const setLyricsStaticOnly = useAuthStore(s => s.setLyricsStaticOnly);
|
||||||
const { isDragging: isPsyDragging } = useDragDrop();
|
const { isDragging: isPsyDragging } = useDragDrop();
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
// useState (not useRef) so the listener-effect re-runs when the container
|
||||||
|
// gets unmounted/remounted by the {lyricsMode === 'standard'} wrapper.
|
||||||
|
const [containerEl, setContainerEl] = useState<HTMLDivElement | null>(null);
|
||||||
const [dropTarget, setDropTarget] = useState<LyricsDropTarget>(null);
|
const [dropTarget, setDropTarget] = useState<LyricsDropTarget>(null);
|
||||||
const dropTargetRef = useRef<LyricsDropTarget>(null);
|
const dropTargetRef = useRef<LyricsDropTarget>(null);
|
||||||
const sourcesRef = useRef(lyricsSources);
|
const sourcesRef = useRef(lyricsSources);
|
||||||
@@ -2695,8 +2697,7 @@ function LyricsSourcesCustomizer() {
|
|||||||
}, [isPsyDragging]);
|
}, [isPsyDragging]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const el = containerRef.current;
|
if (!containerEl) return;
|
||||||
if (!el) return;
|
|
||||||
const onPsyDrop = (e: Event) => {
|
const onPsyDrop = (e: Event) => {
|
||||||
const detail = (e as CustomEvent).detail;
|
const detail = (e as CustomEvent).detail;
|
||||||
if (!detail?.data) return;
|
if (!detail?.data) return;
|
||||||
@@ -2717,13 +2718,13 @@ function LyricsSourcesCustomizer() {
|
|||||||
next.splice(insertBefore > fromIdx ? insertBefore - 1 : insertBefore, 0, moved);
|
next.splice(insertBefore > fromIdx ? insertBefore - 1 : insertBefore, 0, moved);
|
||||||
setLyricsSources(next);
|
setLyricsSources(next);
|
||||||
};
|
};
|
||||||
el.addEventListener('psy-drop', onPsyDrop);
|
containerEl.addEventListener('psy-drop', onPsyDrop);
|
||||||
return () => el.removeEventListener('psy-drop', onPsyDrop);
|
return () => containerEl.removeEventListener('psy-drop', onPsyDrop);
|
||||||
}, [setLyricsSources]);
|
}, [containerEl, setLyricsSources]);
|
||||||
|
|
||||||
const handleMouseMove = (e: React.MouseEvent) => {
|
const handleMouseMove = (e: React.MouseEvent) => {
|
||||||
if (!isPsyDragging || !containerRef.current) return;
|
if (!isPsyDragging || !containerEl) return;
|
||||||
const rows = containerRef.current.querySelectorAll<HTMLElement>('[data-lyrics-idx]');
|
const rows = containerEl.querySelectorAll<HTMLElement>('[data-lyrics-idx]');
|
||||||
let target: LyricsDropTarget = null;
|
let target: LyricsDropTarget = null;
|
||||||
for (const row of rows) {
|
for (const row of rows) {
|
||||||
const rect = row.getBoundingClientRect();
|
const rect = row.getBoundingClientRect();
|
||||||
@@ -2817,7 +2818,7 @@ function LyricsSourcesCustomizer() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{lyricsMode === 'standard' && (
|
{lyricsMode === 'standard' && (
|
||||||
<div className="settings-card" style={{ padding: '4px 0' }} ref={containerRef} onMouseMove={handleMouseMove}>
|
<div className="settings-card" style={{ padding: '4px 0' }} ref={setContainerEl} onMouseMove={handleMouseMove}>
|
||||||
{lyricsSources.map((src, i) => {
|
{lyricsSources.map((src, i) => {
|
||||||
const label = t(LYRICS_SOURCE_LABEL_KEYS[src.id]);
|
const label = t(LYRICS_SOURCE_LABEL_KEYS[src.id]);
|
||||||
const isBefore = isPsyDragging && dropTarget?.idx === i && dropTarget.before;
|
const isBefore = isPsyDragging && dropTarget?.idx === i && dropTarget.before;
|
||||||
|
|||||||
Reference in New Issue
Block a user