diff --git a/nix/package.nix b/nix/package.nix index db9dd06ca..598e6e881 100644 --- a/nix/package.nix +++ b/nix/package.nix @@ -42,7 +42,7 @@ buildNpmPackage rec { # To update: run `nix build` with lib.fakeHash, copy the `got:` hash. # CI auto-updates this when package-lock.json changes (see .github/workflows/). - npmDepsHash = "sha256-gyCcVTlgLk8+G/OtwZT/GomN2lYe7uEcDoLp1ZQoc5M="; + npmDepsHash = "sha256-6NXZBZwIxCBYxaTe+lq6D8uNaJzL3+z/VUodVS0sS9o="; # Prevent onnxruntime-node's install script from running during automatic # npm rebuild (it tries to download from api.nuget.org, which fails in the sandbox). diff --git a/packages/app/src/screens/workspace/workspace-desktop-tabs-row.tsx b/packages/app/src/screens/workspace/workspace-desktop-tabs-row.tsx index 110f01970..93493da3b 100644 --- a/packages/app/src/screens/workspace/workspace-desktop-tabs-row.tsx +++ b/packages/app/src/screens/workspace/workspace-desktop-tabs-row.tsx @@ -1,4 +1,12 @@ -import { useCallback, useMemo, useState, type Dispatch, type SetStateAction } from "react"; +import { + useCallback, + useEffect, + useMemo, + useRef, + useState, + type Dispatch, + type SetStateAction, +} from "react"; import { ActivityIndicator, Platform, @@ -101,6 +109,27 @@ function getFallbackTabLabel(tab: WorkspaceTabDescriptor): string { return "Agent"; } +function useMiddleClickClose(onClose: () => void) { + const ref = useRef(null); + + useEffect(() => { + const node = ref.current as unknown as HTMLElement | null; + if (!node) return; + + function handleAuxClick(event: MouseEvent) { + if (event.button === 1) { + event.preventDefault(); + onClose(); + } + } + + node.addEventListener("auxclick", handleAuxClick); + return () => node.removeEventListener("auxclick", handleAuxClick); + }, [onClose]); + + return ref; +} + function TabChip({ tab, isActive, @@ -140,6 +169,9 @@ function TabChip({ }) { const { theme } = useUnistyles(); const { closeButtonTestId, contextMenuTestId, menuEntries } = resolvedTab; + const middleClickRef = useMiddleClickClose( + useCallback(() => void onCloseTab(tab.tabId), [onCloseTab, tab.tabId]), + ); const [hovered, setHovered] = useState(false); const isHighlighted = isActive || hovered || isCloseHovered; const closeButtonDragBlockers = @@ -155,6 +187,7 @@ function TabChip({ : undefined; return ( + @@ -325,6 +358,7 @@ function TabChip({ )} + ); }