import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { Pencil, Trash2 } from 'lucide-react'; import { useState } from 'react'; import { Button } from '#/components/atoms/button.jsx'; import { Card } from '#/components/atoms/card.jsx'; import { Link } from '#/components/atoms/link.jsx'; import { Notice } from '#/components/atoms/notice.jsx'; import { Skeleton } from '#/components/atoms/skeleton.jsx'; import { AtUri } from '#/components/molecules/at-uri.jsx'; import { Copyable } from '#/components/molecules/copyable.jsx'; import { JsonView } from '#/components/molecules/json-view.jsx'; import { RepoScope } from '#/components/molecules/repo-scope.jsx'; import { ago, fileSize, rkeyTime } from '#/lib/format.js'; import { href } from '#/lib/navigation.jsx'; import { useSession } from '#/lib/session.jsx'; import { deleteRecord, getBlob, getRecord, putRecord } from '#/lib/spaces.js'; /** * One blob a record references. The PDS serves it with a disposition that stops * it from being displayed in the PDS's own origin, so the bytes are read here * and shown from an object URL belonging to this page. */ function BlobPreview({ space, repo, cid, onClose }) { const { session } = useSession(); const { data, error, isPending } = useQuery({ queryKey: ['blob', space, repo, cid], queryFn: () => getBlob(session, { space, repo }, cid), retry: false, }); return (
{cid.slice(0, 20)}…
{isPending && } {error && {error.message}} {data && ( <> {data.type.startsWith('image/') ? ( {cid} ) : (
{data.type || 'unknown type'}
)} Download {fileSize(data.size)} )}
); } export function RecordPage({ space, collection, rkey, repo }) { const { session, writable } = useSession(); const client = useQueryClient(); const own = !repo || repo === session.did; const [blobCid, setBlobCid] = useState(null); const [draft, setDraft] = useState(null); const { data, error, isPending } = useQuery({ queryKey: ['record', space, repo, collection, rkey], queryFn: () => getRecord(session, { space, repo }, collection, rkey), retry: false, }); const save = useMutation({ mutationFn: () => putRecord(session, { space, collection, rkey, record: JSON.parse(draft), }), onSuccess: () => { setDraft(null); client.invalidateQueries({ queryKey: ['record', space] }); }, }); const remove = useMutation({ mutationFn: () => deleteRecord(session, { space, collection, rkey }), onSuccess: () => { client.invalidateQueries({ queryKey: ['records', space] }); window.history.back(); }, }); const written = rkeyTime(rkey); return (
← {collection}

{rkey}

{written && (
written {ago(written)}
)}
{isPending && } {error && {error.message}} {data && ( <> {blobCid && ( setBlobCid(null)} /> )} {draft === null ? ( ) : (