Первоначальная версия VidConf

This commit is contained in:
2026-07-23 01:04:01 +03:00
commit 896455381a
335 changed files with 61527 additions and 0 deletions

View File

@@ -0,0 +1,62 @@
import { Check, Copy, Users } from 'lucide-react'
import { useParticipants } from '@livekit/components-react'
import { useState } from 'react'
import { pluralizeParticipants } from '@/lib/pluralize'
interface RoomTopbarProps {
roomName: string
/** Slug/номер конференции из адреса — для инвайт-чипа (копирование ссылки). */
slug?: string
number?: string
}
/**
* Верхняя панель комнаты: название, число участников и инвайт-чип
* (номер + копирование ссылки-приглашения `/j/:slug`).
*
* Примечание: в design/mockups/room.html этого чипа нет — он добавлен,
* чтобы ссылка и номер конференции были видны и копировались, в стиле
* тёмных токенов темы `room` (см. `--color-room-tile*`), без новых
* цветов и форм.
*/
export function RoomTopbar({ roomName, slug, number }: RoomTopbarProps) {
const participants = useParticipants()
const [copied, setCopied] = useState(false)
async function handleCopy() {
if (!slug) return
const link = `${window.location.origin}/j/${slug}`
try {
await navigator.clipboard.writeText(link)
setCopied(true)
setTimeout(() => setCopied(false), 2000)
} catch {
// Буфер обмена недоступен (нет разрешения/не https) — молча игнорируем,
// это некритичный вспомогательный элемент интерфейса.
}
}
return (
<header className="room-topbar">
<div className="room-title-block">
<h1>{roomName}</h1>
<p>
<span className="rec-dot" aria-hidden="true" />
Конференция активна · <Users className="lucide" style={{ width: 14, height: 14 }} aria-hidden="true" />{' '}
{participants.length} {pluralizeParticipants(participants.length)}
</p>
</div>
{slug && (
<button type="button" className="room-invite-chip" onClick={handleCopy}>
<span>{number ? `${number}` : slug}</span>
{copied ? (
<Check style={{ width: 14, height: 14 }} aria-hidden="true" />
) : (
<Copy style={{ width: 14, height: 14 }} aria-hidden="true" />
)}
{copied ? 'Скопировано' : 'Пригласить'}
</button>
)}
</header>
)
}