mirror of
https://github.com/yusufipk/YTChatHub.git
synced 2026-09-11 10:56:17 +00:00
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.
37 lines
1.1 KiB
TypeScript
37 lines
1.1 KiB
TypeScript
import { BadgeCheck, Crown, Shield, Star, Tv } from 'lucide-react';
|
|
import type { ChatMessage } from '@shared/chat';
|
|
import { proxyImageUrl } from '../lib/imageProxy';
|
|
|
|
const ICONS = {
|
|
moderator: Shield,
|
|
member: Star,
|
|
verified: BadgeCheck,
|
|
owner: Tv,
|
|
custom: null
|
|
} as const;
|
|
|
|
export function Badges({ message }: { message: ChatMessage }) {
|
|
return (
|
|
<>
|
|
{message.leaderboardRank && (
|
|
<span className="badge badge--rank" title={`#${message.leaderboardRank} on the chat leaderboard`}>
|
|
<Crown size={11} strokeWidth={2.5} />
|
|
{message.leaderboardRank}
|
|
</span>
|
|
)}
|
|
{message.badges?.map((badge, i) => {
|
|
if (badge.imageUrl) {
|
|
return <img key={i} src={proxyImageUrl(badge.imageUrl)} alt={badge.label ?? badge.type} title={badge.label} className="badge badge--image" />;
|
|
}
|
|
const Icon = ICONS[badge.type];
|
|
if (!Icon) return null;
|
|
return (
|
|
<span key={i} className={`badge badge--${badge.type}`} title={badge.label}>
|
|
<Icon size={12} strokeWidth={2.5} />
|
|
</span>
|
|
);
|
|
})}
|
|
</>
|
|
);
|
|
}
|