refactor(explorer): update context menu for file history

This commit is contained in:
2026-08-04 18:41:19 +02:00
parent 50524c2759
commit 90070697dd
+25 -4
View File
@@ -11,6 +11,7 @@
FileCog, FileCog,
FileImage, FileImage,
FileJson, FileJson,
FileSearch,
FileSpreadsheet, FileSpreadsheet,
FileText, FileText,
FileType, FileType,
@@ -37,6 +38,7 @@
onCollapseAllFolders: () => void; onCollapseAllFolders: () => void;
onSelectNode: (node: ExplorerNode) => void; onSelectNode: (node: ExplorerNode) => void;
onOpenFile: (node: ExplorerNode) => void; onOpenFile: (node: ExplorerNode) => void;
onFileHistory: (node: ExplorerNode) => void;
onBlame: (node: ExplorerNode) => void; onBlame: (node: ExplorerNode) => void;
collapsed?: boolean; collapsed?: boolean;
onToggleCollapsed?: () => void; onToggleCollapsed?: () => void;
@@ -54,6 +56,7 @@
onCollapseAllFolders = () => {}, onCollapseAllFolders = () => {},
onSelectNode = () => {}, onSelectNode = () => {},
onOpenFile = () => {}, onOpenFile = () => {},
onFileHistory = () => {},
onBlame = () => {}, onBlame = () => {},
collapsed = false, collapsed = false,
onToggleCollapsed = () => {}, onToggleCollapsed = () => {},
@@ -175,7 +178,7 @@
contextNode = node; contextNode = node;
contextMenuX = Math.max(8, Math.min(event.clientX + 2, window.innerWidth - 192)); contextMenuX = Math.max(8, Math.min(event.clientX + 2, window.innerWidth - 192));
contextMenuY = Math.max(8, Math.min(event.clientY + 2, window.innerHeight - 56)); contextMenuY = Math.max(8, Math.min(event.clientY + 2, window.innerHeight - 132));
} }
function closeFileContextMenu() { function closeFileContextMenu() {
@@ -196,6 +199,13 @@
onBlame(node); onBlame(node);
} }
function openContextFileHistory() {
const node = contextNode;
if (!node || node.kind !== "file" || !node.tracked) return;
closeFileContextMenu();
onFileHistory(node);
}
function handleWindowKeydown(event: KeyboardEvent) { function handleWindowKeydown(event: KeyboardEvent) {
if (event.key === "Escape") closeFileContextMenu(); if (event.key === "Escape") closeFileContextMenu();
} }
@@ -261,12 +271,14 @@
{:else} {:else}
<div class="explorer-list overflow-auto p-2"> <div class="explorer-list overflow-auto p-2">
{#each visibleNodes as node (`${node.kind}:${node.path}`)} {#each visibleNodes as node (`${node.kind}:${node.path}`)}
<!-- svelte-ignore a11y_no_static_element_interactions -->
<div <div
class="explorer-row" class="explorer-row"
class:active={selectedExplorerPath === node.path && selectedExplorerKind === node.kind} class:active={selectedExplorerPath === node.path && selectedExplorerKind === node.kind}
class:folder={node.kind === "folder"} class:folder={node.kind === "folder"}
style={`--depth: ${node.depth}`} style={`--depth: ${node.depth}`}
title={node.path} title={node.path}
oncontextmenu={(event) => openFileContextMenu(event, node)}
> >
{#if node.kind === "folder"} {#if node.kind === "folder"}
<button <button
@@ -328,9 +340,8 @@
class="explorer-select" class="explorer-select"
type="button" type="button"
onclick={() => onSelectNode(node)} onclick={() => onSelectNode(node)}
oncontextmenu={(event) => openFileContextMenu(event, node)}
disabled={isBusy} disabled={isBusy}
title={`Show history for ${node.path}`} title={`Select ${node.path}`}
> >
<span>{node.name}</span> <span>{node.name}</span>
</button> </button>
@@ -355,6 +366,16 @@
tabindex="-1" tabindex="-1"
aria-label={`Actions for ${contextNode.path}`} aria-label={`Actions for ${contextNode.path}`}
> >
<button
type="button"
role="menuitem"
onclick={openContextFileHistory}
disabled={!contextNode.tracked}
title={contextNode.tracked ? "Show the commit history for this file" : "File history is only available for tracked files"}
>
<History size={14} aria-hidden="true" />
File history
</button>
<button <button
type="button" type="button"
role="menuitem" role="menuitem"
@@ -372,7 +393,7 @@
disabled={!contextNode.tracked || contextNode.status === "deleted"} disabled={!contextNode.tracked || contextNode.status === "deleted"}
title={!contextNode.tracked || contextNode.status === "deleted" ? "Blame is only available for tracked files" : "Show blame for this file"} title={!contextNode.tracked || contextNode.status === "deleted" ? "Blame is only available for tracked files" : "Show blame for this file"}
> >
<History size={14} aria-hidden="true" /> <FileSearch size={14} aria-hidden="true" />
Blame Blame
</button> </button>
</div> </div>