/** * Calling the Rust side. * * Thin wrappers around `invoke`, so components never touch command names or * argument shapes directly. */ import { Channel, invoke } from "@tauri-apps/api/core"; import type { GraphEvent, OpenedRepository, RecentRepository, RefEntry, RepositoryId, RepositorySummary, } from "./bindings"; export function openRepository(path: string): Promise { return invoke("open_repository", { path }); } export function closeRepository(id: RepositoryId): Promise { return invoke("close_repository", { id }); } export function repositorySummary(id: RepositoryId): Promise { return invoke("repository_summary", { id }); } export function listReferences(id: RepositoryId): Promise { return invoke("list_references", { id }); } /** Repositories opened before, most recent first. */ export function listRecentRepositories(): Promise { return invoke("list_recent_repositories"); } /** Drop a repository from the recents list. Resolves to whether it was there. */ export function forgetRecentRepository(id: RepositoryId): Promise { return invoke("forget_recent_repository", { id }); } /** A running graph stream. */ export type GraphStream = { /** * Allow the backend to send `rows` more rows. Call this as the view * approaches the end of what it has. */ requestMore(rows: number): Promise; }; /** * Start streaming the commit graph. * * Rows are pushed rather than requested one page at a time: `budget` rows are * on their way as soon as they exist, without a round trip, and nothing beyond * the budget is sent until {@link GraphStream.requestMore} raises it. That is * what keeps a million-commit repository from flooding the boundary while * still putting the first screen up immediately. * * Only one stream runs per repository — starting another replaces it and * restarts the walk from the newest commit. */ export async function streamGraph( id: RepositoryId, budget: number, onEvent: (event: GraphEvent) => void, ): Promise { const channel = new Channel(); // Tauri's Channel is not an EventTarget — `onmessage` is the only way to // receive from it, so the usual advice to prefer addEventListener does not // apply here. // oxlint-disable-next-line unicorn/prefer-add-event-listener channel.onmessage = onEvent; await invoke("stream_graph", { id, channel, budget }); return { requestMore: (rows: number) => invoke("request_more_rows", { id, rows }), }; }