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 (
The server reads it from its own storage. The answer is cached from here on.
The repository is read straight from its bundles in blob storage. It is cached from here on.