perf: Streamline playlist switching flow for faster, cleaner transitions - Clear all state immediately (songs, totalSongs, totalDuration) on playlist switch - Combine switching and loading states into single spinner with dynamic text - Remove duplicate switching indicators to prevent UI flicker - Reset switching state when loading starts for immediate transition - Eliminates confusing flow: switching → old data → 0 of X → loading → new data - Now shows: switching → loading → new data (much cleaner)
This commit is contained in:
parent
90bcd10ed9
commit
966240b0d1
@ -154,12 +154,12 @@ export default function RekordboxReader() {
|
|||||||
}
|
}
|
||||||
}, [currentPlaylist, playlists, navigate, xmlLoading]);
|
}, [currentPlaylist, playlists, navigate, xmlLoading]);
|
||||||
|
|
||||||
// Reset switching state when songs are loaded
|
// Reset switching state when loading starts (immediate transition)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (songs.length > 0 && isSwitchingPlaylist) {
|
if (songsLoading && isSwitchingPlaylist) {
|
||||||
setIsSwitchingPlaylist(false);
|
setIsSwitchingPlaylist(false);
|
||||||
}
|
}
|
||||||
}, [songs.length, isSwitchingPlaylist]);
|
}, [songsLoading, isSwitchingPlaylist]);
|
||||||
|
|
||||||
const handlePlaylistSelect = (name: string) => {
|
const handlePlaylistSelect = (name: string) => {
|
||||||
// Set switching state immediately for visual feedback
|
// Set switching state immediately for visual feedback
|
||||||
|
|||||||
@ -409,12 +409,12 @@ export const PaginatedSongList: React.FC<PaginatedSongListProps> = memo(({
|
|||||||
<Flex direction="column" gap={2}>
|
<Flex direction="column" gap={2}>
|
||||||
{songItems}
|
{songItems}
|
||||||
|
|
||||||
{/* Loading indicator for infinite scroll */}
|
{/* Loading indicator for infinite scroll or playlist switching */}
|
||||||
{loading && (
|
{(loading || isSwitchingPlaylist) && (
|
||||||
<Flex justify="center" align="center" p={6} key="loading-spinner" gap={3}>
|
<Flex justify="center" align="center" p={6} key="loading-spinner" gap={3}>
|
||||||
<Spinner size="md" color="blue.400" />
|
<Spinner size="md" color="blue.400" />
|
||||||
<Text color="gray.400" fontSize="sm">
|
<Text color="gray.400" fontSize="sm">
|
||||||
Loading more songs...
|
{isSwitchingPlaylist ? 'Switching playlist...' : 'Loading more songs...'}
|
||||||
</Text>
|
</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
)}
|
)}
|
||||||
@ -440,21 +440,12 @@ export const PaginatedSongList: React.FC<PaginatedSongListProps> = memo(({
|
|||||||
</Flex>
|
</Flex>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* No results message or playlist switching indicator */}
|
{/* No results message */}
|
||||||
{!loading && songs.length === 0 && (
|
{!loading && !isSwitchingPlaylist && songs.length === 0 && (
|
||||||
<Flex justify="center" p={8} key="no-results" direction="column" align="center" gap={3}>
|
<Flex justify="center" p={8} key="no-results" direction="column" align="center" gap={3}>
|
||||||
{isSwitchingPlaylist ? (
|
<Text color="gray.500">
|
||||||
<>
|
{searchQuery ? 'No songs found matching your search' : 'No songs available'}
|
||||||
<Spinner size="md" color="blue.400" />
|
</Text>
|
||||||
<Text color="blue.400" fontSize="sm" fontWeight="medium">
|
|
||||||
Switching playlist...
|
|
||||||
</Text>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<Text color="gray.500">
|
|
||||||
{searchQuery ? 'No songs found matching your search' : 'No songs available'}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@ -138,7 +138,7 @@ export const usePaginatedSongs = (options: UsePaginatedSongsOptions = {}) => {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Handle playlist changes - optimized for immediate response
|
// Handle playlist changes - streamlined for immediate response
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (previousPlaylistRef.current !== playlistName) {
|
if (previousPlaylistRef.current !== playlistName) {
|
||||||
// Update refs immediately
|
// Update refs immediately
|
||||||
@ -146,16 +146,14 @@ export const usePaginatedSongs = (options: UsePaginatedSongsOptions = {}) => {
|
|||||||
currentSearchQueryRef.current = searchQuery;
|
currentSearchQueryRef.current = searchQuery;
|
||||||
previousPlaylistRef.current = playlistName;
|
previousPlaylistRef.current = playlistName;
|
||||||
|
|
||||||
// Clear songs IMMEDIATELY for instant visual feedback
|
// Clear all state immediately for instant visual feedback
|
||||||
setSongs([]);
|
setSongs([]);
|
||||||
|
setTotalSongs(0);
|
||||||
// Batch remaining state updates together to reduce re-renders
|
setTotalDuration(undefined);
|
||||||
React.startTransition(() => {
|
setHasMore(true);
|
||||||
setHasMore(true);
|
setCurrentPage(1);
|
||||||
setCurrentPage(1);
|
setSearchQuery(initialSearch);
|
||||||
setSearchQuery(initialSearch);
|
setError(null);
|
||||||
setError(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Load immediately
|
// Load immediately
|
||||||
loadPage(1, initialSearch, playlistName);
|
loadPage(1, initialSearch, playlistName);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user