import { Head, Link, router, useForm } from '@inertiajs/react'; import { Check, Copy, Eye, ImagePlus, Radio, RotateCw, Save, ShieldAlert, StopCircle, Video, } from 'lucide-react'; import type { FormEvent, ReactNode } from 'react'; import { useEffect, useRef, useState } from 'react'; import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { useClipboard } from '@/hooks/use-clipboard'; import { useTranslation } from '@/lib/translations'; import { cn } from '@/lib/utils'; import { dashboard as dashboardRoute } from '@/routes'; import { show as showChannel } from '@/routes/channels'; import { stop as stopBroadcastRoute, store as storeBroadcastRoute, } from '@/routes/creator/broadcasts'; import { store as storeChannelRoute, update as updateChannelRoute, } from '@/routes/creator/channel'; import { rotate as rotateStreamKeyRoute } from '@/routes/creator/stream-key'; import type { BroadcastSummary, Category } from '@/types'; type CreatorChannel = { id: number; slug: string; display_name: string; description: string | null; avatar_url: string | null; banner_url: string | null; thumbnail_url: string | null; is_live: boolean; viewer_count: number; stream_key_last_used_at: string | null; category_id: number | null; live_broadcast: BroadcastSummary | null; }; type Props = { channel: CreatorChannel | null; canCreateChannel: boolean; plainStreamKey: string | null; streaming: { ingestServer: string; tokenizedPath: string | null; }; categories: Category[]; recentBroadcasts: BroadcastSummary[]; }; export default function Dashboard({ channel, canCreateChannel, plainStreamKey, streaming, categories, recentBroadcasts, }: Props) { const [copiedText, copy] = useClipboard(); const { t } = useTranslation(); const [stopTarget, setStopTarget] = useState(null); const [thumbnailPreviewUrl, setThumbnailPreviewUrl] = useState< string | null >(null); const thumbnailInputRef = useRef(null); const liveBroadcast = channel?.live_broadcast ?? null; const pendingBroadcast = recentBroadcasts.find((broadcast) => broadcast.status === 'pending') ?? null; const createForm = useForm({ display_name: '', slug: '', description: '', category_id: '', }); const channelForm = useForm({ _method: 'PATCH', display_name: channel?.display_name ?? '', slug: channel?.slug ?? '', description: channel?.description ?? '', category_id: channel?.category_id ? String(channel.category_id) : '', thumbnail: null as File | null, }); const broadcastForm = useForm({ title: '', recording_enabled: false, }); useEffect(() => { return () => { if (thumbnailPreviewUrl) { URL.revokeObjectURL(thumbnailPreviewUrl); } }; }, [thumbnailPreviewUrl]); function createChannel(event: FormEvent) { event.preventDefault(); createForm.submit(storeChannelRoute()); } function updateChannel(event: FormEvent) { event.preventDefault(); channelForm.post(updateChannelRoute.url(), { forceFormData: true, onSuccess: () => { channelForm.reset('thumbnail'); setThumbnailPreviewUrl(null); if (thumbnailInputRef.current) { thumbnailInputRef.current.value = ''; } }, }); } function updateThumbnail(file: File | null) { channelForm.setData('thumbnail', file); setThumbnailPreviewUrl(file ? URL.createObjectURL(file) : null); } function createBroadcast(event: FormEvent) { event.preventDefault(); broadcastForm.submit(storeBroadcastRoute(), { onSuccess: () => broadcastForm.reset('title', 'recording_enabled'), }); } function stopBroadcast() { if (!stopTarget) { return; } router.post(stopBroadcastRoute(stopTarget.id), undefined, { onFinish: () => setStopTarget(null), }); } return ( <>
{pendingBroadcast && !liveBroadcast && ( {t('READY')} )}

{channel?.display_name ?? t('Creator Studio')}

{t( 'Prepare broadcasts, secure your stream key, and monitor the current session.', )}

{channel && ( )}
{!channel ? ( canCreateChannel ? (
createForm.setData( 'display_name', event.target.value, ) } placeholder={t('Nyone Live')} /> createForm.setData( 'slug', event.target.value.toLowerCase(), ) } placeholder={t('nyone-live')} /> createForm.setData( 'category_id', value, ) } />