Files
YTChatHub/client/components/OnAir.tsx
T
yusufipek 6bcbd5400b Rewrite dashboard and overlay, single /events stream, static client served by the backend
Backend: one SSE stream for messages, selection, poll and connection status; reconnect with backoff; no on-disk Innertube session cache; mock only with MOCK_CHAT=1; binds to 127.0.0.1; serves client/out so production runs on one port. Full URLs for links YouTube truncates in chat.

Client: components split out, Lucide icons, stream title and status, on-air strip, search, pause, keyboard shortcuts, overlay settings dialog. Overlay themes, position, size, animation and auto-hide via URL, sized for 1080p and scaled with the source. New blueprint theme for the brand background.

Removed Tailwind, better-sqlite3, zod, the timezone helpers, Cline memory bank and AGENTS.md. Added ESLint, node:test tests and CI.
2026-09-02 22:05:58 +03:00

37 lines
1.4 KiB
TypeScript

'use client';
import { X } from 'lucide-react';
import type { ChatMessage } from '@shared/chat';
import { proxyImageUrl } from '../lib/imageProxy';
import { formatAmount } from '../lib/format';
import { MessageBody } from './MessageBody';
type Props = { selection: ChatMessage | null; onClear: () => void };
/** Mirrors what the OBS overlay is showing right now, so the operator never has to guess. */
export function OnAir({ selection, onClear }: Props) {
return (
<section className={`onair ${selection ? 'onair--live' : ''}`}>
<span className="onair__label">On air</span>
{selection ? (
<>
{selection.authorPhoto && <img src={proxyImageUrl(selection.authorPhoto)} alt="" className="avatar avatar--sm" />}
<span className="onair__author">{selection.author}</span>
{selection.superChat && (
<span className="card__amount" style={{ background: selection.superChat.color }}>
{formatAmount(selection.superChat.amount, selection.superChat.currency)}
</span>
)}
<MessageBody message={selection} className="onair__text" />
<button type="button" className="btn btn--sm" onClick={onClear} title="Clear the overlay (Esc)">
<X size={13} />
Clear
</button>
</>
) : (
<span className="onair__hint">Nothing on the overlay. Click a message to show it, click again to hide it.</span>
)}
</section>
);
}