import VideoPlayer from './VideoPlayer'; import Link from 'next/link'; import WatchActions from './WatchActions'; import SubscribeButton from '../components/SubscribeButton'; import { API_BASE } from '../constants'; interface VideoData { id: string; title: string; uploader: string; channel_id?: string; thumbnail: string; view_count: number; duration: string; } interface VideoInfo { title: string; description: string; uploader: string; channel_id: string; view_count: number; thumbnail?: string; } async function getVideoInfo(id: string): Promise { try { const res = await fetch(`${API_BASE}/api/get_stream_info?v=${id}`, { cache: 'no-store' }); if (!res.ok) return null; const data = await res.json(); return { title: data.title || `Video ${id}`, description: data.description || '', uploader: data.uploader || 'Unknown', channel_id: data.channel_id || '', view_count: data.view_count || 0, thumbnail: data.thumbnail || `https://i.ytimg.com/vi/${id}/hqdefault.jpg`, }; } catch (e) { console.error(e); return null; } } async function getRelatedVideos(videoId: string, title: string, uploader: string) { try { const params = new URLSearchParams({ v: videoId, title: title || '', uploader: uploader || '', limit: '15' }); const res = await fetch(`${API_BASE}/api/related?${params.toString()}`, { cache: 'no-store' }); if (!res.ok) return []; return res.json() as Promise; } catch (e) { console.error(e); return []; } } function formatViews(views: number): string { if (views >= 1000000) return (views / 1000000).toFixed(1) + 'M'; if (views >= 1000) return (views / 1000).toFixed(1) + 'K'; return views.toString(); } function formatNumber(num: number): string { if (num >= 1000000) return (num / 1000000).toFixed(1) + 'M'; if (num >= 1000) return (num / 1000).toFixed(0) + 'K'; return num.toString(); } export default async function WatchPage({ searchParams, }: { searchParams: Promise<{ [key: string]: string | string[] | undefined }> }) { const awaitParams = await searchParams; const v = awaitParams.v as string; if (!v) { return
No video ID provided
; } const info = await getVideoInfo(v); const relatedVideos = await getRelatedVideos(v, info?.title || '', info?.uploader || ''); const nextVideoId = relatedVideos.length > 0 ? relatedVideos[0].id : undefined; return (

{info?.title || `Video ${v}`}

{info && (
{info.uploader}
)} {info && (
{formatNumber(info.view_count)} views
{info.description || 'No description available.'}
)}
{relatedVideos.map((video, i) => { const views = formatViews(video.view_count); const staggerClass = `stagger-${Math.min(i + 1, 6)}`; return (
{video.title} {video.duration && (
{video.duration}
)}
{video.title} {video.uploader} {views} views
); })}
); }