[READ-ONLY] Mirror of https://github.com/SantaClaas/gigit. git client
Something went wrong. Try again.
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101/** * The state behind the history view. * * Owns the stream and the rows it has produced so far, so components can stay * about rendering. */
import { createSignal } from "solid-js";
import { streamGraph, type GraphStream } from "./api";import type { GraphRow, RepositoryId } from "./bindings";import { isGigitError } from "./bindings";
/** * Rows asked for up front. Comfortably more than a screenful, so the first * scroll does not have to wait for a round trip. */const INITIAL_BUDGET = 300;
/** Rows asked for each time the view nears the end of what it has. */const TOP_UP = 400;
export type GraphStatus = "idle" | "loading" | "streaming" | "complete" | "failed";
export function createGraphView() { const [rows, setRows] = createSignal<GraphRow[]>([]); const [status, setStatus] = createSignal<GraphStatus>("idle"); const [message, setMessage] = createSignal<string | undefined>();
let stream: GraphStream | undefined; /** Guards against asking for more while a top-up is already in flight. */ let waiting = false;
function receive(event: Parameters<Parameters<typeof streamGraph>[2]>[0]) { switch (event.event) { case "rows": { waiting = false; // `start` is the row index of the batch, so a batch that somehow // arrives out of order still lands in the right place. setRows((current) => { const next = current.slice(0, event.data.start); next.push(...event.data.rows); return next; }); break; } case "exhausted": { waiting = false; setStatus("complete"); if (event.data.degraded) { setMessage( "This history's dates are skewed enough that some commits may be a row or two out of place.", ); } break; } case "failed": { waiting = false; setStatus("failed"); setMessage(event.data.message); break; } } }
/** Start drawing a repository's history from the newest commit. */ async function show(id: RepositoryId) { setRows([]); setMessage(undefined); setStatus("loading"); waiting = false;
try { stream = await streamGraph(id, INITIAL_BUDGET, receive); setStatus((current) => (current === "loading" ? "streaming" : current)); } catch (error) { setStatus("failed"); setMessage(isGigitError(error) ? error.message : String(error)); } }
/** * Ask for more rows. Safe to call on every scroll — it does nothing while a * top-up is already on its way, or once the history is fully drawn. */ function loadMore() { if (waiting || !stream || status() !== "streaming") return;
waiting = true; stream.requestMore(TOP_UP).catch((error: unknown) => { waiting = false; setStatus("failed"); setMessage(isGigitError(error) ? error.message : String(error)); }); }
return { rows, status, message, show, loadMore };}
export type GraphView = ReturnType<typeof createGraphView>;