Skip to content

feat(desktop): show pick-workspace prompt on cross-version routes#4211

Merged
Kitenite merged 1 commit intomainfrom
cross-version-content-sel
May 7, 2026
Merged

feat(desktop): show pick-workspace prompt on cross-version routes#4211
Kitenite merged 1 commit intomainfrom
cross-version-content-sel

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented May 7, 2026

Summary

  • When the active version (v1 vs v2) doesn't match the current workspace route, swap the content <Outlet /> for a "Pick a workspace" placeholder so users see the version-correct sidebar list instead of a v1 page rendering inside a v2 shell (or vice versa).

Why / Context

The dashboard sidebar shows v1 or v2 entries based on useIsV2CloudEnabled, but the router still resolves the previously-visited /workspace/$id or /v2-workspace/$id route after a version flip. The user lands on a workspace they can't navigate to from the current sidebar, with no obvious next step.

How It Works

  • DashboardLayout already calls useMatchRoute for /workspace/$workspaceId. Added a parallel match for /v2-workspace/$workspaceId and a versionMismatch boolean — true when the active version disagrees with the matched route.
  • When mismatched, the content slot renders CrossVersionMismatchState (a small empty-state with the existing select-text cursor-text treatment) instead of <Outlet />. The sidebar is untouched, so picking any workspace from it routes the user back to a matching shell.
  • The placeholder copy is generic ("Pick a workspace") — no v1/v2 mention, since to the user this just looks like they haven't chosen one yet.

Manual QA Checklist

v2 active, v1 workspace route

  • In v2 mode, navigate to a /workspace/$id URL (e.g. via back button after toggling)
  • Content shows "Pick a workspace" placeholder, sidebar still shows v2 entries
  • Clicking a v2 workspace from the sidebar renders normally

v1 active, v2 workspace route

  • In v1 mode, navigate to a /v2-workspace/$id URL
  • Content shows the placeholder, sidebar shows v1 entries
  • Clicking a v1 workspace from the sidebar renders normally

No regression on matching routes

  • v2 active + /v2-workspace/$id → workspace renders as before
  • v1 active + /workspace/$id → workspace renders as before
  • Non-workspace routes (settings, automations, tasks, etc.) unaffected in both modes

Testing

  • bun run lint:fix (clean)
  • Typecheck: no new errors introduced (pre-existing route-tree errors unrelated)

Summary by cubic

Show a "Pick a workspace" placeholder when the active version (v1/v2) doesn't match the current workspace route. In this case, DashboardLayout renders CrossVersionMismatchState instead of the <Outlet />, keeping the sidebar intact so users can pick a workspace from the correct version.

Written for commit a73988f. Summary will update on new commits.

Summary by CodeRabbit

  • New Features
    • Added a new cross-version mismatch state that displays when a workspace version is incompatible with your current application settings.

When the active version (v1 vs v2) doesn't match the current workspace
route, swap the content Outlet for a "Pick a workspace" placeholder so
users land on the version-correct sidebar instead of an empty/broken page.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 7, 2026

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ea495337-3f54-4a26-b7b2-133b6c248f9b

📥 Commits

Reviewing files that changed from the base of the PR and between f32667a and a73988f.

📒 Files selected for processing (3)
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/CrossVersionMismatchState/CrossVersionMismatchState.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/CrossVersionMismatchState/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx

📝 Walkthrough

Walkthrough

The PR introduces cross-version mismatch detection in the dashboard. A new component displays a workspace selection prompt when the active workspace route version (V1 or V2) conflicts with the isV2CloudEnabled feature flag. The layout now conditionally renders this state instead of dashboard content when incompatibility is detected.

Changes

Cross-Version Mismatch State

Layer / File(s) Summary
UI Component Definition
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/CrossVersionMismatchState/CrossVersionMismatchState.tsx, apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/CrossVersionMismatchState/index.ts
New CrossVersionMismatchState component renders a centered prompt with an ArrowLeftFromLine icon and workspace selection message. Exported via barrel index.
Layout Integration
apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx
DashboardLayout now detects workspace route version (V1 vs V2), compares against isV2CloudEnabled, and conditionally renders CrossVersionMismatchState on version mismatch instead of the normal routed Outlet.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A mismatch of versions, oh dear!
The rabbit now whispers most clear:
Pick a workspace, you see,
V1 or V2 must agree,
Or this friendly state will appear! 🚀

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: showing a pick-workspace prompt when cross-version route mismatches occur.
Description check ✅ Passed The PR description is comprehensive, covering motivation, implementation details, manual QA checklist, and testing performed. It aligns well with the template structure despite not using explicit section headers.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cross-version-content-sel

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.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 7, 2026

Greptile Summary

Introduces a CrossVersionMismatchState placeholder that replaces <Outlet /> in DashboardLayout when the active cloud version (v1/v2) disagrees with the current workspace route, preventing users from seeing a v1 page inside a v2 shell (or vice versa). The sidebar is left untouched so users can pick a correctly-versioned workspace from it.

  • layout.tsx adds a parallel matchRoute call for /v2-workspace/$workspaceId and a versionMismatch boolean derived from isV2CloudEnabled vs. the matched route; the content slot conditionally renders the new placeholder.
  • CrossVersionMismatchState is a simple icon + copy empty-state with no external dependencies.
  • The CLOSE_WORKSPACE hotkey and the workspaces.get tRPC query are both still active when a v1 route is matched in v2 mode (mismatch case), which is an unintended side-effect of the current implementation.

