Skip to content

fix(desktop): make it so you can close projects#480

Merged
AviPeltz merged 2 commits intomainfrom
close-project
Dec 23, 2025
Merged

fix(desktop): make it so you can close projects#480
AviPeltz merged 2 commits intomainfrom
close-project

Conversation

@AviPeltz
Copy link
Copy Markdown
Collaborator

@AviPeltz AviPeltz commented Dec 23, 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
    • Users can now close projects directly from the workspace context menu. Closing a project properly terminates associated terminal processes and cleans up related workspaces.

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

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 23, 2025

Walkthrough

This PR introduces a "close project" feature enabling users to cleanly shut down projects. The backend mutation terminates associated terminal processes, removes related workspaces, hides the project, and handles active workspace updates. A React hook wraps the mutation with automatic cache invalidation, and a UI menu item integrates the feature.

Changes

Cohort / File(s) Summary
Backend TRPC Mutation
apps/desktop/src/lib/trpc/routers/projects/projects.ts
New close mutation that terminates all terminals for a project's workspaces, removes workspace records, hides the project by nulling tabOrder, updates active workspace if necessary, and returns terminalWarning if failures occurred. Tracks project_closed analytics event.
Frontend Query Hook
apps/desktop/src/renderer/react-query/projects/useCloseProject.ts, apps/desktop/src/renderer/react-query/projects/index.ts
New useCloseProject hook wrapping the TRPC mutation with automatic invalidation of workspace and project recents queries on success. Exports hook via barrel export.
UI Integration
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroupContextMenu.tsx
Imports and instantiates useCloseProject hook; replaces placeholder menu action with closeProject.mutate({ id: projectId }) call; updates button label to "Close Project" and styling to destructive emphasis.

Sequence Diagram

sequenceDiagram
    actor User
    participant UI as Context Menu
    participant Hook as useCloseProject<br/>(React Query)
    participant Server as TRPC Server<br/>(projects.close)
    participant TM as Terminal<br/>Manager
    participant DB as Database
    participant QC as Query<br/>Client

    User->>UI: Click "Close Project"
    UI->>Hook: mutate({ id })
    Hook->>Server: Call projects.close mutation
    
    rect rgb(220, 240, 220)
    note right of Server: Close Project Flow
    Server->>DB: Get project + workspaces
    Server->>TM: killByWorkspaceId (all workspaces)
    TM-->>Server: { failures: [...] }
    Server->>DB: Delete workspace records
    Server->>DB: Null project.tabOrder (hide)
    Server->>DB: Update active workspace if needed
    Server-->>Hook: { success, terminalWarning }
    end
    
    rect rgb(240, 220, 220)
    note right of QC: Cache Invalidation
    Hook->>QC: Invalidate workspace queries
    Hook->>QC: Invalidate project recents queries
    end
    
    Hook->>Hook: Call onSuccess callback (if provided)
    Hook-->>UI: Mutation complete
    UI-->>User: Menu closes, UI updates
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

The backend mutation logic requires careful review for edge cases (terminal cleanup failure aggregation, workspace record deletion integrity, active workspace state updates). The React hook is straightforward but depends on correct TRPC mutation signature and invalidation strategy. UI integration is minimal but requires verification of hook integration pattern.

Possibly related PRs

  • Group tabs for workspaces #116 — Introduced tabOrder and color handling in projects router; this PR nulls tabOrder to hide projects, directly building on that feature's logic.

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description contains only the template skeleton with no substantive details about what was changed, why, testing steps, or related issues. Fill in the Description section with details of changes, provide Related Issues links, describe testing steps performed, and include any additional context about the implementation.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: adding the ability to close projects in the desktop application.
✨ 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 close-project

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 (1)
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroupContextMenu.tsx (1)

150-158: Consider adding a confirmation dialog for this destructive action.

Closing a project terminates all terminal processes and removes workspace records. Users could accidentally trigger this from the context menu. A confirmation dialog would prevent accidental data loss.

Additionally, the backend returns a terminalWarning when processes fail to terminate cleanly, but this isn't surfaced to the user. Consider showing a toast/notification when terminalWarning is present.

🔎 Suggested approach
const closeProject = useCloseProject({
  onSuccess: (data) => {
    if (data.terminalWarning) {
      // Show toast notification with terminalWarning
    }
  },
});

// In the button onClick, show confirmation first:
onClick={() => {
  if (window.confirm('Close this project? This will terminate all running terminals.')) {
    closeProject.mutate({ id: projectId });
  }
}}

Or use a proper dialog component from your UI library for a better UX.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b5de00e and 639ee5c.

📒 Files selected for processing (4)
  • apps/desktop/src/lib/trpc/routers/projects/projects.ts
  • apps/desktop/src/renderer/react-query/projects/index.ts
  • apps/desktop/src/renderer/react-query/projects/useCloseProject.ts
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroupContextMenu.tsx
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Avoid using any type in TypeScript - maintain type safety unless absolutely necessary

