import React, { useEffect, useState } from 'react'; import { useSearchParams } from 'react-router-dom'; import { Play, Search } from 'lucide-react'; import { search, SearchResults as ISearchResults, SubsonicSong } from '../api/subsonic'; import { usePlayerStore, songToTrack } from '../store/playerStore'; import AlbumRow from '../components/AlbumRow'; import ArtistRow from '../components/ArtistRow'; import { useTranslation } from 'react-i18next'; import { useDragDrop } from '../contexts/DragDropContext'; import { useAuthStore } from '../store/authStore'; function formatDuration(s: number) { return `${Math.floor(s / 60)}:${(s % 60).toString().padStart(2, '0')}`; } export default function SearchResults() { const { t } = useTranslation(); const [params] = useSearchParams(); const query = params.get('q') ?? ''; const [results, setResults] = useState(null); const [loading, setLoading] = useState(false); const playTrack = usePlayerStore(s => s.playTrack); const currentTrack = usePlayerStore(s => s.currentTrack); const psyDrag = useDragDrop(); const musicLibraryFilterVersion = useAuthStore(s => s.musicLibraryFilterVersion); useEffect(() => { if (!query.trim()) { setResults(null); return; } setLoading(true); search(query, { artistCount: 20, albumCount: 20, songCount: 50 }) .then(r => setResults(r)) .finally(() => setLoading(false)); }, [query, musicLibraryFilterVersion]); const hasResults = results && (results.artists.length || results.albums.length || results.songs.length); const playSong = (song: SubsonicSong, list: SubsonicSong[]) => { playTrack(songToTrack(song), list.map(songToTrack)); }; return (

{query ? t('search.resultsFor', { query }) : t('search.title')}

{loading && (
)} {!loading && query && !hasResults && (
{t('search.noResults', { query })}
)} {!loading && results && ( <> {results.artists.length > 0 && ( )} {results.albums.length > 0 && ( )} {results.songs.length > 0 && (

{t('search.songs')}

{t('albumDetail.trackTitle')}
{t('albumDetail.trackArtist')}
{t('search.album')}
{t('albumDetail.trackFormat')}
{t('albumDetail.trackDuration')}
{results.songs.map(song => (
playSong(song, results.songs)} role="row" onMouseDown={e => { if (e.button !== 0) return; e.preventDefault(); const sx = e.clientX, sy = e.clientY; const track = songToTrack(song); const onMove = (me: MouseEvent) => { if (Math.abs(me.clientX - sx) > 5 || Math.abs(me.clientY - sy) > 5) { document.removeEventListener('mousemove', onMove); document.removeEventListener('mouseup', onUp); psyDrag.startDrag({ data: JSON.stringify({ type: 'song', track }), label: song.title }, me.clientX, me.clientY); } }; const onUp = () => { document.removeEventListener('mousemove', onMove); document.removeEventListener('mouseup', onUp); }; document.addEventListener('mousemove', onMove); document.addEventListener('mouseup', onUp); }} >
{song.title}
{song.artist}
{song.album}
{[song.suffix?.toUpperCase(), song.bitRate ? `${song.bitRate} kbps` : ''].filter(Boolean).join(' ยท ')} {formatDuration(song.duration)}
))}
)} )}
); }