import { useEffect, useState, useSyncExternalStore } from 'react'; import { bytes } from '#/lib/format.js'; import { onRepoProgress, readSource, repoProgress } from '#/lib/git.js'; /** * How long a read has to run before it is worth telling anyone about. A * repository already open answers in a few milliseconds, and a bar that * appears and leaves inside one frame reads as a flicker rather than as * progress. */ const QUIET_MS = 400; /** * What a repository being opened looks like while it opens. * * Read in this page, an indexed repository opens off its small index blobs * and one without indexes downloads its whole bundle chain. Either way the * record says how large the download is before the first byte arrives, so * the wait can be an honest measure rather than a spinner. Read on the * server, nothing is downloaded here, so the wait has no measure and says * only that the server is at work. * * Nothing renders until the read has run past QUIET_MS, so the common case, * an indexed repository or one already in memory, shows no wait at all. * Whatever appears after that fades in, so a read that finishes just over * the line does not snap on and straight off again. */ export function ReadingRepo({ size }) { // The third argument is the snapshot for a render with no client behind // it. The store is a plain module value, so it reads the same either way. const progress = useSyncExternalStore( onRepoProgress, repoProgress, repoProgress, ); const source = useSyncExternalStore(onRepoProgress, readSource, readSource); const [slow, setSlow] = useState(false); useEffect(() => { const timer = setTimeout(() => setSlow(true), QUIET_MS); return () => clearTimeout(timer); }, []); if (!slow) return null; if (source === 'server' && progress.total === 0) { return (
Reading the repository

The server reads it from its own storage. The answer is cached from here on.

); } const total = progress.total || size || 0; const done = total > 0 ? Math.min(1, progress.loaded / total) : 0; return (
Reading the repository {total > 0 ? `${bytes(progress.loaded)} of ${bytes(total)}` : ''}

The repository is read straight from its bundles in blob storage. It is cached from here on.

); }