fix: Make playlist folders start collapsed by default - Change default state from expanded to collapsed for better UX

This commit is contained in:
Geert Rademakes 2025-08-06 10:05:32 +02:00
parent 7fb8614130
commit 2e32a3c3b6
3 changed files with 19 additions and 9 deletions

View File

@ -120,6 +120,7 @@ export const PaginatedSongList: React.FC<PaginatedSongListProps> = memo(({
const [localSearchQuery, setLocalSearchQuery] = useState(searchQuery);
const observerRef = useRef<IntersectionObserver | null>(null);
const loadingRef = useRef<HTMLDivElement>(null);
const scrollContainerRef = useRef<HTMLDivElement>(null);
// Debounce search to prevent excessive API calls
const debouncedSearchQuery = useDebounce(localSearchQuery, 300);
@ -233,7 +234,10 @@ export const PaginatedSongList: React.FC<PaginatedSongListProps> = memo(({
onLoadMore();
}
},
{ threshold: 0.1 }
{
threshold: 0.1,
rootMargin: '100px' // Start loading when 100px away from the bottom
}
);
observerRef.current.observe(loadingRef.current);
@ -338,23 +342,29 @@ export const PaginatedSongList: React.FC<PaginatedSongListProps> = memo(({
</Box>
{/* Scrollable Song List */}
<Box flex={1} overflowY="auto" mt={2}>
<Box
ref={scrollContainerRef}
flex={1}
overflowY="auto"
mt={2}
id="song-list-container"
>
<Flex direction="column" gap={2}>
{songItems}
{/* Loading indicator for infinite scroll */}
{loading && (
<Flex justify="center" p={4}>
<Flex justify="center" p={4} key="loading-spinner">
<Spinner size="md" color="blue.400" />
</Flex>
)}
{/* Intersection observer target */}
<div ref={loadingRef} style={{ height: '20px' }} />
<div ref={loadingRef} style={{ height: '20px' }} key="intersection-target" />
{/* End of results message */}
{!hasMore && songs.length > 0 && (
<Flex justify="center" p={4}>
<Flex justify="center" p={4} key="end-message">
<Text color="gray.500" fontSize="sm">
No more songs to load
</Text>
@ -363,7 +373,7 @@ export const PaginatedSongList: React.FC<PaginatedSongListProps> = memo(({
{/* No results message */}
{!loading && songs.length === 0 && (
<Flex justify="center" p={8}>
<Flex justify="center" p={8} key="no-results">
<Text color="gray.500">
{searchQuery ? 'No songs found matching your search' : 'No songs available'}
</Text>

View File

@ -77,7 +77,7 @@ const PlaylistItem: React.FC<PlaylistItemProps> = ({
onPlaylistMove,
allFolders,
}) => {
const [isOpen, setIsOpen] = useState(true);
const [isOpen, setIsOpen] = useState(false);
const indent = level * 10;
if (node.type === 'folder') {

View File

@ -100,7 +100,7 @@ export const usePaginatedSongs = (options: UsePaginatedSongsOptions = {}) => {
// Search songs with debouncing
const searchSongs = useCallback((query: string) => {
setSearchQuery(query);
setSongs([]);
// Don't clear songs immediately - let the new search results replace them
setHasMore(true);
setCurrentPage(1);
setError(null);
@ -134,7 +134,7 @@ export const usePaginatedSongs = (options: UsePaginatedSongsOptions = {}) => {
if (currentPlaylistRef.current !== playlistName) {
currentPlaylistRef.current = playlistName;
if (!isInitialLoad) {
setSongs([]);
// Don't clear songs immediately - let the new playlist results replace them
setHasMore(true);
setCurrentPage(1);
setSearchQuery(initialSearch);