closes #151
This commit is contained in:
parent
c32c230227
commit
0c07258e58
@ -14,6 +14,7 @@ import { RelativeTime } from "../relative-time";
|
||||
import { VideoInfo } from "@/service/video/info";
|
||||
import { VideoDuration } from "./duration";
|
||||
import { getName } from "../profile";
|
||||
import { useDeadLink } from "@/hooks/dead-link";
|
||||
|
||||
export function VideoTile({
|
||||
ev,
|
||||
@ -34,10 +35,13 @@ export function VideoTile({
|
||||
const isGrownUp = useContentWarning();
|
||||
const { proxy } = useImgProxy();
|
||||
|
||||
const liveMedia = useDeadLink(ev);
|
||||
const link = NostrLink.fromEvent(ev);
|
||||
const poster = video.bestPoster();
|
||||
const bestVideo = video.bestVideo();
|
||||
const [hasImg, setHasImage] = useState(true);
|
||||
if (!liveMedia) return;
|
||||
console.debug(liveMedia)
|
||||
return (
|
||||
<div
|
||||
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);
|
||||
|
||||
console.debug(login?.state?.muted);
|
||||
const sorted = videos
|
||||
.filter(a => {
|
||||
const host = getHost(a);
|
||||
|
Loading…
x
Reference in New Issue
Block a user