fix(reorder): only show end-of-list drop zone during active reorder drag; reset hover indicators on drag end

This commit is contained in:
Geert Rademakes 2025-08-08 14:53:26 +02:00
parent d0a83a85f5
commit ac52441dd1

View File

@ -171,6 +171,7 @@ export const PaginatedSongList: React.FC<PaginatedSongListProps> = memo(({
const timeoutRef = useRef<NodeJS.Timeout | null>(null); const timeoutRef = useRef<NodeJS.Timeout | null>(null);
const [dragHoverIndex, setDragHoverIndex] = useState<number | null>(null); const [dragHoverIndex, setDragHoverIndex] = useState<number | null>(null);
const [endDropHover, setEndDropHover] = useState<boolean>(false); const [endDropHover, setEndDropHover] = useState<boolean>(false);
const [isReorderDragging, setIsReorderDragging] = useState<boolean>(false);
// Store current values in refs to avoid stale closures // Store current values in refs to avoid stale closures
const hasMoreRef = useRef(hasMore); const hasMoreRef = useRef(hasMore);
@ -258,6 +259,9 @@ export const PaginatedSongList: React.FC<PaginatedSongListProps> = memo(({
const handleDragEnd = useCallback(() => { const handleDragEnd = useCallback(() => {
setIsDragging(false); setIsDragging(false);
setIsReorderDragging(false);
setEndDropHover(false);
setDragHoverIndex(null);
dragSelectionRef.current = null; dragSelectionRef.current = null;
}, []); }, []);
@ -280,7 +284,7 @@ export const PaginatedSongList: React.FC<PaginatedSongListProps> = memo(({
e.preventDefault(); e.preventDefault();
setDragHoverIndex(index); setDragHoverIndex(index);
}} }}
onRowDrop={async (e: React.DragEvent) => { onRowDrop={async (e: React.DragEvent) => {
if (!onReorder || !currentPlaylist || selectedSongs.size > 0) return; if (!onReorder || !currentPlaylist || selectedSongs.size > 0) return;
e.preventDefault(); e.preventDefault();
const fromId = e.dataTransfer.getData('text/song-id'); const fromId = e.dataTransfer.getData('text/song-id');
@ -303,7 +307,8 @@ export const PaginatedSongList: React.FC<PaginatedSongListProps> = memo(({
console.debug('[Reorder] move request', { playlist: currentPlaylist, fromId, toId }); console.debug('[Reorder] move request', { playlist: currentPlaylist, fromId, toId });
await api.moveTrackInPlaylist(currentPlaylist, fromId, toId); await api.moveTrackInPlaylist(currentPlaylist, fromId, toId);
await onReorder(songs.map(s => s.id)); // trigger refresh via parent await onReorder(songs.map(s => s.id)); // trigger refresh via parent
setDragHoverIndex(null); setDragHoverIndex(null);
setIsReorderDragging(false);
}} }}
onRowDragStartCapture={(e: React.DragEvent) => { onRowDragStartCapture={(e: React.DragEvent) => {
// Provide a simple id for intra-list reorder // Provide a simple id for intra-list reorder
@ -313,6 +318,7 @@ export const PaginatedSongList: React.FC<PaginatedSongListProps> = memo(({
// Explicitly set effect to move for better UX // Explicitly set effect to move for better UX
try { e.dataTransfer.effectAllowed = 'move'; } catch {} try { e.dataTransfer.effectAllowed = 'move'; } catch {}
try { e.dataTransfer.dropEffect = 'move'; } catch {} try { e.dataTransfer.dropEffect = 'move'; } catch {}
setIsReorderDragging(true);
}} }}
/> />
)); ));
@ -503,7 +509,7 @@ export const PaginatedSongList: React.FC<PaginatedSongListProps> = memo(({
</Box> </Box>
{/* Drop zone to move item to end of playlist */} {/* Drop zone to move item to end of playlist */}
{onReorder && currentPlaylist && selectedSongs.size === 0 && ( {onReorder && currentPlaylist && selectedSongs.size === 0 && isReorderDragging && (
<Box <Box
onDragOver={(e: React.DragEvent) => { onDragOver={(e: React.DragEvent) => {
e.preventDefault(); e.preventDefault();
@ -521,7 +527,9 @@ export const PaginatedSongList: React.FC<PaginatedSongListProps> = memo(({
await api.moveTrackInPlaylist(currentPlaylist, fromId); await api.moveTrackInPlaylist(currentPlaylist, fromId);
await onReorder(songs.map(s => s.id)); await onReorder(songs.map(s => s.id));
setEndDropHover(false); setEndDropHover(false);
setIsReorderDragging(false);
}} }}
onDragEnd={handleDragEnd}
position="relative" position="relative"
height="28px" height="28px"
mt={1} mt={1}