perf(frontend): use startTransition for selection updates to keep UI responsive on large sets
This commit is contained in:
parent
1d290bdfa6
commit
017ba31d83
@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useRef, useEffect, useCallback, useMemo, memo } from 'react';
|
import React, { useState, useRef, useEffect, useCallback, useMemo, memo, startTransition } from 'react';
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Flex,
|
Flex,
|
||||||
@ -224,6 +224,7 @@ export const PaginatedSongList: React.FC<PaginatedSongListProps> = memo(({
|
|||||||
// const allPlaylists = useMemo(() => getAllPlaylists(playlists), [playlists, getAllPlaylists]);
|
// const allPlaylists = useMemo(() => getAllPlaylists(playlists), [playlists, getAllPlaylists]);
|
||||||
|
|
||||||
const toggleSelection = useCallback((songId: string) => {
|
const toggleSelection = useCallback((songId: string) => {
|
||||||
|
startTransition(() => {
|
||||||
setSelectedSongs(prev => {
|
setSelectedSongs(prev => {
|
||||||
const newSelection = new Set(prev);
|
const newSelection = new Set(prev);
|
||||||
if (newSelection.has(songId)) {
|
if (newSelection.has(songId)) {
|
||||||
@ -233,12 +234,14 @@ export const PaginatedSongList: React.FC<PaginatedSongListProps> = memo(({
|
|||||||
}
|
}
|
||||||
return newSelection;
|
return newSelection;
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Range selection using shift-click between last selected and current
|
// Range selection using shift-click between last selected and current
|
||||||
const toggleSelectionRange = useCallback((fromIndex: number, toIndex: number, checked: boolean) => {
|
const toggleSelectionRange = useCallback((fromIndex: number, toIndex: number, checked: boolean) => {
|
||||||
if (fromIndex === null || toIndex === null) return;
|
if (fromIndex === null || toIndex === null) return;
|
||||||
const [start, end] = fromIndex < toIndex ? [fromIndex, toIndex] : [toIndex, fromIndex];
|
const [start, end] = fromIndex < toIndex ? [fromIndex, toIndex] : [toIndex, fromIndex];
|
||||||
|
startTransition(() => {
|
||||||
setSelectedSongs(prev => {
|
setSelectedSongs(prev => {
|
||||||
const next = new Set(prev);
|
const next = new Set(prev);
|
||||||
for (let i = start; i <= end; i++) {
|
for (let i = start; i <= end; i++) {
|
||||||
@ -248,6 +251,7 @@ export const PaginatedSongList: React.FC<PaginatedSongListProps> = memo(({
|
|||||||
}
|
}
|
||||||
return next;
|
return next;
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}, [songs]);
|
}, [songs]);
|
||||||
|
|
||||||
const handleCheckboxToggle = useCallback((index: number, checked: boolean, shift: boolean) => {
|
const handleCheckboxToggle = useCallback((index: number, checked: boolean, shift: boolean) => {
|
||||||
@ -262,20 +266,19 @@ export const PaginatedSongList: React.FC<PaginatedSongListProps> = memo(({
|
|||||||
}, [songs, toggleSelection, toggleSelectionRange]);
|
}, [songs, toggleSelection, toggleSelectionRange]);
|
||||||
|
|
||||||
const toggleSelectAll = useCallback(() => {
|
const toggleSelectAll = useCallback(() => {
|
||||||
|
startTransition(() => {
|
||||||
setSelectedSongs(prev => {
|
setSelectedSongs(prev => {
|
||||||
const noneSelected = prev.size === 0;
|
const noneSelected = prev.size === 0;
|
||||||
const allSelected = prev.size === songs.length && songs.length > 0;
|
const allSelected = prev.size === songs.length && songs.length > 0;
|
||||||
if (noneSelected) {
|
if (noneSelected) {
|
||||||
// Select all from empty state
|
|
||||||
return new Set(songs.map(s => s.id));
|
return new Set(songs.map(s => s.id));
|
||||||
}
|
}
|
||||||
if (allSelected) {
|
if (allSelected) {
|
||||||
// Deselect all when everything is selected
|
|
||||||
return new Set();
|
return new Set();
|
||||||
}
|
}
|
||||||
// Mixed/some selected: clear first, then select all (single state update reflects final state)
|
|
||||||
return new Set(songs.map(s => s.id));
|
return new Set(songs.map(s => s.id));
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}, [songs]);
|
}, [songs]);
|
||||||
|
|
||||||
const handleBulkAddToPlaylist = useCallback((playlistName: string) => {
|
const handleBulkAddToPlaylist = useCallback((playlistName: string) => {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user