Files
zap.stream/src/element/video-tile.tsx
2023-08-27 16:25:27 +01:00

60 lines
2.1 KiB
TypeScript

import { Link } from "react-router-dom";
import { Profile } from "./profile";
import "./video-tile.css";
import { NostrEvent, encodeTLV, NostrPrefix } from "@snort/system";
import { useInView } from "react-intersection-observer";
import { StatePill } from "./state-pill";
import { StreamState } from "index";
import { findTag, getHost } from "utils";
import { formatSats } from "number";
import ZapStream from "../../public/zap-stream.svg";
import { isContentWarningAccepted } from "./content-warning";
import { Tags } from "element/tags";
import { FormattedMessage } from "react-intl";
export function VideoTile({
ev,
showAuthor = true,
showStatus = true,
}: {
ev: NostrEvent;
showAuthor?: boolean;
showStatus?: boolean;
}) {
const { inView, ref } = useInView({ triggerOnce: true });
const id = findTag(ev, "d") ?? "";
const title = findTag(ev, "title");
const image = findTag(ev, "image");
const status = findTag(ev, "status");
const viewers = findTag(ev, "current_participants");
const contentWarning = findTag(ev, "content-warning") && !isContentWarningAccepted();
const host = getHost(ev);
const link = encodeTLV(NostrPrefix.Address, id, undefined, ev.kind, ev.pubkey);
return (
<div className="video-tile-container">
<Link to={`/${link}`} className={`video-tile${contentWarning ? " nsfw" : ""}`} ref={ref} state={ev}>
<div
style={{
backgroundImage: `url(${inView ? ((image?.length ?? 0) > 0 ? image : ZapStream) : ""})`,
}}></div>
<span className="pill-box">
{showStatus && <StatePill state={status as StreamState} />}
{viewers && (
<span className="pill viewers">
<FormattedMessage defaultMessage="{n} viewers" values={{ n: formatSats(Number(viewers)) }} />
</span>
)}
</span>
<h3>{title}</h3>
</Link>
<div className="video-tile-info">
<div className="video-tags">
<Tags ev={ev} max={3} />
</div>
{showAuthor && <div>{inView && <Profile pubkey={host} />}</div>}
</div>
</div>
);
}