'use client'; import { useCallback, useEffect, useState } from 'react'; import { ChevronDown, ChevronRight } from 'lucide-react'; import { backlinksFromPage, flattenSources, getBacklinks, getBacklinkSources, type BacklinkRecord, type BacklinkSource, } from '@/utils/atproto/constellation'; import { shortDid } from '@/utils/atproto/urls'; import AtUriLink from '../AtUriLink'; /** * Inbound-link panel. Used both as a repo-overview tab (target = DID) and * inside the record view (target = at:// URI). * * undefined → still loading * null → constellation unavailable / failed * [] → no inbound links found */ export default function BacklinksTab({ target }: { target: string }) { const [sources, setSources] = useState(undefined); const [open, setOpen] = useState(null); useEffect(() => { let cancelled = false; setSources(undefined); setOpen(null); getBacklinkSources(target).then((raw) => { if (cancelled) return; if (raw === null) { setSources(null); return; } setSources(flattenSources(raw) || []); }); return () => { cancelled = true; }; }, [target]); if (sources === undefined) return

Loading backlinks…

; if (sources === null) { return (

Backlinks unavailable ( constellation ).

); } if (sources.length === 0) { return

No inbound links found.

; } return ( ); } function BacklinkRecords({ target, source }: { target: string; source: string }) { const [records, setRecords] = useState([]); const [cursor, setCursor] = useState(null); const [done, setDone] = useState(false); const [loading, setLoading] = useState(true); const [errored, setErrored] = useState(false); const loadPage = useCallback( async (after: string | null) => { setLoading(true); const res = await getBacklinks(target, source, { limit: 25, cursor: after || undefined, }); if (res === null) { setErrored(true); setLoading(false); setDone(true); return; } const batch = backlinksFromPage(res); setRecords((prev) => (after ? [...prev, ...batch] : batch)); setCursor(res.cursor || null); if (!res.cursor || batch.length === 0) setDone(true); setLoading(false); }, [target, source], ); useEffect(() => { setRecords([]); setCursor(null); setDone(false); setErrored(false); loadPage(null); }, [loadPage]); if (errored) { return (

Couldn’t load linking records.

); } return (
{records.length === 0 && loading && (

Loading…

)} {records.length === 0 && !loading && (

No linking records to show.

)}
    {records.map((r) => { const atUri = `at://${r.did}/${r.collection}/${r.rkey}`; return (
  • {shortDid(r.did)} {r.rkey}
  • ); })}
{!done && records.length > 0 && ( )}
); }