"use client";
import { useEffect, useRef } from "react";
import type { GitStatus } from "~/utils/git";
import { parsePatchFiles } from "@pierre/diffs";
import type { FileDiff as FileDiffRenderer } from "@pierre/diffs";
import { cn } from "~/utils/cn";
type FileChange = { status: string; path: string };
export type StatusViewProps = {
status: GitStatus;
workingDiff: string;
stagedDiff: string;
};
export function StatusView({ status, workingDiff, stagedDiff }: StatusViewProps) {
const hasChanges = status.staged.length > 0 || status.unstaged.length > 0 || status.untracked.length > 0;
if (!hasChanges) {
return
Working tree clean
;
}
return (
{status.untracked.length > 0 && (
Untracked ({status.untracked.length})
{status.untracked.map((p) => (
-
?
{p}
))}
)}
);
}
function DiffSection({
title,
items,
color,
diff,
}: {
title: string;
items: FileChange[];
color: string;
diff: string;
}) {
if (items.length === 0) return null;
return (
{title} ({items.length})
{diff && }
);
}
function FileList({ items, color }: { items: FileChange[]; color: string }) {
return (
{items.map((item) => (
-
{item.status}
{item.path}
))}
);
}
function PatchRenderer({ patch }: { patch: string }) {
const containerRef = useRef(null);
const instancesRef = useRef([]);
useEffect(() => {
let mounted = true;
async function render() {
const { FileDiff } = await import("@pierre/diffs");
if (!mounted || !containerRef.current) return;
for (const inst of instancesRef.current) {
inst.cleanUp();
}
instancesRef.current = [];
containerRef.current.innerHTML = "";
try {
const parsed = parsePatchFiles(patch);
const files = parsed.flatMap((p) => p.files);
for (const fileDiff of files) {
const wrapper = document.createElement("div");
wrapper.className = "mb-3 overflow-hidden rounded-lg border border-gray-800";
containerRef.current.appendChild(wrapper);
const instance = new FileDiff({
theme: "pierre-dark",
diffStyle: "unified",
diffIndicators: "bars",
overflow: "scroll",
});
instance.render({
fileDiff,
containerWrapper: wrapper,
});
instancesRef.current.push(instance);
}
} catch {
if (containerRef.current) {
containerRef.current.innerHTML = 'Could not parse diff
';
}
}
}
render();
return () => {
mounted = false;
for (const inst of instancesRef.current) {
inst.cleanUp();
}
instancesRef.current = [];
};
}, [patch]);
return ;
}