36 lines · 1.6 KB
import { useQuery } from "@tanstack/react-query";
import { getLastCommits } from "~/fns/code";
import type { CommitBrief } from "~/lib/code-intel";

const MAX_CONTINUATIONS = 40;
const CONTINUE_DELAY_MS = 250;
/** Resolved per-commit metadata never changes for a given tree sha. */
const COMPLETE_STALE_MS = Number.POSITIVE_INFINITY;

export type LastCommitsState = { commits: Record<string, CommitBrief | null>; complete: boolean } | null;

export const lastCommitsQueryKey = (owner: string, repo: string, sha: string, path: string) =>
  ["last-commits", owner, repo, sha, path] as const;

/**
 * Loads the latest commit per directory entry after the tree renders. The server walks history in
 * bounded chunks, so the query keeps asking until every entry resolves or the cap is hit, then the
 * result is cached for the tree sha so navigating back never shows placeholders again.
 */
export function useLastCommits(owner: string, repo: string, sha: string, path: string): LastCommitsState {
  const query = useQuery({
    queryKey: lastCommitsQueryKey(owner, repo, sha, path),
    queryFn: async () => {
      let page = await getLastCommits({ data: { owner, repo, ref: sha, path } });
      for (let attempt = 0; attempt < MAX_CONTINUATIONS && !page.complete; attempt++) {
        await new Promise((resolve) => setTimeout(resolve, CONTINUE_DELAY_MS));
        page = await getLastCommits({ data: { owner, repo, ref: sha, path } });
      }
      return page;
    },
    staleTime: COMPLETE_STALE_MS,
  });
  if (query.isError) return { commits: {}, complete: true };
  return query.data ?? null;
}