Skip to content

Worktree right click#183

Closed
Kitenite wants to merge 3 commits intomainfrom
olive-cloud-73
Closed

Worktree right click#183
Kitenite wants to merge 3 commits intomainfrom
olive-cloud-73

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented Nov 29, 2025

Description

Related Issues

Type of Change

  • Bug fix
  • New feature
  • Documentation
  • Refactor
  • Other (please describe):

Testing

Screenshots (if applicable)

Additional Notes

Summary by CodeRabbit

  • New Features

    • Right-click workspace tabs to access a context menu with options to rename and open the workspace location in your file manager.
  • Refactor

    • Improved internal directory resolution logic and optimized hotkey registrations.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link
Copy Markdown

vercel Bot commented Nov 29, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
website Error Error Nov 29, 2025 6:01pm

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Nov 29, 2025

Walkthrough

This pull request refactors worktree path handling by introducing a centralized utility function, propagating it through workspace data structures and UI components, and adding a context menu with "Open in Finder" functionality to workspace items. It includes terminal router updates, UI component modifications, and minor code formatting adjustments.

Changes

Cohort / File(s) Summary
Worktree utility and workspace routing
apps/desktop/src/lib/trpc/routers/workspaces/utils/worktree.ts, apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts, apps/desktop/src/lib/trpc/routers/terminal/terminal.ts
Added getWorktreePath(worktreeId) utility function for centralized worktree path lookup. Updated workspace router's getAllGrouped to include worktreePath field in grouped workspace objects. Terminal router now uses getWorktreePath for simplified cwd resolution.
Workspace tab UI components
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroup.tsx, apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx
Extended Workspace interface to include worktreePath: string property. Updated WorkspaceItem to accept and propagate worktreePath prop. Modified WorkspaceGroup to pass worktreePath to WorkspaceItem component.
Workspace item context menu
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItemContextMenu.tsx
New component providing right-click context menu with "Rename" and "Open in Finder" options. Invokes TRPC openInFinder mutation with worktreePath when non-empty.
Minor refactoring and formatting
apps/desktop/src/renderer/screens/main/index.tsx, apps/desktop/src/renderer/globals.css, apps/desktop/src/resources/public/theme-boot.js
Refactored three hotkey registrations to single-line format. Adjusted tertiary-active color numeric formatting in light theme CSS. Changed IIFE syntax from function expression to arrow function in theme-boot.js.

Sequence Diagram

sequenceDiagram
    participant User
    participant WorkspaceItem
    participant ContextMenu as WorkspaceItemContextMenu
    participant TRPC
    participant System as System (Finder)

    User->>WorkspaceItem: Right-click on workspace tab
    WorkspaceItem->>ContextMenu: Render context menu
    ContextMenu->>User: Display "Rename" and "Open in Finder" options
    User->>ContextMenu: Click "Open in Finder"
    ContextMenu->>TRPC: Call openInFinder(worktreePath)
    TRPC->>System: Execute system open command
    System->>User: Open Finder at worktree path
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Key areas requiring attention:

  • WorkspaceItemContextMenu integration: Verify proper wrapping of existing WorkspaceItem functionality and that context menu overlays/positioning don't break existing drag-and-drop behavior
  • worktreePath propagation chain: Ensure type consistency across terminal.ts → workspaces.ts → WorkspaceGroup → WorkspaceItem → WorkspaceItemContextMenu
  • TRPC mutation handling: Confirm openInFinder mutation exists, handles empty paths gracefully, and integrates correctly with the component lifecycle
  • theme-boot.js IIFE conversion: Verify arrow function syntax doesn't cause scoping or timing issues with the DOM/CSS variable initialization

Possibly related PRs

Poem

A worktree path now flows with grace, 🐰
Through routers, props, and every place,
Context menus bloom so fine,
Finder opens at your design,
Hop along this refactored trace! ✨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is entirely empty—it contains only the template placeholders with no actual content, related issues, type of change selection, testing details, or additional context provided. Fill in all required sections: describe the changes, link related issues if any, select the type of change, document testing approach, and add any relevant notes about the implementation.
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Worktree right click' is vague and does not clearly describe the main changes in the PR, which include refactoring worktree path resolution and adding a context menu to workspace tabs. Consider a more descriptive title such as 'Add right-click context menu to workspace tabs' or 'Extract worktree path resolution and add finder integration'.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch olive-cloud-73

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
apps/desktop/src/lib/trpc/routers/terminal/terminal.ts (1)

