MoreChanges
uses IntersectionObserver
A history entry's changes from from on, loaded as they're scrolled to: ten at a time, each ten asked for when the
page comes within a screen of them, and the next ten's turn only once those are in. A merge of hundreds sends what's
read.
import { EntryChangeGroup } from "#codebase/tcmts/share"; import { Suspense, useEffect, useRef, useState } from "react"; export function MoreChanges({ hash, from, total }: { hash: string; from: number; total: number }) { const [near, setNear] = useState(false); const mark = useRef<HTMLDivElement>(null); useEffect(() => { const el = mark.current; if (!el || near) return; const seen = new IntersectionObserver( (es) => es.some((e) => e.isIntersecting) && setNear(true), { rootMargin: "800px 0px", }, ); seen.observe(el); return () => seen.disconnect(); }, [near]); const to = Math.min(from + 10, total); const left = `${total - from} more change${total - from === 1 ? "" : "s"}`; if (!near) return ( <div ref={mark} className="box loading"> {left} </div> ); return ( <Suspense fallback={<div className="box loading">Loading {left}…</div>}> <EntryChangeGroup hash={hash} from={from} to={to} /> {to < total && <MoreChanges hash={hash} from={to} total={total} />} </Suspense> ); }