mirror of
https://github.com/yusufipk/YTChatHub.git
synced 2026-09-11 10:56:17 +00:00
79 lines
2.6 KiB
TypeScript
79 lines
2.6 KiB
TypeScript
'use client';
|
|
|
|
import { useEffect, useState } from 'react';
|
|
import type { ChatMessage } from '@shared/chat';
|
|
|
|
const BACKEND_URL = process.env.NEXT_PUBLIC_BACKEND_URL ?? 'http://localhost:4100';
|
|
|
|
type SelectionPayload = {
|
|
message: ChatMessage | null;
|
|
};
|
|
|
|
export default function OverlayPage() {
|
|
const [message, setMessage] = useState<ChatMessage | null>(null);
|
|
const [connected, setConnected] = useState(false);
|
|
|
|
useEffect(() => {
|
|
const source = new EventSource(`${BACKEND_URL}/overlay/stream`);
|
|
const onSelection = (event: MessageEvent) => {
|
|
try {
|
|
const payload: SelectionPayload = JSON.parse(event.data);
|
|
setMessage(payload.message);
|
|
setConnected(true);
|
|
} catch (error) {
|
|
console.error('overlay: failed to parse payload', error);
|
|
}
|
|
};
|
|
|
|
source.addEventListener('selection', onSelection as EventListener);
|
|
source.addEventListener('heartbeat', () => setConnected(true));
|
|
source.onerror = () => setConnected(false);
|
|
|
|
return () => {
|
|
source.removeEventListener('selection', onSelection as EventListener);
|
|
source.close();
|
|
};
|
|
}, []);
|
|
|
|
return (
|
|
<main className="overlay">
|
|
{message ? (
|
|
<div className="overlay__card">
|
|
<div className="overlay__header">
|
|
{message.authorPhoto && (
|
|
<img src={message.authorPhoto} alt={message.author} className="overlay__avatar" />
|
|
)}
|
|
<div>
|
|
<div className="overlay__authorLine">
|
|
<span className="overlay__author">{message.author}</span>
|
|
{message.badges && message.badges.map((badge, i) => (
|
|
<span key={i} className={`overlay__badge overlay__badge--${badge.type}`} title={badge.label}>
|
|
{badge.type === 'moderator' && '🛡️'}
|
|
{badge.type === 'member' && '⭐'}
|
|
{badge.type === 'verified' && '✓'}
|
|
</span>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{message.superChat && (
|
|
<div className="overlay__superchat" style={{ backgroundColor: message.superChat.color }}>
|
|
💰 {message.superChat.amount}
|
|
</div>
|
|
)}
|
|
{message.membershipGift && (
|
|
<div className="overlay__membership">
|
|
🎁 New Member!
|
|
</div>
|
|
)}
|
|
<p className="overlay__text">{message.text}</p>
|
|
</div>
|
|
) : (
|
|
<div className="overlay__placeholder">
|
|
<span>{connected ? 'Awaiting selection…' : 'Reconnecting…'}</span>
|
|
</div>
|
|
)}
|
|
</main>
|
|
);
|
|
}
|