import { useRef, useState } from "react"; import { executeAction } from "@/platform/actions"; import { useTx } from "@/platform/i18n"; import { reorderedTabs, useWindowGroup } from "@/platform/windowGroups"; import { Icon, IconButton, showContextMenu } from "@/ui"; import { notifications } from "./contributions"; import styles from "./WindowGroupTabs.module.css"; function run(work: Promise) { void work.catch((e) => notifications().notify({ level: "error", title: "Window group", body: String(e) })); } export function WindowGroupTabs() { const tabs = useWindowGroup((state) => state.tabs); const drag = useRef<{ label: string; x: number; moved: boolean } | null>(null); const [dragging, setDragging] = useState(null); const tx = useTx(); if (tabs.length < 2) return null; return (
{tabs.map((tab) => (
{ drag.current = null; if (e.button === 0 && (e.target as Element).closest('[role="tab"]')) drag.current = { label: tab.label, x: e.clientX, moved: false }; }} onPointerMove={(e) => { if (drag.current && Math.abs(e.clientX - drag.current.x) > 5) { drag.current.moved = true; e.currentTarget.setPointerCapture(e.pointerId); setDragging(tab.label); } }} onPointerUp={(e) => { const source = drag.current; if (source?.moved) { const target = document .elementFromPoint(e.clientX, e.clientY) ?.closest("[data-project-tab]")?.dataset.projectTab; if (target) run(executeAction("window.reorderTabs", reorderedTabs(tabs, source.label, target))); } setDragging(null); // Keep the moved flag through the click following pointerup. if (!source?.moved) drag.current = null; }} onPointerCancel={() => { drag.current = null; setDragging(null); }} onClickCapture={(e) => { if (drag.current?.moved) { e.preventDefault(); e.stopPropagation(); drag.current = null; } }} onContextMenu={(e) => { e.preventDefault(); const index = tabs.indexOf(tab); showContextMenu(e, [ { label: "Move Tab to New Window", disabled: !tab.current, run: () => executeAction("window.detachTab"), }, { kind: "separator" }, { label: "Close Tab", run: () => executeAction("window.closeTab", tab.label) }, { label: "Close Other Tabs", run: () => executeAction("window.closeOtherTabs", tab.label) }, { label: "Close Tabs to the Left", disabled: index <= 0, run: () => executeAction("window.closeTabsToLeft", tab.label), }, { label: "Close Tabs to the Right", disabled: index >= tabs.length - 1, run: () => executeAction("window.closeTabsToRight", tab.label), }, ]); }} > run(executeAction("window.closeTab", tab.label))} />
))}
); }