Files:

  • apps/desktop/src/renderer/react-query/projects/index.ts
  • apps/desktop/src/lib/trpc/routers/projects/projects.ts
  • apps/desktop/src/renderer/react-query/projects/useCloseProject.ts
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroupContextMenu.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Run Biome for formatting, linting, import organization, and safe fixes at the root level using bun run lint:fix

Files:

  • apps/desktop/src/renderer/react-query/projects/index.ts
  • apps/desktop/src/lib/trpc/routers/projects/projects.ts
  • apps/desktop/src/renderer/react-query/projects/useCloseProject.ts
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroupContextMenu.tsx
apps/desktop/src/renderer/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never import Node.js modules in renderer process or shared code - use only in main process (src/main/)

Files:

  • apps/desktop/src/renderer/react-query/projects/index.ts
  • apps/desktop/src/renderer/react-query/projects/useCloseProject.ts
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroupContextMenu.tsx
apps/desktop/src/{main,renderer,preload}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use type-safe IPC communication - define channel types in apps/desktop/src/shared/ipc-channels.ts before implementing handlers

Files:

  • apps/desktop/src/renderer/react-query/projects/index.ts
  • apps/desktop/src/renderer/react-query/projects/useCloseProject.ts
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroupContextMenu.tsx
apps/desktop/**/*.{ts,tsx}

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

apps/desktop/**/*.{ts,tsx}: For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc
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.
For tRPC subscriptions with trpc-electron, ALWAYS use the observable pattern from @trpc/server/observable instead of async generators, as the library explicitly checks isObservable(result) and throws an error otherwise

Files:

  • apps/desktop/src/renderer/react-query/projects/index.ts
  • apps/desktop/src/lib/trpc/routers/projects/projects.ts
  • apps/desktop/src/renderer/react-query/projects/useCloseProject.ts
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroupContextMenu.tsx
**/{components,features}/**/[!.]*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Organize project structure with one folder per component: ComponentName/ComponentName.tsx with index.ts barrel export

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroupContextMenu.tsx
**/{components,features}/**/*.{ts,tsx,test.ts,test.tsx,stories.tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Co-locate component dependencies (utils, hooks, constants, config, tests, stories) next to the file using them

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroupContextMenu.tsx
**/*.{tsx,css}

📄 CodeRabbit inference engine (AGENTS.md)

Use React + TailwindCSS v4 + shadcn/ui for UI development

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroupContextMenu.tsx
**/{components,features}/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

**/{components,features}/**/*.tsx: Nest components in parent's components/ folder if used only once, promote to highest shared parent's components/ if used 2+ times
Use one component per file - do not combine multiple components in a single file

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroupContextMenu.tsx
🧠 Learnings (1)
📚 Learning: 2025-12-18T23:19:10.415Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.415Z
Learning: Applies to **/{components,features}/**/[!.]*.tsx : Organize project structure with one folder per component: ComponentName/ComponentName.tsx with index.ts barrel export

Applied to files:

  • apps/desktop/src/renderer/react-query/projects/index.ts
🧬 Code graph analysis (3)
apps/desktop/src/lib/trpc/routers/projects/projects.ts (2)
apps/desktop/src/main/lib/db/index.ts (1)
  • db (69-76)
apps/desktop/src/main/lib/analytics/index.ts (1)
  • track (45-66)
apps/desktop/src/renderer/react-query/projects/useCloseProject.ts (1)
apps/desktop/src/renderer/react-query/projects/index.ts (1)
  • useCloseProject (1-1)
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceGroupContextMenu.tsx (1)
apps/desktop/src/renderer/react-query/projects/useCloseProject.ts (1)
  • useCloseProject (7-24)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (4)
apps/desktop/src/renderer/react-query/projects/index.ts (1)

1-4: LGTM!

The barrel export correctly exposes the new useCloseProject hook, consistent with the existing export pattern.

apps/desktop/src/renderer/react-query/projects/useCloseProject.ts (1)

7-23: LGTM!

Well-structured hook that properly wraps the tRPC mutation with automatic query invalidation. The pattern of spreading options and chaining the user's onSuccess callback is correct.

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

554-613: LGTM!

The close mutation implementation is well-structured:

  • Properly collects workspaces before modifications
  • Terminates terminals gracefully with failure tracking
  • Correctly updates lastActiveWorkspaceId by sorting remaining workspaces
  • Hides project (via tabOrder = null) rather than deleting, allowing future reopening
  • Analytics tracking appropriately placed after successful operation

569-575: Consider whether terminal cleanup failures should affect the close operation.

Currently, failed terminal terminations are aggregated and returned as a warning, but the close operation proceeds regardless. This is likely the correct UX (don't block user from closing), but verify this matches the intended behavior.

If a terminal truly can't be killed, the user might expect the close to fail or at least see the warning prominently.

@AviPeltz AviPeltz merged commit 63b341b into main Dec 23, 2025
5 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

Service Status
Neon Database (Neon) ⚠️

Thank you for your contribution! 🎉


Preview resources have been processed for cleanup

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