closes #151
This commit is contained in:
@ -14,6 +14,7 @@ import { RelativeTime } from "../relative-time";
|
|||||||
import { VideoInfo } from "@/service/video/info";
|
import { VideoInfo } from "@/service/video/info";
|
||||||
import { VideoDuration } from "./duration";
|
import { VideoDuration } from "./duration";
|
||||||
import { getName } from "../profile";
|
import { getName } from "../profile";
|
||||||
|
import { useDeadLink } from "@/hooks/dead-link";
|
||||||
|
|
||||||
export function VideoTile({
|
export function VideoTile({
|
||||||
ev,
|
ev,
|
||||||
@ -34,10 +35,13 @@ export function VideoTile({
|
|||||||
const isGrownUp = useContentWarning();
|
const isGrownUp = useContentWarning();
|
||||||
const { proxy } = useImgProxy();
|
const { proxy } = useImgProxy();
|
||||||
|
|
||||||
|
const liveMedia = useDeadLink(ev);
|
||||||
const link = NostrLink.fromEvent(ev);
|
const link = NostrLink.fromEvent(ev);
|
||||||
const poster = video.bestPoster();
|
const poster = video.bestPoster();
|
||||||
const bestVideo = video.bestVideo();
|
const bestVideo = video.bestVideo();
|
||||||
const [hasImg, setHasImage] = useState(true);
|
const [hasImg, setHasImage] = useState(true);
|
||||||
|
if (!liveMedia) return;
|
||||||
|
console.debug(liveMedia)
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classNames("flex gap-2", className, {
|
className={classNames("flex gap-2", className, {
|
||||||
|
73
src/hooks/dead-link.ts
Normal file
73
src/hooks/dead-link.ts
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import { SHORTS_KIND, VIDEO_KIND } from "@/const";
|
||||||
|
import { MediaPayload, VideoInfo } from "@/service/video/info";
|
||||||
|
import { findTag } from "@/utils";
|
||||||
|
import { NostrEvent, TaggedNostrEvent } from "@snort/system";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
const saveDeadLink = (link: string, val: boolean) => localStorage.setItem(`dead-link:${link}`, String(val));
|
||||||
|
const getDeadLink = (link: string) => localStorage.getItem(`dead-link:${link}`);
|
||||||
|
|
||||||
|
export function useDeadLink(ev: TaggedNostrEvent | NostrEvent) {
|
||||||
|
const [alive, setAlive] = useState<MediaPayload>();
|
||||||
|
|
||||||
|
async function testLink(link: string) {
|
||||||
|
const u = new URL(link);
|
||||||
|
link = u.toString(); // normalize link
|
||||||
|
const existing = getDeadLink(link);
|
||||||
|
if (existing === null) {
|
||||||
|
// youtube links cant be played
|
||||||
|
if (u.hostname.endsWith("youtube.com") || u.hostname.endsWith("youtu.be")) {
|
||||||
|
saveDeadLink(link, false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const req = await fetch(link, {
|
||||||
|
method: "HEAD",
|
||||||
|
});
|
||||||
|
saveDeadLink(link, req.ok);
|
||||||
|
return req.ok;
|
||||||
|
} else {
|
||||||
|
return existing === "true";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function testPayload(pl: MediaPayload) {
|
||||||
|
const alive = await testLink(pl.url);
|
||||||
|
if (pl.url && alive) {
|
||||||
|
return pl;
|
||||||
|
}
|
||||||
|
for (const alt of pl.alternatives) {
|
||||||
|
const alive = await testLink(alt);
|
||||||
|
if (alt && alive) {
|
||||||
|
return {
|
||||||
|
...pl,
|
||||||
|
url: alt
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getLiveLink(links: Array<MediaPayload>) {
|
||||||
|
for (const l of links) {
|
||||||
|
const live = await testPayload(l);
|
||||||
|
if (live) {
|
||||||
|
setAlive(live);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const links = ev.kind === VIDEO_KIND || ev.kind === SHORTS_KIND ?
|
||||||
|
VideoInfo.parse(ev)?.sources() :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
url: findTag(ev, "streaming") ?? findTag(ev, "recording"),
|
||||||
|
alternatives: []
|
||||||
|
} as MediaPayload
|
||||||
|
];
|
||||||
|
|
||||||
|
getLiveLink(links).catch(console.error);
|
||||||
|
}, [ev]);
|
||||||
|
|
||||||
|
return alive;
|
||||||
|
}
|
@ -15,7 +15,6 @@ export function VideosPage() {
|
|||||||
|
|
||||||
const videos = useRequestBuilder(rb);
|
const videos = useRequestBuilder(rb);
|
||||||
|
|
||||||
console.debug(login?.state?.muted);
|
|
||||||
const sorted = videos
|
const sorted = videos
|
||||||
.filter(a => {
|
.filter(a => {
|
||||||
const host = getHost(a);
|
const host = getHost(a);
|
||||||
|
Reference in New Issue
Block a user