import { useState, type FormEvent } from "react"; import { api, formatLength } from "../api"; import type { Track } from "../types"; const SOURCE_BADGE: Record = { youtube: "YouTube", soundcloud: "SoundCloud", direct: "Ссылка", local: "Медиатека", }; interface Props { serverId: string; canControl: boolean; localLibrary: boolean; onError(message: string | null): void; } const SOURCE_KEY = "mbot.searchSource"; export function SearchPanel({ serverId, canControl, localLibrary, onError }: Props) { const [query, setQuery] = useState(""); const [source, setSource] = useState(() => localStorage.getItem(SOURCE_KEY) ?? "all"); const [results, setResults] = useState([]); const [busy, setBusy] = useState(false); const [lastAdded, setLastAdded] = useState(null); const [searched, setSearched] = useState(false); async function submit(event: FormEvent) { event.preventDefault(); const value = query.trim(); if (!value) return; setBusy(true); onError(null); try { if (/^https?:\/\//i.test(value)) { await api.play(serverId, { query: value }); setLastAdded(value); setResults([]); setSearched(false); setQuery(""); return; } const { tracks } = await api.search(serverId, value, source); setResults(tracks); setSearched(true); } catch (err) { onError(err instanceof Error ? err.message : "Поиск не удался"); } finally { setBusy(false); } } async function enqueue(track: Track, mode: "append" | "next" | "now") { onError(null); try { await api.play(serverId, { trackIds: [track.id], mode }); setLastAdded(track.title); } catch (err) { onError(err instanceof Error ? err.message : "Не удалось добавить трек"); } } return (

Поиск

setQuery(event.target.value)} placeholder="Название трека или ссылка…" disabled={!canControl} />
{results.length === 0 ? (
{searched ? `По запросу «${query}» ничего не нашлось. YouTube иногда прячет результаты от ботов — попробуйте другие слова или вставьте прямую ссылку на трек.` : lastAdded ? `Добавлено: ${lastAdded}` : "Введите запрос или вставьте ссылку — плейлисты тоже поддерживаются."}
) : (
    {results.map((track, index) => (
  • {index + 1} {track.thumbnail ? :
    }
    {track.title}
    {[track.author, formatLength(track)].filter(Boolean).join(" · ")}
    {SOURCE_BADGE[track.source]}
  • ))}
)}

Префиксы: sc: — искать в SoundCloud, yt: — в YouTube {localLibrary ? ( <> , local: — в локальной медиатеке ) : null} .

); }