140-152: Consider using getWorktreePath here for consistency.

This procedure manually looks up the worktree path, duplicating the logic now encapsulated in getWorktreePath. Using the utility here would improve consistency and reduce duplication.

 		getWorkspaceCwd: publicProcedure
 			.input(z.string())
 			.query(async ({ input: workspaceId }) => {
 				const workspace = db.data.workspaces.find((w) => w.id === workspaceId);
 				if (!workspace) {
 					return undefined;
 				}
-
-				const worktree = db.data.worktrees.find(
-					(wt) => wt.id === workspace.worktreeId,
-				);
-				return worktree?.path;
+				return getWorktreePath(workspace.worktreeId);
 			}),
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItemContextMenu.tsx (1)

1-42: Context menu wiring looks good; double‑check worktreePath assumptions

This component cleanly encapsulates the context menu and correctly guards the openInFinder.mutate call behind a truthy worktreePath, while using the trpc alias as per desktop guidelines. One thing to verify is that all callers (and the backing TRPC router) truly guarantee worktreePath is a string (with “no path” represented as ""), not undefined. If getWorktreePath can return undefined end‑to‑end, consider either making the prop worktreePath?: string or normalizing it at the data layer so the type here stays accurate. From a UX angle, if some workspaces legitimately have no worktree, it may be worth later disabling or hiding the “Open in Finder” item rather than making it a no‑op on click.

apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx (1)

78-151: Add a null‑check in the drag/drop ref callback for extra safety

The new structure with WorkspaceItemContextMenu wrapping the draggable button and inline rename/delete UI looks good and preserves the previous behaviors (activate on mousedown, rename on double‑click, delete via dialog, attention badge, etc.). One small robustness improvement: the ref callback currently calls drag(drop(node)); unconditionally. On unmount, React will invoke the ref with null, so guarding against that avoids coupling to react‑dnd’s handling of null:

-					<button
+					<button
 						type="button"
-						ref={(node) => {
-							drag(drop(node));
-						}}
+						ref={(node) => {
+							if (node) {
+								drag(drop(node));
+							}
+						}}

This keeps the behavior identical for mounted elements while making the connector more defensive against lifecycle quirks.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4b4935d and 13d9fa4.

