support HLS video events

This commit is contained in:
hzrd149 2025-01-09 10:27:57 -06:00
parent eae4ee3f14
commit 50ed22479a
3 changed files with 22 additions and 13 deletions

View File

@ -1,26 +1,25 @@
import { getTagValue } from "applesauce-core/helpers";
import { NostrEvent } from "../../types/nostr-event";
export const FLARE_VIDEO_KIND = 34235;
export function getVideoTitle(video: NostrEvent) {
const title = video.tags.find((t) => t[0] === "title")?.[1];
if (!title) throw new Error("Missing title");
return title;
return getTagValue(video, "title");
}
export function getVideoUrl(video: NostrEvent) {
const url = video.tags.find((t) => t[0] === "url")?.[1];
const url = getTagValue(video, "url");
if (!url) throw new Error("Missing url");
return url;
}
export function getVideoSummary(video: NostrEvent) {
return video.tags.find((t) => t[0] === "summary")?.[1];
return getTagValue(video, "summary");
}
export function getVideoSize(video: NostrEvent) {
const str = video.tags.find((t) => t[0] === "size")?.[1];
const str = getTagValue(video, "size");
return str ? parseInt(str) || undefined : undefined;
}
export function getVideoDuration(video: NostrEvent) {
const str = video.tags.find((t) => t[0] === "duration")?.[1];
const str = getTagValue(video, "duration");
return str ? parseInt(str) || undefined : undefined;
}
export function getVideoPublishDate(video: NostrEvent) {
@ -28,7 +27,11 @@ export function getVideoPublishDate(video: NostrEvent) {
return str ? parseInt(str) || undefined : undefined;
}
export function getVideoImages(video: NostrEvent) {
const thumb = video.tags.find((t) => t[0] === "thumb")?.[1];
const image = video.tags.find((t) => t[0] === "image")?.[1];
const thumb = getTagValue(video, "thumb");
const image = getTagValue(video, "image");
return { thumb, image };
}
export function isValidVideo(video: NostrEvent) {
return video.tags.some((t) => t[0] === "url" && t[1]);
}

View File

@ -8,7 +8,7 @@ import TimelineActionAndStatus from "../../components/timeline/timeline-action-a
import VerticalPageLayout from "../../components/vertical-page-layout";
import { useTimelineCurserIntersectionCallback } from "../../hooks/use-timeline-cursor-intersection-callback";
import IntersectionObserverProvider from "../../providers/local/intersection-observer";
import { FLARE_VIDEO_KIND } from "../../helpers/nostr/video";
import { FLARE_VIDEO_KIND, isValidVideo } from "../../helpers/nostr/video";
import VideoCard from "./components/video-card";
import { ErrorBoundary } from "../../components/error-boundary";
import { useReadRelays } from "../../hooks/use-client-relays";
@ -32,7 +32,7 @@ function VideosPage() {
<IntersectionObserverProvider callback={callback}>
<SimpleGrid columns={{ base: 1, sm: 2, md: 3, lg: 4, xl: 5 }} spacing="2">
{videos?.map((video) => (
{videos.filter(isValidVideo).map((video) => (
<ErrorBoundary key={getEventUID(video)} event={video}>
<VideoCard video={video} />
</ErrorBoundary>

View File

@ -1,5 +1,5 @@
import { Box, ButtonGroup, Flex, Heading, Spinner, Tag, Text } from "@chakra-ui/react";
import { getEventUID } from "applesauce-core/helpers";
import { getEventUID, isStreamURL } from "applesauce-core/helpers";
import VerticalPageLayout from "../../components/vertical-page-layout";
import {
@ -28,6 +28,7 @@ import { useBreakpointValue } from "../../providers/global/breakpoint-provider";
import SimpleBookmarkButton from "../../components/simple-bookmark-button";
import EventZapButton from "../../components/zap/event-zap-button";
import EventQuoteButton from "../../components/note/event-quote-button";
import LiveVideoPlayer from "../../components/live-video-player";
function VideoRecommendations({ video }: { video: NostrEvent }) {
const readRelays = useReadRelays();
@ -50,7 +51,12 @@ function VideoDetailsPage({ video }: { video: NostrEvent }) {
<VerticalPageLayout>
<Flex gap="4">
<Flex direction="column" gap="2" flexGrow={1}>
<Box as="video" src={url} w="full" maxH="95vh" controls poster={image || thumb} />
{isStreamURL(url) ? (
<LiveVideoPlayer stream={url} poster={image || thumb} />
) : (
<Box as="video" src={url} w="full" maxH="95vh" controls poster={image || thumb} />
)}
<Flex gap="2" overflow="hidden">
<Heading size="md" my="2" isTruncated>
{title}