Skip to content

feat(desktop): add local v1/v2 version toggle in top bar#3347

Merged
Kitenite merged 2 commits intomainfrom
local-version-toggle
Apr 11, 2026
Merged

feat(desktop): add local v1/v2 version toggle in top bar#3347
Kitenite merged 2 commits intomainfrom
local-version-toggle

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented Apr 11, 2026

Summary

  • Adds a segmented v1/v2 toggle pill in the top bar (next to resource consumption) that appears when the v2 feature flag is enabled remotely
  • Lets you switch between v1 and v2 locally without changing the PostHog flag — preference persists in localStorage
  • Centralizes all V2_CLOUD flag checks into a single useIsV2CloudEnabled hook

Test plan

  • Enable v2-cloud flag in PostHog → toggle appears in top bar
  • Click toggle to v1 → sidebar, modals, and settings switch to v1 mode
  • Click toggle back to v2 → everything returns to v2 mode
  • Restart app → toggle state persists
  • Disable v2-cloud flag in PostHog → toggle is hidden, app is v1

Summary by cubic

Adds a local v1/v2 toggle in the desktop top bar that appears only when the remote V2 flag is on. Users can switch versions locally and the choice persists across restarts.

  • New Features

    • Segmented v1/v2 pill in the top bar; click to switch versions without changing PostHog.
    • Local override store useV2LocalOverrideStore using zustand persist to save preference in localStorage.
    • New hook useIsV2CloudEnabled exposing isV2CloudEnabled and isRemoteV2Enabled.
  • Refactors

    • Centralized V2_CLOUD checks into useIsV2CloudEnabled and updated TopBar, dashboard layout, authenticated layout, and terminal settings to use it.

Written for commit 7ef3d28. Summary will update on new commits.

Summary by CodeRabbit

  • New Features
    • Added a version toggle button allowing users to switch between V1 and V2 interfaces.
    • Local preference for version selection is now persisted across sessions.

When the v2 feature flag is enabled remotely, a segmented toggle appears
in the top bar (next to resource consumption) that lets you switch
between v1 and v2 locally without changing the PostHog flag. The
preference persists in localStorage across app restarts.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 11, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

The changes introduce a centralized feature flag management pattern by creating a useIsV2CloudEnabled hook that combines remote PostHog feature flag state with local override persistence, add a UI VersionToggle component for switching between versions, and refactor multiple layout and settings components to use the unified approach instead of directly accessing PostHog.

Changes

Cohort / File(s) Summary
Core Feature Flag & Store
apps/desktop/src/renderer/hooks/useIsV2CloudEnabled.ts, apps/desktop/src/renderer/stores/v2-local-override.ts
New hook that reads remote V2 Cloud flag and local override state, returning both isV2CloudEnabled and isRemoteV2Enabled. New Zustand store with forceV1 persistent flag and toggle() action for local version override.
TopBar & Version Toggle
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/TopBar/TopBar.tsx, apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/TopBar/components/VersionToggle/VersionToggle.tsx, apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/TopBar/components/VersionToggle/index.ts
TopBar refactored to use new useIsV2CloudEnabled hook; new VersionToggle component added that reads local override store and renders pill-style toggle button with conditional tooltip, switching between V1 and V2 versions.
Layout Components
apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx, apps/desktop/src/renderer/routes/_authenticated/layout.tsx, apps/desktop/src/renderer/routes/_authenticated/settings/terminal/components/TerminalSettings/TerminalSettings.tsx
Multiple layout and settings components refactored to use useIsV2CloudEnabled hook instead of direct PostHog feature flag access, removing FEATURE_FLAGS and useFeatureFlagEnabled imports.

Sequence Diagram

sequenceDiagram
    actor User
    participant VersionToggle
    participant V2LocalOverrideStore
    participant useIsV2CloudEnabled
    participant PostHog
    participant TopBar/UI

    User->>VersionToggle: Click toggle button
    VersionToggle->>V2LocalOverrideStore: Call toggle()
    V2LocalOverrideStore->>V2LocalOverrideStore: Flip forceV1 state<br/>(persist to localStorage)
    
    V2LocalOverrideStore-->>useIsV2CloudEnabled: State change detected
    useIsV2CloudEnabled->>PostHog: Read FEATURE_FLAGS.V2_CLOUD
    PostHog-->>useIsV2CloudEnabled: Return remote flag state
    useIsV2CloudEnabled->>V2LocalOverrideStore: Read forceV1 value
    V2LocalOverrideStore-->>useIsV2CloudEnabled: Return forceV1
    useIsV2CloudEnabled->>useIsV2CloudEnabled: Compute isV2CloudEnabled<br/>(remote && !forceV1)
    
    useIsV2CloudEnabled-->>TopBar/UI: Return { isV2CloudEnabled, isRemoteV2Enabled }
    TopBar/UI->>TopBar/UI: Re-render with updated state
    TopBar/UI-->>User: Display active version (V1 or V2)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰✨ A toggle blooms where flags once ruled,
Local state and remote unified,
V1, V2—choose with a tap,
The rabbit's refactor makes features snappy! 🚀

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description includes a clear summary and test plan, but is missing several required template sections: Related Issues, Type of Change, Testing, Screenshots, and Additional Notes. Complete the PR description template by adding: Related Issues section (if applicable), explicit Type of Change checkbox selection, formal Testing section detailing test execution, and Additional Notes for any relevant context.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding a local v1/v2 version toggle in the desktop top bar. It is concise, clear, and specific.

✏️ 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 local-version-toggle

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 Apr 11, 2026

Greptile Summary