📒 Files selected for processing (9)
  • apps/desktop/src/lib/trpc/routers/terminal/terminal.ts (2 hunks)
  • apps/desktop/src/lib/trpc/routers/workspaces/utils/worktree.ts (1 hunks)
  • apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts (3 hunks)
  • apps/desktop/src/renderer/globals.css (1 hunks)
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroup.tsx (2 hunks)
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx (3 hunks)
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItemContextMenu.tsx (1 hunks)
  • apps/desktop/src/renderer/screens/main/index.tsx (1 hunks)
  • apps/desktop/src/resources/public/theme-boot.js (1 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
apps/desktop/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc

Files:

  • apps/desktop/src/lib/trpc/routers/workspaces/utils/worktree.ts
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroup.tsx
  • apps/desktop/src/resources/public/theme-boot.js
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItemContextMenu.tsx
  • apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts
  • apps/desktop/src/lib/trpc/routers/terminal/terminal.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
apps/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.{ts,tsx}: Please use alias as defined in tsconfig.json when possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary

Files:

  • apps/desktop/src/lib/trpc/routers/workspaces/utils/worktree.ts
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroup.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItemContextMenu.tsx
  • apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts
  • apps/desktop/src/lib/trpc/routers/terminal/terminal.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Avoid using any type - use explicit types instead for type safety
Use camelCase for variable and function names following existing codebase patterns
Keep diffs minimal with targeted edits only - avoid unnecessary changes when making modifications
Follow existing patterns and match the codebase style when writing new code

Files:

  • apps/desktop/src/lib/trpc/routers/workspaces/utils/worktree.ts
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroup.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItemContextMenu.tsx
  • apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts
  • apps/desktop/src/lib/trpc/routers/terminal/terminal.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
apps/desktop/src/lib/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Never import Node.js modules in shared code like src/lib/electron-router-dom.ts - this code runs in both main and renderer processes

Files:

  • apps/desktop/src/lib/trpc/routers/workspaces/utils/worktree.ts
  • apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts
  • apps/desktop/src/lib/trpc/routers/terminal/terminal.ts
**/components/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

**/components/**/*.tsx: Create one folder per component with structure: ComponentName/ComponentName.tsx + index.ts for barrel export
Co-locate tests next to the component file they test (e.g., ComponentName.test.tsx)
Co-locate dependencies (utils, hooks, constants, config, stories) next to the file using them
Use nested components/ subdirectory within a parent component only if a sub-component is used 2+ times within that parent; otherwise keep it in the parent's components/ folder
One component per file - avoid multi-component files

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroup.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItemContextMenu.tsx
apps/desktop/src/renderer/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never import Node.js modules (fs, path, os, net, etc.) in renderer process code - browser environment only

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroup.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItemContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/index.tsx
apps/desktop/src/renderer/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Call IPC methods using window.ipcRenderer.invoke() with object parameters - TypeScript will infer the exact response type automatically

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroup.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItemContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/index.tsx
🧠 Learnings (2)
📚 Learning: 2025-11-28T01:03:47.951Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T01:03:47.951Z
Learning: Applies to **/*.{ts,tsx} : Keep diffs minimal with targeted edits only - avoid unnecessary changes when making modifications

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroup.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx
  • apps/desktop/src/lib/trpc/routers/terminal/terminal.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
📚 Learning: 2025-11-24T21:33:13.244Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-11-24T21:33:13.244Z
Learning: Applies to apps/desktop/**/*.{ts,tsx} : Please use alias as defined in `tsconfig.json` when possible

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItemContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/index.tsx
🧬 Code graph analysis (3)
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx (2)
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItemContextMenu.tsx (1)
  • WorkspaceItemContextMenu (17-42)
packages/ui/src/lib/utils.ts (1)
  • cn (4-6)
apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts (1)
apps/desktop/src/lib/trpc/routers/workspaces/utils/worktree.ts (1)
  • getWorktreePath (6-9)
apps/desktop/src/lib/trpc/routers/terminal/terminal.ts (1)
apps/desktop/src/lib/trpc/routers/workspaces/utils/worktree.ts (1)
  • getWorktreePath (6-9)
🔇 Additional comments (11)
apps/desktop/src/renderer/screens/main/index.tsx (1)

32-47: Hotkey refactoring looks solid.

The three hotkey registrations maintain their original logic with appropriate conditional guards (workspace view checks and workspace ID validation). Dependency arrays are complete and correct for each hook, preventing stale closure issues. The refactoring keeps changes minimal and focused on the hotkey handlers themselves.

apps/desktop/src/renderer/globals.css (1)

74-74: LGTM!

Minor numeric formatting cleanup with no visual impact.

apps/desktop/src/resources/public/theme-boot.js (1)

3-12: LGTM!

Arrow function IIFE is a valid modernization. Since neither this nor arguments is used here, the behavior is identical.

apps/desktop/src/lib/trpc/routers/workspaces/utils/worktree.ts (1)

1-9: LGTM!

Clean utility function that centralizes worktree path lookup logic. Good use of optional chaining and appropriate return type.

apps/desktop/src/lib/trpc/routers/terminal/terminal.ts (2)

6-6: LGTM!

Good use of the centralized utility.


49-51: LGTM!

Clean refactor using the new utility function. The ternary expression is clear and handles the optional workspace case well.

apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts (3)

15-15: LGTM!

Correct import of the new utility.


153-165: LGTM!

The type definition is clear and properly includes the new worktreePath field.


183-190: LGTM!

Good use of spread operator with the new worktreePath field. The fallback to empty string is appropriate for cases where the worktree might not exist.

apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx (1)

17-39: Prop plumbing for worktreePath is consistent, just ensure upstream data matches

Adding worktreePath: string to WorkspaceItemProps and destructuring it alongside the existing fields keeps the API clear and makes it easy to wire into the context menu. This assumes every workspace in this group has a concrete string value; if the TRPC payload can omit or null this field for some workspaces, it would be safer to type it as optional (or normalize it to "" at the data layer) to keep types and runtime behavior aligned.

apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroup.tsx (1)

6-12: worktreePath propagation into WorkspaceItem is straightforward; verify it’s always populated

Extending the Workspace interface with worktreePath: string and passing it directly into WorkspaceItem keeps the data flow simple and matches the new context menu behavior. Just ensure the TRPC workspaces payload and any mock/test data always include worktreePath for every workspace; otherwise you may want to mark it optional here (and in WorkspaceItemProps) or normalize it at the query/transform layer so the type remains truthful.

Also applies to: 72-82

@Kitenite Kitenite closed this Dec 1, 2025
@Kitenite Kitenite deleted the olive-cloud-73 branch December 1, 2025 00:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant