mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-23 17:52:49 +00:00
* perf(app): reduce avoidable work when opening large diffs Large snapshots were recursively reconstructed for reference stability, while native scroll worklets captured complete file models. Preserve identity at the data producers and prepare text for the visible window without rebuilding unchanged files. * test(app): await commit diff query completion without polling * chore(app): remove profiling artifacts from the source tree
107 lines
3.6 KiB
TypeScript
107 lines
3.6 KiB
TypeScript
import { shareCheckoutDiff } from "./diff-sharing";
|
|
import { useMemo } from "react";
|
|
import { useRetainedPanelActive } from "@/components/retained-panel";
|
|
import { useReplicaQuery } from "@/data/query";
|
|
import { checkoutDiffPushRoute } from "@/data/push-router";
|
|
import { useHostRuntimeIsConnected } from "@/runtime/host-runtime";
|
|
import type { ParsedDiffFile, SubscribeCheckoutDiffResponse } from "@getpaseo/protocol/messages";
|
|
import { checkoutDiffQueryKey } from "@/git/query-keys";
|
|
|
|
interface UseCheckoutDiffQueryOptions {
|
|
serverId: string;
|
|
cwd: string;
|
|
mode: "uncommitted" | "base";
|
|
baseRef?: string;
|
|
ignoreWhitespace?: boolean;
|
|
enabled?: boolean;
|
|
queryScope?: string;
|
|
}
|
|
|
|
type CheckoutDiffQueryPayload = Omit<SubscribeCheckoutDiffResponse["payload"], "subscriptionId">;
|
|
|
|
// Re-export the canonical protocol type so all consumers share one definition.
|
|
export type { ParsedDiffFile };
|
|
export type DiffHunk = ParsedDiffFile["hunks"][number];
|
|
export type DiffLine = DiffHunk["lines"][number];
|
|
export type HighlightToken = NonNullable<DiffLine["tokens"]>[number];
|
|
|
|
function normalizeCheckoutDiffCompare(compare: {
|
|
mode: "uncommitted" | "base";
|
|
baseRef?: string;
|
|
ignoreWhitespace?: boolean;
|
|
}): { mode: "uncommitted" | "base"; baseRef?: string; ignoreWhitespace?: boolean } {
|
|
const ignoreWhitespace = compare.ignoreWhitespace === true;
|
|
if (compare.mode === "uncommitted") {
|
|
return { mode: "uncommitted", ignoreWhitespace };
|
|
}
|
|
const trimmedBaseRef = compare.baseRef?.trim();
|
|
return trimmedBaseRef
|
|
? { mode: "base", baseRef: trimmedBaseRef, ignoreWhitespace }
|
|
: { mode: "base", ignoreWhitespace };
|
|
}
|
|
|
|
export function useCheckoutDiffQuery({
|
|
serverId,
|
|
cwd,
|
|
mode,
|
|
baseRef,
|
|
ignoreWhitespace,
|
|
enabled = true,
|
|
queryScope,
|
|
}: UseCheckoutDiffQueryOptions) {
|
|
const retainedPanelActive = useRetainedPanelActive();
|
|
const queryEnabled = enabled && retainedPanelActive;
|
|
const isConnected = useHostRuntimeIsConnected(serverId);
|
|
const normalizedCompare = useMemo(
|
|
() => normalizeCheckoutDiffCompare({ mode, baseRef, ignoreWhitespace }),
|
|
[mode, baseRef, ignoreWhitespace],
|
|
);
|
|
const compareMode = normalizedCompare.mode;
|
|
const compareBaseRef = normalizedCompare.baseRef;
|
|
const compareIgnoreWhitespace = normalizedCompare.ignoreWhitespace;
|
|
const queryKey = useMemo(() => {
|
|
const comparisonKey = checkoutDiffQueryKey(
|
|
serverId,
|
|
cwd,
|
|
compareMode,
|
|
compareBaseRef,
|
|
compareIgnoreWhitespace,
|
|
);
|
|
const normalizedScope = queryScope?.trim();
|
|
return normalizedScope ? [...comparisonKey, "scope", normalizedScope] : comparisonKey;
|
|
}, [serverId, cwd, compareMode, compareBaseRef, compareIgnoreWhitespace, queryScope]);
|
|
const subscriptionId = useMemo(() => `checkoutDiff:${JSON.stringify(queryKey)}`, [queryKey]);
|
|
const routeEnabled = Boolean(queryEnabled && isConnected && cwd);
|
|
|
|
const query = useReplicaQuery<CheckoutDiffQueryPayload>({
|
|
queryKey,
|
|
structuralSharing: shareCheckoutDiff,
|
|
enabled: routeEnabled,
|
|
pushEvent: "checkout_diff_update",
|
|
meta: checkoutDiffPushRoute({
|
|
enabled: routeEnabled,
|
|
serverId,
|
|
subscriptionId,
|
|
cwd,
|
|
compare: {
|
|
mode: compareMode,
|
|
...(compareBaseRef ? { baseRef: compareBaseRef } : {}),
|
|
ignoreWhitespace: compareIgnoreWhitespace,
|
|
},
|
|
}),
|
|
});
|
|
|
|
const payload = query.data ?? null;
|
|
const payloadError = payload?.error ?? null;
|
|
|
|
return {
|
|
files: payload?.files ?? [],
|
|
payloadError,
|
|
diffTooLarge: payload?.diffTooLarge === true,
|
|
isLoading: payload === null && queryEnabled && isConnected,
|
|
isFetching: false,
|
|
isError: Boolean(payloadError),
|
|
error: null,
|
|
};
|
|
}
|