Confidence Score: 3/5

The content-area guard works correctly, but the CLOSE_WORKSPACE hotkey and workspace tRPC query remain active during the mismatch state, which can surface the delete dialog for a workspace the user has no visible path to.

The new component and the mismatch detection logic are sound. The gap is that versionMismatch only gates Outlet — it does not disable the CLOSE_WORKSPACE hotkey, which is enabled whenever currentWorkspaceId is non-null. In the v2-mode + v1-route scenario, currentWorkspaceId comes from the v1 route match, so the hotkey is active and can open DeleteWorkspaceDialog for a workspace the user should not be operating on from this state.

apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx — the hotkey enabled guard and the workspaces.get query enabled condition both need && !versionMismatch.

Important Files Changed

Filename Overview
apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx Adds v2 route matching and versionMismatch logic to conditionally render CrossVersionMismatchState; CLOSE_WORKSPACE hotkey remains enabled during mismatch, and the workspace query fires unnecessarily when mismatched on a v1 route.
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/CrossVersionMismatchState/CrossVersionMismatchState.tsx New empty-state component rendering 'Pick a workspace' placeholder with an icon; straightforward and correct.
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/CrossVersionMismatchState/index.ts Barrel re-export for the new component; no issues.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[DashboardLayout renders] --> B{isV2CloudEnabled?}
    B -- Yes --> C{onV1WorkspaceRoute?\n/workspace/:id matched}
    B -- No --> D{onV2WorkspaceRoute?\n/v2-workspace/:id matched}
    C -- Yes --> E[versionMismatch = true]
    C -- No --> F[versionMismatch = false]
    D -- Yes --> E
    D -- No --> F
    E --> G[Render CrossVersionMismatchState\n'Pick a workspace']
    F --> H[Render Outlet\nnormal workspace content]
    G --> I[Sidebar still shows\nversion-correct workspace list]
    H --> I
Loading

Comments Outside Diff (2)

  1. apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx, line 91-103 (link)

    P1 CLOSE_WORKSPACE hotkey fires through the mismatch state

    When the user is in v2 mode and lands on a /workspace/$id route, currentWorkspaceId is still non-null (derived from currentWorkspaceMatch), so this hotkey is enabled. If the user triggers it and the workspaces.get query has resolved, deleteTarget gets set and DeleteWorkspaceDialog opens for a workspace they can't navigate to from the current sidebar. The mismatch guard only gates the content <Outlet />, not this side-effect. Adding && !versionMismatch to the enabled option would prevent the hotkey from being active while the placeholder is shown.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx
    Line: 91-103
    
    Comment:
    **CLOSE_WORKSPACE hotkey fires through the mismatch state**
    
    When the user is in v2 mode and lands on a `/workspace/$id` route, `currentWorkspaceId` is still non-null (derived from `currentWorkspaceMatch`), so this hotkey is enabled. If the user triggers it and the `workspaces.get` query has resolved, `deleteTarget` gets set and `DeleteWorkspaceDialog` opens for a workspace they can't navigate to from the current sidebar. The mismatch guard only gates the content `<Outlet />`, not this side-effect. Adding `&& !versionMismatch` to the `enabled` option would prevent the hotkey from being active while the placeholder is shown.
    
    How can I resolve this? If you propose a fix, please make it concise.
  2. apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx, line 55-58 (link)

    P2 When the version mismatch is active on a v1 route (v2 mode), currentWorkspaceId is non-null so this query fires and fetches workspace data that is never shown. Gating with !versionMismatch avoids the unnecessary network call.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx
    Line: 55-58
    
    Comment:
    When the version mismatch is active on a v1 route (v2 mode), `currentWorkspaceId` is non-null so this query fires and fetches workspace data that is never shown. Gating with `!versionMismatch` avoids the unnecessary network call.
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx:91-103
**CLOSE_WORKSPACE hotkey fires through the mismatch state**

When the user is in v2 mode and lands on a `/workspace/$id` route, `currentWorkspaceId` is still non-null (derived from `currentWorkspaceMatch`), so this hotkey is enabled. If the user triggers it and the `workspaces.get` query has resolved, `deleteTarget` gets set and `DeleteWorkspaceDialog` opens for a workspace they can't navigate to from the current sidebar. The mismatch guard only gates the content `<Outlet />`, not this side-effect. Adding `&& !versionMismatch` to the `enabled` option would prevent the hotkey from being active while the placeholder is shown.

### Issue 2 of 2
apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx:55-58
When the version mismatch is active on a v1 route (v2 mode), `currentWorkspaceId` is non-null so this query fires and fetches workspace data that is never shown. Gating with `!versionMismatch` avoids the unnecessary network call.

```suggestion
	const { data: currentWorkspace } = electronTrpc.workspaces.get.useQuery(
		{ id: currentWorkspaceId ?? "" },
		{ enabled: !!currentWorkspaceId && !versionMismatch },
	);
```

Reviews (1): Last reviewed commit: "feat(desktop): show pick-workspace promp..." | Re-trigger Greptile

@Kitenite Kitenite merged commit 56a1f50 into main May 7, 2026
9 of 10 checks passed
@Kitenite Kitenite deleted the cross-version-content-sel branch May 7, 2026 22:00
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 7, 2026

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch

Thank you for your contribution! 🎉

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