import type { MouseEvent } from "react"; import { Link, useNavigate } from "react-router"; import type { Entry } from "../types"; import { avatarUrl, formatTime, linkify } from "../format"; import { Votes } from "./Votes"; import { useBump } from "./Bump"; // Klick auf die Karte öffnet den Beitrag -- außer der Klick galt einem Link // oder Knopf darin. function useOpenOnClick(pid: number) { const navigate = useNavigate(); return (ev: MouseEvent) => { if (!(ev.target as Element).closest("a, button")) navigate(`/e/${pid}`); }; } export function EntryCard({ entry: e }: { entry: Entry }) { const open = useOpenOnClick(e.pid); const when = formatTime(e.created_at); // Soft-gelöschter Beitrag: nur Platzhalter, damit der Thread navigierbar bleibt. if (e.deleted) { return (
[deleted] · {when}
[deleted]
); } return ; } function LiveCard({ entry: e, when, open }: { entry: Entry; when: string; open: (ev: MouseEvent) => void }) { const bump = useBump(e); const profile = `/u/${encodeURIComponent(e.username)}`; return (
{e.username} · {when} {bump.cooldown}
{linkify(e.content)}
{e.filepath && }
Antworten ({e.reply_count}) {bump.button}
); } // Discussion zeigt einen Beitrag mit der Antwort, die seine Diskussion zuletzt // fortgesetzt hat: [Beitrag] ── "k weitere Beiträge" ── [jüngste Antwort]. // Der Strich verbindet die Glieder wie in der Ahnenkette; "k weitere" steht // als Unterbrechung auf dem Strich und führt wie die Antwort selbst zu deren // Seite, wo die ganze Kette darüber steht. export function Discussion({ entry: e }: { entry: Entry }) { if (!e.latest) return ; const { entry: latest, skipped } = e.latest; return (
{skipped > 0 && (
{skipped === 1 ? "1 weiterer Beitrag" : `${skipped} weitere Beiträge`}
)}
); }