import { useMemo } from 'react'; import { Skeleton } from '#/components/atoms/skeleton.jsx'; import { ActivityTicks } from '#/components/molecules/activity-ticks.jsx'; import { LanguageBar } from '#/components/molecules/language-bar.jsx'; import { ACTIVITY_WEEKS } from '#/lib/activity.js'; import { languageShares, percent } from '#/lib/languages.js'; import { useFileList, useHistory } from '#/lib/source.js'; /** * Two readings of the repository as a whole: what it is written in, and how * lately it was worked on. Both stand under the file pane, so they keep the * reader's company whatever file or directory is open. * * Each walk reads objects the page has already downloaded, and both share * their keys with the pages that want the same answers, so a gauge costs no * request of its own. */ export function RepoGauges({ repo, refName, space }) { const { data: files, isPending: languagesPending } = useFileList( repo, refName, space, ); const languages = useMemo( () => (files ? languageShares(files) : undefined), [files], ); const { data: history, isPending: historyPending } = useHistory( repo, refName, space, ); const showLanguages = languagesPending || Boolean(languages?.length); const showActivity = historyPending || Boolean(history?.dates?.length); if (!showLanguages && !showActivity) return null; return (
{/* Each gauge keeps its place from the first frame. Both walks run over the whole repository, so they land well after the file beside them, and a listing that stepped down the page twice on the way would be the reader's problem rather than the walk's. */} {showLanguages && (
{languages?.length ? ( ) : ( )} {/* The placeholder sits inside the line rather than replacing it, so the label keeps the height its text will have. */}
{languages?.length ? ( `${languages[0].name} ${percent(languages[0].share)}` ) : ( )}
)} {showActivity && (
{history?.dates?.length ? ( ) : ( )}
{ACTIVITY_WEEKS} weeks
)}
); }