261 lines · 7.9 KB · TypeScript
RawDownload
import type { KeybindingCommand, ScopedThreadRef } from "@t3tools/contracts";import { useCallback, useMemo } from "react"; import { useCommandPaletteStore } from "../commandPaletteStore";import {  useFocusedWorkspaceSurface,  useWorkspaceDocument,  useWorkspaceStore,} from "../workspace/store";import type { WorkspaceSurfaceInstance } from "../workspace/types"; export const WORKSPACE_COMMAND_IDS = [  "workspace.terminal.splitRight",  "workspace.terminal.splitDown",  "workspace.terminal.newTab",  "workspace.pane.splitRight",  "workspace.pane.splitDown",  "workspace.focus.left",  "workspace.focus.right",  "workspace.focus.up",  "workspace.focus.down",  "workspace.pane.close",  "workspace.pane.moveLeft",  "workspace.pane.moveRight",  "workspace.pane.moveUp",  "workspace.pane.moveDown",  "workspace.tab.moveLeft",  "workspace.tab.moveRight",  "workspace.tab.moveUp",  "workspace.tab.moveDown",] as const satisfies readonly KeybindingCommand[]; export type WorkspaceCommandId = (typeof WORKSPACE_COMMAND_IDS)[number]; export const WORKSPACE_COMMAND_METADATA: Record<  WorkspaceCommandId,  {    searchTerms: readonly string[];    title: string;  }> = {  "workspace.terminal.splitRight": {    title: "Open terminal in split right",    searchTerms: ["terminal", "split", "right", "pane", "workspace"],  },  "workspace.terminal.splitDown": {    title: "Open terminal in split down",    searchTerms: ["terminal", "split", "down", "bottom", "pane", "workspace"],  },  "workspace.terminal.newTab": {    title: "Open terminal as tab",    searchTerms: ["terminal", "tab", "pane", "workspace"],  },  "workspace.pane.splitRight": {    title: "Open in split right",    searchTerms: ["split", "pane", "right", "open", "workspace"],  },  "workspace.pane.splitDown": {    title: "Open in split down",    searchTerms: ["split", "pane", "down", "open", "workspace"],  },  "workspace.focus.left": {    title: "Focus pane left",    searchTerms: ["focus", "pane", "left", "workspace"],  },  "workspace.focus.right": {    title: "Focus pane right",    searchTerms: ["focus", "pane", "right", "workspace"],  },  "workspace.focus.up": {    title: "Focus pane up",    searchTerms: ["focus", "pane", "up", "workspace"],  },  "workspace.focus.down": {    title: "Focus pane down",    searchTerms: ["focus", "pane", "down", "workspace"],  },  "workspace.pane.close": {    title: "Close current pane",    searchTerms: ["close", "pane", "window", "workspace"],  },  "workspace.pane.moveLeft": {    title: "Move pane left",    searchTerms: ["move", "pane", "left", "workspace"],  },  "workspace.pane.moveRight": {    title: "Move pane right",    searchTerms: ["move", "pane", "right", "workspace"],  },  "workspace.pane.moveUp": {    title: "Move pane up",    searchTerms: ["move", "pane", "up", "workspace"],  },  "workspace.pane.moveDown": {    title: "Move pane down",    searchTerms: ["move", "pane", "down", "workspace"],  },  "workspace.tab.moveLeft": {    title: "Move tab left",    searchTerms: ["move", "tab", "left", "workspace"],  },  "workspace.tab.moveRight": {    title: "Move tab right",    searchTerms: ["move", "tab", "right", "workspace"],  },  "workspace.tab.moveUp": {    title: "Move tab up",    searchTerms: ["move", "tab", "up", "workspace"],  },  "workspace.tab.moveDown": {    title: "Move tab down",    searchTerms: ["move", "tab", "down", "workspace"],  },}; function threadRefForWorkspaceSurface(  surface: WorkspaceSurfaceInstance | null | undefined,): ScopedThreadRef | null {  if (!surface) {    return null;  }   if (surface.kind === "terminal") {    return surface.input.threadRef;  }   if (surface.input.scope === "server") {    return surface.input.threadRef;  }   return null;} export function isWorkspaceCommandId(  command: string | null | undefined,): command is WorkspaceCommandId {  return WORKSPACE_COMMAND_IDS.includes(command as WorkspaceCommandId);} export function useWorkspaceCommandExecutor() {  const document = useWorkspaceDocument();  const focusedSurface = useFocusedWorkspaceSurface();  const openWorkspaceTarget = useCommandPaletteStore((state) => state.openWorkspaceTarget);  const closeFocusedWindow = useWorkspaceStore((state) => state.closeFocusedWindow);  const focusAdjacentWindow = useWorkspaceStore((state) => state.focusAdjacentWindow);  const moveActiveTabToAdjacentWindow = useWorkspaceStore(    (state) => state.moveActiveTabToAdjacentWindow,  );  const moveFocusedWindow = useWorkspaceStore((state) => state.moveFocusedWindow);  const openTerminalSurfaceForThread = useWorkspaceStore(    (state) => state.openTerminalSurfaceForThread,  );   const focusedWindowId = useMemo(() => {    if (document.focusedWindowId && document.windowsById[document.focusedWindowId]) {      return document.focusedWindowId;    }     return Object.keys(document.windowsById)[0] ?? null;  }, [document]);   const focusedThreadRef = useMemo(    () => threadRefForWorkspaceSurface(focusedSurface),    [focusedSurface],  );   const executeWorkspaceCommand = useCallback(    async (command: WorkspaceCommandId): Promise<boolean> => {      switch (command) {        case "workspace.terminal.splitRight":          if (!focusedThreadRef) {            return false;          }          openTerminalSurfaceForThread(focusedThreadRef, "split-right");          return true;        case "workspace.terminal.splitDown":          if (!focusedThreadRef) {            return false;          }          openTerminalSurfaceForThread(focusedThreadRef, "split-down");          return true;        case "workspace.terminal.newTab":          if (!focusedThreadRef) {            return false;          }          openTerminalSurfaceForThread(focusedThreadRef, "new-tab");          return true;        case "workspace.pane.splitRight":          if (!focusedWindowId) {            return false;          }          openWorkspaceTarget({ disposition: "split-right" });          return true;        case "workspace.pane.splitDown":          if (!focusedWindowId) {            return false;          }          openWorkspaceTarget({ disposition: "split-down" });          return true;        case "workspace.focus.left":          focusAdjacentWindow("left");          return true;        case "workspace.focus.right":          focusAdjacentWindow("right");          return true;        case "workspace.focus.up":          focusAdjacentWindow("up");          return true;        case "workspace.focus.down":          focusAdjacentWindow("down");          return true;        case "workspace.pane.close":          closeFocusedWindow();          return true;        case "workspace.pane.moveLeft":          moveFocusedWindow("left");          return true;        case "workspace.pane.moveRight":          moveFocusedWindow("right");          return true;        case "workspace.pane.moveUp":          moveFocusedWindow("up");          return true;        case "workspace.pane.moveDown":          moveFocusedWindow("down");          return true;        case "workspace.tab.moveLeft":          moveActiveTabToAdjacentWindow("left");          return true;        case "workspace.tab.moveRight":          moveActiveTabToAdjacentWindow("right");          return true;        case "workspace.tab.moveUp":          moveActiveTabToAdjacentWindow("up");          return true;        case "workspace.tab.moveDown":          moveActiveTabToAdjacentWindow("down");          return true;      }    },    [      closeFocusedWindow,      focusAdjacentWindow,      focusedThreadRef,      focusedWindowId,      moveActiveTabToAdjacentWindow,      moveFocusedWindow,      openTerminalSurfaceForThread,      openWorkspaceTarget,    ],  );   return {    canOpenTerminalSurface: focusedThreadRef !== null,    canSplitFocusedPane: focusedWindowId !== null,    executeWorkspaceCommand,    focusedSurface,    focusedThreadRef,    focusedWindowId,  };}