This PR adds a local v1/v2 version toggle pill in the desktop app's top bar, visible when the PostHog V2_CLOUD feature flag is enabled remotely. It introduces a Zustand store (v2-local-override.ts) backed by localStorage to persist the user's override preference, a centralized useIsV2CloudEnabled hook that composes the remote flag with the local override, and a VersionToggle segmented button component. All four prior call sites that directly called useFeatureFlagEnabled(FEATURE_FLAGS.V2_CLOUD) are migrated to use the new hook.

Key changes:

  • New v2-local-override Zustand store (devtools + persist) with a single forceV1 boolean and a toggle action
  • New useIsV2CloudEnabled hook returns both the effective isV2CloudEnabled value and the raw isRemoteV2Enabled flag (used to conditionally render the toggle)
  • New VersionToggle component — a styled segmented pill with tooltip, rendered in the top bar left cluster
  • All four consumer components (TopBar, _dashboard/layout, _authenticated/layout, TerminalSettings) updated to use the centralized hook

Confidence Score: 4/5

Safe to merge — core logic is correct and migration is complete; one non-critical UX quirk remains in the toggle interaction model.

All V2_CLOUD flag usages are correctly centralized, the Zustand store uses the right middleware ordering and persist key, and the conditional rendering logic is sound. The only functional concern is that the segmented control acts as a blind toggle rather than an explicit selector, which could confuse users who click the already-active segment. This doesn't break any functionality but is worth addressing before widespread use.

apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/TopBar/components/VersionToggle/VersionToggle.tsx — UX interaction model and accessibility

Important Files Changed

Filename Overview
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/TopBar/components/VersionToggle/VersionToggle.tsx New segmented pill toggle component; missing aria-label on the button, inconsistent tooltip indentation, and clicking either segment always toggles rather than selecting explicitly
apps/desktop/src/renderer/hooks/useIsV2CloudEnabled.ts Centralizes V2_CLOUD flag logic; correctly guards undefined with ?? false and exposes both effective and raw values
apps/desktop/src/renderer/stores/v2-local-override.ts New Zustand store with devtools + persist middleware; correct middleware ordering and toggle implementation using get()
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/TopBar/TopBar.tsx Correctly migrated to useIsV2CloudEnabled; renders VersionToggle conditionally on isRemoteV2Enabled
apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx Straightforward migration of flag check to useIsV2CloudEnabled hook, no issues
apps/desktop/src/renderer/routes/_authenticated/layout.tsx Straightforward migration of flag check to useIsV2CloudEnabled hook, no issues
apps/desktop/src/renderer/routes/_authenticated/settings/terminal/components/TerminalSettings/TerminalSettings.tsx Straightforward migration of flag check to useIsV2CloudEnabled hook, no issues
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/TopBar/components/VersionToggle/index.ts Simple barrel export, no issues

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    PH[PostHog: V2_CLOUD flag] --> hook[useIsV2CloudEnabled]
    LS[localStorage: v2-local-override
forceV1: boolean] --> store[useV2LocalOverrideStore]
    store --> hook

    hook -->|isRemoteV2Enabled| TopBar
    hook -->|isV2CloudEnabled| TopBar
    hook -->|isV2CloudEnabled| DashboardLayout
    hook -->|isV2CloudEnabled| AuthenticatedLayout
    hook -->|isV2CloudEnabled| TerminalSettings

    TopBar -->|isRemoteV2Enabled === true| VersionToggle
    VersionToggle -->|toggle| store

    subgraph Effective State
        A{remoteV2Enabled?}
        A -- No --> V1[App runs V1]
        A -- Yes --> B{forceV1?}
        B -- Yes --> V1
        B -- No --> V2[App runs V2]
    end

    hook --> A
Loading

Reviews (1): Last reviewed commit: "lint" | Re-trigger Greptile

Comment on lines +11 to +15
<TooltipTrigger asChild>
<button
type="button"
onClick={toggle}
className="no-drag flex items-center h-6 rounded-full bg-muted border border-border text-[11px] font-medium overflow-hidden transition-colors"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Segmented control acts as a blind toggle, not a selector

The entire <button> has a single onClick={toggle}. This means clicking the already-active segment also flips to the other version, which is unexpected UX for a segmented control — users expect clicking the active segment to be a no-op.

Consider splitting into two independent <button> elements that each set an explicit target state instead of toggling:

<button
  type="button"
  onClick={() => useV2LocalOverrideStore.getState().setForceV1(true)}
  className={cn("px-2 py-0.5 rounded-full transition-colors", forceV1 ? "bg-foreground text-background" : "text-muted-foreground hover:text-foreground")}
>
  v1
</button>
<button
  type="button"
  onClick={() => useV2LocalOverrideStore.getState().setForceV1(false)}
  className={cn("px-2 py-0.5 rounded-full transition-colors", !forceV1 ? "bg-foreground text-background" : "text-muted-foreground hover:text-foreground")}
>
  v2
</button>

This would require adding a setForceV1(value: boolean) action alongside toggle in the store.

@Kitenite Kitenite merged commit a44108a into main Apr 11, 2026
6 of 7 checks passed
@Kitenite Kitenite deleted the local-version-toggle branch April 11, 2026 00:22
@github-actions
Copy link
Copy Markdown
Contributor

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ⚠️ Neon database branch
  • ⚠️ Electric Fly.io app

Thank you for your contribution! 🎉

MocA-Love pushed a commit to MocA-Love/superset that referenced this pull request Apr 11, 2026
…#3347)

* feat(desktop): add local v1/v2 version toggle in top bar

When the v2 feature flag is enabled remotely, a segmented toggle appears
in the top bar (next to resource consumption) that lets you switch
between v1 and v2 locally without changing the PostHog flag. The
preference persists in localStorage across app restarts.

* lint
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