58 lines
2.1 KiB
TypeScript
58 lines
2.1 KiB
TypeScript
import { useEffect, useState } from 'react';
|
||
import { NavLink } from 'react-router';
|
||
import type { QueueInfo, QueueItem } from '../../shared/api.ts';
|
||
import { api } from '../lib/api.ts';
|
||
|
||
const LINKS = [
|
||
['/', 'Исходники'],
|
||
['/projects', 'Проекты'],
|
||
] as const;
|
||
|
||
export function Nav() {
|
||
return (
|
||
<nav className="nav">
|
||
{LINKS.map(([to, text]) => <NavLink key={to} to={to} end>{text}</NavLink>)}
|
||
<QueueIndicator />
|
||
</nav>
|
||
);
|
||
}
|
||
|
||
function counts(list: QueueItem[]): string {
|
||
const c = new Map<string, number>();
|
||
list.forEach(x => c.set(x.kind, (c.get(x.kind) ?? 0) + 1));
|
||
return [...c].map(([k, n]) => k + (n > 1 ? ' ×' + n : '')).join(', ');
|
||
}
|
||
|
||
/** Состояние очереди ComfyUI: свободен / чем занят и сколько ждёт / недоступен. Обновляется каждые 2 с. */
|
||
function QueueIndicator() {
|
||
const [q, setQ] = useState<QueueInfo | null>(null);
|
||
const [error, setError] = useState('');
|
||
|
||
useEffect(() => {
|
||
let alive = true;
|
||
const update = async () => {
|
||
if (document.hidden) return;
|
||
try {
|
||
const info = await api<QueueInfo>('/api/queue');
|
||
if (alive) { setQ(info); setError(''); }
|
||
} catch (e) {
|
||
if (alive) setError((e as Error).message);
|
||
}
|
||
};
|
||
void update();
|
||
const t = setInterval(update, 2000);
|
||
document.addEventListener('visibilitychange', update);
|
||
return () => { alive = false; clearInterval(t); document.removeEventListener('visibilitychange', update); };
|
||
}, []);
|
||
|
||
if (error) return <span className="queue down" title={error}><span className="dot" />ComfyUI недоступен</span>;
|
||
if (!q) return <span className="queue"><span className="dot" />ComfyUI…</span>;
|
||
if (!q.running.length && !q.pending.length) return <span className="queue idle"><span className="dot" />ComfyUI свободен</span>;
|
||
return (
|
||
<span className="queue busy" title={q.pending.length ? 'Ждут: ' + counts(q.pending) : ''}>
|
||
<span className="dot" />ComfyUI: <b>{counts(q.running) || '—'}</b>
|
||
{q.pending.length > 0 && <> · в очереди <b>{q.pending.length}</b></>}
|
||
</span>
|
||
);
|
||
}
|