"use client" import { useEffect, useRef, useState } from "react" import Link from "next/link" import { RiCheckboxCircleFill } from "react-icons/ri" import { cn } from "@/lib/utils/cn" import { MediaDisplayLayout, MediaInfo } from "@/types/general" import { formatDuration } from "@/lib/formatters/formatDuration" import { formatTimeAgo } from "@/lib/formatters/formatTimeAgo" import { isCertifiedUser } from "@/app/certification" import { transparentImage } from "@/lib/utils/transparentImage" import { DefaultAvatar } from "../default-avatar" import { formatLargeNumber } from "@/lib/formatters/formatLargeNumber" export function VideoCard({ media, className = "", layout = "grid", onSelect, selected, index }: { media: MediaInfo className?: string layout?: MediaDisplayLayout onSelect?: (media: MediaInfo) => void selected?: boolean index: number }) { const ref = useRef(null) const [duration, setDuration] = useState(0) const [channelThumbnail, setChannelThumbnail] = useState(media.channel.thumbnail) const [mediaThumbnail, setMediaThumbnail] = useState( `https://huggingface.co/datasets/jbilcke-hf/ai-tube-index/resolve/main/videos/${media.id}.webp` ) const [mediaThumbnailReady, setMediaThumbnailReady] = useState(false) const [shouldLoadMedia, setShouldLoadMedia] = useState(false) const isCompact = layout === "vertical" const handlePointerEnter = () => { // ref.current?.load() ref.current?.play() } const handlePointerLeave = () => { ref.current?.pause() // ref.current?.load() } const handleLoad = () => { if (ref.current?.readyState) { setDuration(ref.current.duration) } } const handleClick = () => { onSelect?.(media) } const handleBadChannelThumbnail = () => { try { if (channelThumbnail) { setChannelThumbnail("") } } catch (err) { } } useEffect(() => { setTimeout(() => { setShouldLoadMedia(true) }, index * 1500) }, [index]) // uncomment this as a temporary hack when developping, to avoid making too many fetches and downloads return null; return (
{/* VIDEO BLOCK */}
{mediaThumbnailReady && shouldLoadMedia ?
0 ? 'opacity-100' : 'opacity-0' )} >{formatDuration(duration)}
{/* TEXT BLOCK */}
{ isCompact ? null : channelThumbnail ?
: }

{media.label}

{media.channel.label}
{isCertifiedUser(media.channel.datasetUser) ?
: null}
{formatLargeNumber(media.numberOfViews)} views
ยท
{formatTimeAgo(media.updatedAt)}
) }