Первоначальная версия VidConf
This commit is contained in:
62
frontend/src/components/room/RoomTopbar.tsx
Normal file
62
frontend/src/components/room/RoomTopbar.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user