import { lfsPointer } from '@pdsjs/git/browser'; import { useQuery } from '@tanstack/react-query'; import { FileCodeIcon } from 'lucide-react'; import { ButtonLink } from '#/components/atoms/button-link.jsx'; import { Skeleton } from '#/components/atoms/skeleton.jsx'; import { FileCommit } from '#/components/molecules/file-commit.jsx'; import { PageNotice } from '#/components/molecules/page-notice.jsx'; import { ReadingRepo } from '#/components/molecules/reading-repo.jsx'; import { RefSelect } from '#/components/molecules/ref-select.jsx'; import { SourceCrumbs } from '#/components/molecules/source-crumbs.jsx'; import { SourceLines } from '#/components/molecules/source-lines.jsx'; import { SourcePanes } from '#/components/molecules/source-panes.jsx'; import { bytes } from '#/lib/format.js'; import { capabilities, rawUrl, repoRecord, repoSize } from '#/lib/git.js'; import { useNavigate } from '#/lib/navigation.jsx'; import { useObjectUrl } from '#/lib/object-url.js'; import { fileKey, parentOf, readSource, useFileCommit } from '#/lib/source.js'; export function FilePage({ repo, refName, path, space }) { const navigate = useNavigate(); const record = repoRecord(repo, space); const { data, error } = useQuery({ queryKey: fileKey(repo, refName, path, space), enabled: Boolean(record), queryFn: () => readSource(repo, refName, path, space), }); // A file tracked by Git LFS is a few lines naming the file it stands for, // so the bytes an image path returns are text rather than pixels. const pointer = data?.image ? lfsPointer(data.image.bytes) : null; const imageUrl = useObjectUrl( pointer ? null : data?.image?.bytes, data?.image?.mediaType ?? '', ); // Who last changed this file. The walk reads trees rather than the file, so // it runs behind the paint and fills its line in when it lands. const { data: fileCommit, isPending: commitPending } = useFileCommit( repo, refName, path, space, ); if (!record) { return No such repository.; } const selectRef = (next) => navigate( `/${encodeURIComponent(repo)}/blob/${encodeURI(next)}/${encodeURI(path)}`, ); const lines = data?.file?.text != null ? data.file.text.split('\n').length : 0; return (
} /> {/* The panel is not clipped, so its header can pin under the crumbs while the lines scroll past; the lines clip themselves to the panel's bottom corners. */}
{lines > 0 && ( {lines} {lines === 1 ? 'line' : 'lines'} )} {lines > 0 && ยท} {bytes(data?.file?.size)} {data?.file?.mode === '120000' && symlink} {capabilities.rawFiles && !space && ( Raw )}
{error && {error.message}} {!data && !error && ( <>
)} {data?.file && (pointer ? (

{`Stored with Git LFS, ${bytes(pointer.size)}. This repository holds the pointer, not the file itself.`}

) : data.image ? (
{imageUrl && ( {path} )}
) : data.file.text !== null ? ( ) : (

{data.file.binary ? `Binary file, ${bytes(data.file.size)}.` : `File is ${bytes(data.file.size)}, too large to show.`}

))}
); }