diff --git a/apps/desktop/src/lib/trpc/routers/terminal/terminal.ts b/apps/desktop/src/lib/trpc/routers/terminal/terminal.ts index 49166e4c337..2a41ebc6471 100644 --- a/apps/desktop/src/lib/trpc/routers/terminal/terminal.ts +++ b/apps/desktop/src/lib/trpc/routers/terminal/terminal.ts @@ -3,6 +3,7 @@ import { db } from "main/lib/db"; import { terminalManager } from "main/lib/terminal-manager"; import { z } from "zod"; import { publicProcedure, router } from "../.."; +import { getWorktreePath } from "../workspaces/utils/worktree"; /** * Terminal router using TerminalManager with node-pty @@ -44,17 +45,10 @@ export const createTerminalRouter = () => { // Get workspace to determine cwd and workspace name const workspace = db.data.workspaces.find((w) => w.id === workspaceId); - let cwd: string | undefined = cwdOverride; const workspaceName = workspace?.name || "Workspace"; - - if (!cwd && workspace) { - const worktree = db.data.worktrees.find( - (wt) => wt.id === workspace.worktreeId, - ); - if (worktree) { - cwd = worktree.path; - } - } + const cwd = + cwdOverride || + (workspace ? getWorktreePath(workspace.worktreeId) : undefined); const result = await terminalManager.createOrAttach({ tabId, diff --git a/apps/desktop/src/lib/trpc/routers/workspaces/utils/worktree.ts b/apps/desktop/src/lib/trpc/routers/workspaces/utils/worktree.ts new file mode 100644 index 00000000000..1300840572e --- /dev/null +++ b/apps/desktop/src/lib/trpc/routers/workspaces/utils/worktree.ts @@ -0,0 +1,9 @@ +import { db } from "main/lib/db"; + +/** + * Gets the worktree path for a workspace + */ +export function getWorktreePath(worktreeId: string): string | undefined { + const worktree = db.data.worktrees.find((w) => w.id === worktreeId); + return worktree?.path; +} diff --git a/apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts b/apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts index 740f94c9d3d..eba89219e89 100644 --- a/apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts +++ b/apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts @@ -12,6 +12,7 @@ import { worktreeExists, } from "./utils/git"; import { copySetupFiles, loadSetupConfig } from "./utils/setup"; +import { getWorktreePath } from "./utils/worktree"; export const createWorkspacesRouter = () => { return router({ @@ -153,6 +154,7 @@ export const createWorkspacesRouter = () => { id: string; projectId: string; worktreeId: string; + worktreePath: string; name: string; tabOrder: number; createdAt: number; @@ -180,7 +182,10 @@ export const createWorkspacesRouter = () => { for (const workspace of workspaces) { if (groupsMap.has(workspace.projectId)) { - groupsMap.get(workspace.projectId)?.workspaces.push(workspace); + groupsMap.get(workspace.projectId)?.workspaces.push({ + ...workspace, + worktreePath: getWorktreePath(workspace.worktreeId) ?? "", + }); } } diff --git a/apps/desktop/src/renderer/globals.css b/apps/desktop/src/renderer/globals.css index a8fb0c11bb0..bd76cf31cd8 100644 --- a/apps/desktop/src/renderer/globals.css +++ b/apps/desktop/src/renderer/globals.css @@ -71,7 +71,7 @@ --accent: oklch(0.97 0 0); --accent-foreground: oklch(0.205 0 0); --tertiary: oklch(0.95 0.003 40); - --tertiary-active: oklch(0.90 0.003 40); + --tertiary-active: oklch(0.9 0.003 40); --destructive: oklch(0.577 0.245 27.325); --destructive-foreground: oklch(0.985 0 0); --border: oklch(0.922 0 0); diff --git a/apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroup.tsx b/apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroup.tsx index 41f3796c871..3d15268089e 100644 --- a/apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroup.tsx +++ b/apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroup.tsx @@ -6,6 +6,7 @@ import { WorkspaceItem } from "./WorkspaceItem"; interface Workspace { id: string; projectId: string; + worktreePath: string; name: string; tabOrder: number; } @@ -71,6 +72,7 @@ export function WorkspaceGroup({ -
- {/* Main workspace button */} - + {needsAttention && ( + + + + + )} + + )} + - -
+ + + void; +} + +export function WorkspaceItemContextMenu({ + children, + worktreePath, + onRename, +}: WorkspaceItemContextMenuProps) { + const openInFinder = trpc.external.openInFinder.useMutation(); + + const handleOpenInFinder = () => { + if (worktreePath) { + openInFinder.mutate(worktreePath); + } + }; + + return ( + + {children} + + Rename + + + Open in Finder + + + + ); +} diff --git a/apps/desktop/src/renderer/screens/main/index.tsx b/apps/desktop/src/renderer/screens/main/index.tsx index 46c38ff384b..5a73fdf33b6 100644 --- a/apps/desktop/src/renderer/screens/main/index.tsx +++ b/apps/desktop/src/renderer/screens/main/index.tsx @@ -29,34 +29,22 @@ export function MainScreen() { const isWorkspaceView = currentView === "workspace"; // Sidebar toggle shortcut - only in workspace view - useHotkeys( - "meta+s", - () => { - if (isWorkspaceView) toggleSidebar(); - }, - [toggleSidebar, isWorkspaceView], - ); + useHotkeys("meta+s", () => { + if (isWorkspaceView) toggleSidebar(); + }, [toggleSidebar, isWorkspaceView]); // Split view shortcuts - only in workspace view - useHotkeys( - "meta+d", - () => { - if (isWorkspaceView && activeWorkspaceId) { - splitTabVertical(activeWorkspaceId); - } - }, - [activeWorkspaceId, splitTabVertical, isWorkspaceView], - ); + useHotkeys("meta+d", () => { + if (isWorkspaceView && activeWorkspaceId) { + splitTabVertical(activeWorkspaceId); + } + }, [activeWorkspaceId, splitTabVertical, isWorkspaceView]); - useHotkeys( - "meta+shift+d", - () => { - if (isWorkspaceView && activeWorkspaceId) { - splitTabHorizontal(activeWorkspaceId); - } - }, - [activeWorkspaceId, splitTabHorizontal, isWorkspaceView], - ); + useHotkeys("meta+shift+d", () => { + if (isWorkspaceView && activeWorkspaceId) { + splitTabHorizontal(activeWorkspaceId); + } + }, [activeWorkspaceId, splitTabHorizontal, isWorkspaceView]); return ( diff --git a/apps/desktop/src/resources/public/theme-boot.js b/apps/desktop/src/resources/public/theme-boot.js index 3cbf9d430cf..b7070f02665 100644 --- a/apps/desktop/src/resources/public/theme-boot.js +++ b/apps/desktop/src/resources/public/theme-boot.js @@ -1,6 +1,6 @@ // Apply saved theme class immediately to prevent flash of wrong colors // This runs before React hydration to ensure correct initial appearance -(function () { +(() => { try { var themeType = localStorage.getItem("theme-type"); document.documentElement.classList.add(