import { useLogin } from "@/hooks/login"; import { useSortedStreams } from "@/hooks/useLiveStreams"; import { getTagValues, getHost, extractStreamInfo } from "@/utils"; import { NostrEvent, NostrLink, TaggedNostrEvent } from "@snort/system"; import { ReactNode, useMemo } from "react"; import { FormattedMessage } from "react-intl"; import VideoGrid from "./video-grid"; import { StreamTile } from "./stream/stream-tile"; import { CategoryTile } from "./category/category-tile"; import { Link } from "react-router-dom"; import Pill from "./pill"; import { CategoryZaps } from "./category/zaps"; import { StreamState, VIDEO_KIND } from "@/const"; import { useRecentClips } from "@/hooks/clips"; import { ClipTile } from "./stream/clip-tile"; interface VideoGridSortedProps { evs: Array; showAll?: boolean; showEnded?: boolean; showPlanned?: boolean; showPopular?: boolean; showRecentClips?: boolean; showVideos?: boolean; } export default function VideoGridSorted({ evs, showAll, showEnded, showPlanned, showPopular, showRecentClips, showVideos, }: VideoGridSortedProps) { const login = useLogin(); const mutedHosts = login?.state?.muted ?? []; const follows = login?.state?.follows ?? []; const followsHost = (ev: NostrEvent) => follows?.includes(getHost(ev)); const filteredStreams = evs.filter(a => !mutedHosts.includes(NostrLink.publicKey(getHost(a)))); const { live, planned, ended } = useSortedStreams(filteredStreams, showAll ? 0 : undefined); const hashtags: Array = []; const following = live.filter(followsHost); const liveNow = live.filter(e => !following.includes(e)); const hasFollowingLive = following.length > 0; const plannedEvents = planned.filter(followsHost); const liveByHashtag = useMemo(() => { return hashtags .map(t => ({ tag: t, live: live.filter(e => { const evTags = getTagValues(e.tags, "t"); return evTags.includes(t); }), })) .filter(t => t.live.length > 0); }, [live, hashtags]); return (
{hasFollowingLive && ( } items={following} /> )} {!hasFollowingLive && ( {live.map(e => ( ))} )} {liveByHashtag.map(t => ( ))} {showVideos && ( } items={evs.filter(a => a.kind === VIDEO_KIND)} /> )} {showRecentClips && } {hasFollowingLive && liveNow.length > 0 && ( } items={liveNow} /> )} {showPopular && } {plannedEvents.length > 0 && (showPlanned ?? true) && ( } items={plannedEvents} /> )} {ended.length > 0 && (showEnded ?? true) && ( } items={ended} /> )}
); } function GridSection({ header, items }: { header: ReactNode; items: Array }) { return ( <>

{header}

{items.map(e => ( ))} ); } function PopularCategories({ items }: { items: Array }) { const categories = useMemo(() => { const grouped = items.reduce( (acc, v) => { const { gameId, participants, status } = extractStreamInfo(v); if (gameId) { acc[gameId] ??= { gameId, viewers: 0, zaps: 0, streams: 0, }; if (participants && status === StreamState.Live) { acc[gameId].viewers += Number(participants); } acc[gameId].streams++; } return acc; }, {} as Record< string, { gameId: string; viewers: number; zaps: number; streams: number; } >, ); return Object.values(grouped) .sort((a, b) => (a.streams > b.streams ? -1 : 1)) .slice(0, 8); }, [items]); return ( <>

{categories.map(a => (
{a.viewers > 0 && ( )}
))}
); } function RecentClips() { const clips = useRecentClips(); return ( <>

{clips.slice(0, 5).map(a => ( ))} ); }