feat(blame): add file blame dialog with git porcelain parsing

This change introduces a new backend command to fetch file blame using
git's line-porcelain output and returns structured per-line metadata.
The UI adds a BlameDialog that groups lines by commit, highlights
uncommitted changes, and styles the dialog to match the updated theme.

- Add get_file_blame command and parsing with uncommitted detection
- Wire BlameDialog into the explorer file node actions
- Add blame UI component and supporting types and styles
This commit is contained in:
Christoph Brandau
2026-07-07 15:09:25 +02:00
parent a67663f3c5
commit d4ac449074
10 changed files with 548 additions and 25 deletions
+20
View File
@@ -18,6 +18,7 @@
Folder,
FolderOpen,
ExternalLink,
History,
Terminal,
} from "@lucide/svelte";
import { languageIconForPath } from "../languageIcons";
@@ -36,6 +37,7 @@
onCollapseAllFolders: () => void;
onSelectNode: (node: ExplorerNode) => void;
onOpenFile: (node: ExplorerNode) => void;
onBlame: (node: ExplorerNode) => void;
}
let {
@@ -50,6 +52,7 @@
onCollapseAllFolders = () => {},
onSelectNode = () => {},
onOpenFile = () => {},
onBlame = () => {},
}: Props = $props();
let contextNode = $state<ExplorerNode | null>(null);
@@ -182,6 +185,13 @@
onOpenFile(node);
}
function openContextBlame() {
const node = contextNode;
if (!node || node.kind !== "file") return;
closeFileContextMenu();
onBlame(node);
}
function handleWindowKeydown(event: KeyboardEvent) {
if (event.key === "Escape") closeFileContextMenu();
}
@@ -335,5 +345,15 @@
<ExternalLink size={14} aria-hidden="true" />
Open in Explorer
</button>
<button
type="button"
role="menuitem"
onclick={openContextBlame}
disabled={!contextNode.tracked || contextNode.status === "deleted"}
title={!contextNode.tracked || contextNode.status === "deleted" ? "Blame is only available for tracked files" : "Show blame for this file"}
>
<History size={14} aria-hidden="true" />
Blame
</button>
</div>
{/if}