import { useState } from 'react'; import { useNavigate } from 'react-router'; import { useTranslation } from 'react-i18next'; import { Tabs, TabsList, TabsContent, ScrollArea, Card, TextField, } from '@olly/modern-sk'; import { useGetTracksQuery, useGetAlbumsQuery, useGetArtistsQuery, } from '../../api/endpoints/library'; import { TrackRow } from '../../components/track/TrackRow'; import { LoadingSkeleton } from '../../components/common/LoadingSkeleton'; import { EmptyState } from '../../components/common/EmptyState'; import { ErrorState } from '../../components/common/ErrorState'; import { useAppDispatch } from '../../hooks/useAppDispatch'; import { setQueue } from '../../store/slices/queue'; import type { Track, Album, Artist } from '../../api/types'; import { getCoverUrl } from '../../api/endpoints/streaming'; import { formatDuration } from '../../lib/format'; import { useDebounce } from 'use-debounce'; export function LibraryPage() { const { t } = useTranslation(); const navigate = useNavigate(); const dispatch = useAppDispatch(); const [tab, setTab] = useState('tracks'); const [search, setSearch] = useState(''); const [debouncedSearch] = useDebounce(search, 300); const tracksQuery = useGetTracksQuery( debouncedSearch ? { search } : undefined, ); const albumsQuery = useGetAlbumsQuery( debouncedSearch ? { search } : undefined, ); const artistsQuery = useGetArtistsQuery( debouncedSearch ? { search } : undefined, ); const handlePlayAll = (tracks: Track[]) => { dispatch( setQueue({ entries: tracks.map((t) => ({ trackId: t.id, title: t.title, artistName: t.artistName, albumTitle: t.albumTitle, durationMs: t.durationMs, albumArtUrl: t.albumArtUrl, })), source: 'manual', sourceName: t('library.title'), }), ); }; return (

{t('library.title')}

setSearch(e.target.value)} placeholder={t('library.searchPlaceholder')} />
{tracksQuery.isLoading && } {tracksQuery.isError && ( tracksQuery.refetch()} /> )} {tracksQuery.data && tracksQuery.data.items.length === 0 && ( )} {tracksQuery.data && tracksQuery.data.items.length > 0 && (() => { const data = tracksQuery.data!; return (
{data.items.map((track, i) => ( ))}
); })()}
{albumsQuery.isLoading && } {albumsQuery.isError && ( albumsQuery.refetch()} /> )} {albumsQuery.data && albumsQuery.data.items.length === 0 && ( )} {albumsQuery.data && (
{albumsQuery.data.items.map((album) => ( void navigate(`/albums/${album.id}`)} /> ))}
)}
{artistsQuery.isLoading && } {artistsQuery.isError && ( artistsQuery.refetch()} /> )} {artistsQuery.data && artistsQuery.data.items.length === 0 && ( )} {artistsQuery.data && (
{artistsQuery.data.items.map((artist) => ( ))}
)}
); } function AlbumCard({ album, onClick }: { album: Album; onClick: () => void }) { const { t } = useTranslation(); const artUrl = getCoverUrl(album.artUrl); return ( {artUrl ? ( {album.title} ) : (
💿
)}
{album.title}
{album.artistName}
{t('library.albumCard.tracksDuration', { count: album.trackCount, duration: formatDuration(album.totalDurationMs), })}
); } function ArtistRow({ artist }: { artist: Artist }) { const { t } = useTranslation(); return (
🎤
{artist.name}
{t('library.artistRow.meta', { albumCount: artist.albumCount, trackCount: artist.trackCount, })}
); }