// A pull's files, listed without their rows but for the first few, and // the rows of the rest fetched as a reader comes to them: // dev.knotless.getThread with `filesOnly` and `firstRows`, then // dev.knotless.getPullDiff a few files at a time. A commit's the same way, // by dev.knotless.getCommit's `firstRows` and then its `paths` // (later.svelte.ts). import type { FileDiffView, RepoViewBasic } from '#lib/lexicons/dev/knotless/defs.ts'; import type { AtUriString } from '@atproto/lex'; import { repoHref, urlPath } from '#lib/format.ts'; /** The most lines a file changes before its rows wait to be asked for. */ export const HELD = 400; /** How many files one getPullDiff asks for. */ export const BATCH = 10; /** The cookie that keeps whether the viewer last showed a pull's file tree. */ export const TREE = 'tree'; /** * Where a diff's files are after the change: in the repository `repo` at * the commit `rev`, which the lines a diff leaves out are read from, and * on the page `view` gives for a file's path. */ export type Source = { repo: AtUriString; rev: string; view: (path: string) => string }; /** The files of `on` at the commit `rev`, each shown on its page at `ref`: a branch, or the commit itself. */ export const sourceAt = (on: RepoViewBasic, rev: string, ref = rev): Source => ({ repo: `at://${on.did}/dev.knotless.repo/${on.name}`, rev, view: (path) => repoHref(on.handle, on.name, `/blob/${urlPath(ref)}/${urlPath(path)}`) }); /** Whether the cookie `TREE` says to show the tree, or null where it says nothing and the screen's width decides. */ export const treeShown = (said: string | undefined): boolean | null => said === 'shown' ? true : said === 'hidden' ? false : null; /** The path a file goes by: where it is after the change, or was, if deleted. */ export const pathOf = (f: FileDiffView) => (f.status === 'deleted' ? f.old : f.new); /** The paths getPullDiff finds `f` by: both of a renamed file's. */ export const pathsOf = (f: FileDiffView) => (f.status === 'renamed' ? [f.old, f.new] : [pathOf(f)]); /** Whether `f`'s rows are still to fetch: listed without them, and with no note saying why none show. */ export const unfetched = (f: FileDiffView) => f.note === undefined && f.rows.length === 0; /** Whether `f` changes so much that its rows wait to be asked for. */ export const held = (f: FileDiffView) => f.added + f.removed > HELD; /** Which of `asked`, by index into `files`, each of `got` is. */ export function matched( files: FileDiffView[], asked: number[], got: FileDiffView[] ): Map { const out = new Map(); for (const g of got) { const i = asked.find((i) => files[i].old === g.old && files[i].new === g.new); if (i !== undefined) out.set(i, g); } return out; }