import type { DiffFile } from '../types'; import { ConfirmDialog } from './ConfirmDialog'; import { Icon } from './Icon'; // A diff the server refused to hand over unasked, because rendering it would // wedge the page (see git.Repo.Diff). Two shapes, both built from the file // summary that came back in its place: // // - OversizeWarning — the modal that asks, put up as soon as the diff lands. // - OversizeNotice — what stands in for the diff afterwards, so a dismissed // warning doesn't leave an empty screen with no way back. // // The size is nearly always a base ref whose history has moved on rather than a // genuinely enormous review, so both of them point at the base and at what to // switch to. const n = (x: number) => x.toLocaleString(); // sizeLine describes the change set in one phrase: "412 files, 87,204 changed // lines". Binary files count for no lines, so the file count carries them. function sizeLine(files: DiffFile[]): string { const lines = files.reduce((total, f) => total + f.additions + f.deletions, 0); return `${n(files.length)} file${files.length === 1 ? '' : 's'}, ${n(lines)} changed line${ lines === 1 ? '' : 's' }`; } // commitAdvice points at the other way through a change set too big to render: // the commits are listed in the left rail whether or not the patch loaded, and // one of them at a time costs nothing. function commitAdvice(commits: number): string | null { if (commits === 0) return null; return ( 'The commits it spans are listed in the left rail — reading one at a time ' + 'renders only that commit, however big the whole range is.' ); } // advice suggests the way out, which depends on what the base already is. function advice(base: string, suggested: string): string { if (base === 'HEAD') { return 'That is a lot of uncommitted work for one screen.'; } const alternative = suggested && suggested !== base ? `${suggested}, or HEAD` : 'HEAD'; return ( `A diff this size usually means ${base} has moved on since this work was ` + `cut from it, so the change set is padded with commits nobody is reviewing. ` + `Switching the base to ${alternative} will show only the work itself.` ); } export function OversizeWarning({ files, base, suggested, commits, onLoad, onCancel, }: { files: DiffFile[]; base: string; suggested: string; commits: number; onLoad: () => void; onCancel: () => void; }) { return (

{base} gives {sizeLine(files)}. Rendering that much at once can leave the page unresponsive for a while.

{advice(base, suggested)}

{commitAdvice(commits) &&

{commitAdvice(commits)}

}
); } export function OversizeNotice({ files, base, suggested, commits, onLoad, }: { files: DiffFile[]; base: string; suggested: string; commits: number; onLoad: () => void; }) { return (

Diff not loaded

{base} gives {sizeLine(files)} — enough to make the page unresponsive, so it wasn’t rendered.

{advice(base, suggested)}

{commitAdvice(commits) &&

{commitAdvice(commits)}

}
); }