import { useState, useEffect, useCallback } from 'react'; import { useClient } from 'hooks/useClient'; import { toast } from 'sonner'; import { Server, Radio, Plug, PlugZap, RefreshCw, Package, Loader2 } from 'lucide-react'; import type { SlskdApplication, SlskdServerState } from './shared'; // System panel — connection health and controls for the slskd daemon. GET /application carries the // server block (state/address/username) and version info; PUT /server connects to Soulseek, DELETE // /server disconnects. Basic version: a connection card with connect/disconnect, and a version card. const POLL_MS = 3000; export const SoulseekSystem = () => { const client = useClient(); const [app, setApp] = useState(null); const [busy, setBusy] = useState(false); const refresh = useCallback(async () => { try { setApp(await client.get('/soulseek/api/v0/application')); } catch { /* connection card will show the stale/empty state */ } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { refresh(); const timer = setInterval(refresh, POLL_MS); return () => clearInterval(timer); }, [refresh]); const server: SlskdServerState | undefined = app?.server; const connected = server?.isConnected ?? false; const connect = async () => { setBusy(true); try { await client.put('/soulseek/api/v0/server'); toast.success('Connecting to Soulseek…'); await refresh(); } catch (err) { toast.error(`Connect failed: ${err instanceof Error ? err.message : String(err)}`); } finally { setBusy(false); } }; const disconnect = async () => { setBusy(true); try { await client.delete('/soulseek/api/v0/server'); toast.success('Disconnected from Soulseek.'); await refresh(); } catch (err) { toast.error(`Disconnect failed: ${err instanceof Error ? err.message : String(err)}`); } finally { setBusy(false); } }; const version = app?.version; return (
System
{/* Connection */}
{server?.state ?? 'Unknown'}
{server?.address &&
{server.address}
}
{server?.username && {server.username}}
{/* Version */}
Version
{version?.isUpdateAvailable ? ( Update available ) : ( Up to date )}
); }; type FieldProps = { label: string; value: string }; const Field = ({ label, value }: FieldProps) => (
{label} {value}
);