Conversation
📝 WalkthroughWalkthroughAdds a Pro gating modal component and service, integrates it into chat and templates license checks, and removes a redundant “What you get with Pro” panel in Billing. Updates translation source references. The modal can open Settings for upgrade and toggles pricing interval internally. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant Feature as Feature (Chat/Templates)
participant Service as showProGateModal
participant DOM as document.body
participant Modal as ProGateModal
participant Router as Settings Router
User->>Feature: Trigger gated action
Feature->>Feature: Check license/threshold
alt Not eligible (gate)
Feature->>Service: showProGateModal(type)
Service->>DOM: Create container div
Service->>Modal: Render ProGateModal(isOpen=true, onClose)
User->>Modal: Click "Get Pro Plan"
Modal->>Router: Close modal, open Settings Billing
Modal->>Service: onClose()
Service->>DOM: Unmount and remove container
Service-->>Feature: Promise resolved
Feature-->>User: Return (gated)
else Eligible
Feature-->>User: Proceed normally
end
sequenceDiagram
autonumber
actor User
participant Modal as ProGateModal
participant Timer as Interval
participant Router as Settings Router
Note over Modal: Pricing interval toggle
Modal->>Timer: start interval (toggle monthly/yearly)
User->>Modal: Close or Upgrade
alt Close
Modal->>Timer: clear interval
Modal-->>User: Modal closed
else Upgrade
Modal->>Timer: clear interval
Modal->>Router: Navigate to /app/settings (Billing tab)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
Status, Documentation and Community
|
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (6)
apps/desktop/src/components/pro-gate-modal/types.ts (1)
1-5: Use the alias in props to avoid duplicating the union.Reference the exported ProGateType in ProGateModalProps to keep a single source of truth.
export interface ProGateModalProps { isOpen: boolean; onClose: () => void; - type: "template" | "chat"; + type: ProGateType; }apps/desktop/src/components/pro-gate-modal/service.ts (1)
6-27: Prevent multiple concurrent modals (single-instance guard).A quick guard avoids stacked modals if called twice before close.
+let proGateHost: HTMLElement | null = null; export function showProGateModal(type: ProGateType): Promise<void> { return new Promise((resolve) => { - const modalDiv = document.createElement("div"); - document.body.appendChild(modalDiv); + if (proGateHost) return resolve(); + const modalDiv = document.createElement("div"); + modalDiv.id = "pro-gate-modal-root"; + proGateHost = modalDiv; + document.body.appendChild(modalDiv); const root = createRoot(modalDiv); const handleClose = () => { root.unmount(); - document.body.removeChild(modalDiv); + document.body.removeChild(modalDiv); + proGateHost = null; resolve(); };apps/desktop/src/components/right-panel/hooks/useChatLogic.ts (1)
127-135: Refocus the chat input after closing the modal.Small UX touch so users can resume typing immediately.
- await showProGateModal("chat"); - return; + await showProGateModal("chat"); + chatInputRef.current?.focus(); + return;apps/desktop/src/components/pro-gate-modal/index.tsx (3)
29-33: Avoid magic pricing numbers; derive savings and effective monthly from constants.This prevents copy drift when prices change in one place.
Apply this diff:
- const pricing = { - monthly: { price: "$8", period: "/mo", billing: "(billed monthly)" }, - yearly: { price: "$59", period: "/yr", billing: "(billed annually, save $37)" }, - }; + const monthlyUSD = 8; + const yearlyUSD = 59; + const savingsDollars = monthlyUSD * 12 - yearlyUSD; + const savingsPercent = Math.round((savingsDollars / (monthlyUSD * 12)) * 100); + const pricing = { + monthly: { price: `$${monthlyUSD}`, period: "/mo", billing: "(billed monthly)" }, + yearly: { price: `$${yearlyUSD}`, period: "/yr", billing: `(billed annually, save $${savingsDollars})` }, + }; @@ - {interval === "yearly" && <div className="text-xs text-green-600 font-medium">Save 39%</div>} + {interval === "yearly" && ( + <div className="text-xs text-green-600 font-medium">Save {savingsPercent}%</div> + )} @@ - <div className="text-right"> - <div className="text-green-600 font-medium text-sm">$4.92/month</div> - </div> + <div className="text-right"> + <div className="text-green-600 font-medium text-sm"> + ${ (yearlyUSD / 12).toFixed(2) }/month + </div> + </div>Also applies to: 117-123
127-154: Minor copy/i18n follow-ups.Consider localizing feature bullets and the CTA label for full coverage.
If you want, I can provide a follow-up diff wrapping these with and adding IDs for PO extraction.
Also applies to: 156-161
34-47: Avoid magic 500 ms delay; wait for explicit window readinessI didn’t find any existing “did-show”,
windowIsVisible, or “ready”–style events in@hypr/plugin-windowsacross the repo, so our current fixed timeout is the only mechanism in use. Relying on a hardcoded 500 ms risks flakiness on slower machines.Please verify whether
@hypr/plugin-windowsactually emits a readiness event via itswindowsEventsAPI (for example,windowsEvents.didShowor similar). If such an event exists, subscribe to it instead of usingsetTimeout.If the plugin does not expose a built-in readiness signal, consider one of these optional refactors:
• Polling fallback
– Repeatedly callwindowsCommands.windowExists({ type: "settings" })or a hypotheticalwindowsCommands.windowIsVisiblein a short retry loop with backoff, resolving once the window is ready.
• Encapsulated helper
– AbstractshowAndNavigate(type, to, search)that handles showing the window, awaiting readiness (via event or polling), then emitting navigation. This will DRY up similar patterns across:
•pro-gate-modal/index.tsx(handleUpgrade, lines 34–47)
•toast/model-select.tsx(lines 19–24)
•settings/components/ai/llm-local-view.tsx(lines 141–146)
•left-sidebar/top-area/settings-button.tsx(lines 55–62)
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (8)
apps/desktop/src/components/pro-gate-modal/index.tsx(1 hunks)apps/desktop/src/components/pro-gate-modal/service.ts(1 hunks)apps/desktop/src/components/pro-gate-modal/types.ts(1 hunks)apps/desktop/src/components/right-panel/hooks/useChatLogic.ts(2 hunks)apps/desktop/src/components/settings/views/billing.tsx(0 hunks)apps/desktop/src/components/settings/views/templates.tsx(2 hunks)apps/desktop/src/locales/en/messages.po(8 hunks)apps/desktop/src/locales/ko/messages.po(8 hunks)
💤 Files with no reviewable changes (1)
- apps/desktop/src/components/settings/views/billing.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,ts,tsx,rs}
⚙️ CodeRabbit configuration file
**/*.{js,ts,tsx,rs}: 1. No error handling.
2. No unused imports, variables, or functions.
3. For comments, keep it minimal. It should be about "Why", not "What".
Files:
apps/desktop/src/components/right-panel/hooks/useChatLogic.tsapps/desktop/src/components/pro-gate-modal/types.tsapps/desktop/src/components/pro-gate-modal/service.tsapps/desktop/src/components/settings/views/templates.tsxapps/desktop/src/components/pro-gate-modal/index.tsx
🧬 Code graph analysis (5)
apps/desktop/src/components/right-panel/hooks/useChatLogic.ts (1)
apps/desktop/src/components/pro-gate-modal/service.ts (1)
showProGateModal(6-27)
apps/desktop/src/components/pro-gate-modal/types.ts (1)
apps/desktop/src/components/pro-gate-modal/index.tsx (2)
ProGateModalProps(169-169)ProGateType(169-169)
apps/desktop/src/components/pro-gate-modal/service.ts (2)
apps/desktop/src/components/pro-gate-modal/index.tsx (2)
ProGateType(169-169)ProGateModal(11-167)apps/desktop/src/components/pro-gate-modal/types.ts (1)
ProGateType(7-7)
apps/desktop/src/components/settings/views/templates.tsx (1)
apps/desktop/src/components/pro-gate-modal/service.ts (1)
showProGateModal(6-27)
apps/desktop/src/components/pro-gate-modal/index.tsx (4)
apps/desktop/src/components/pro-gate-modal/types.ts (1)
ProGateModalProps(1-5)packages/ui/src/components/ui/modal.tsx (4)
Modal(23-83)ModalBody(99-105)ModalTitle(130-136)ModalDescription(143-148)packages/ui/src/components/ui/button.tsx (1)
Button(37-89)packages/ui/src/lib/utils.ts (1)
cn(4-6)
⏰ 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). (3)
- GitHub Check: cubic · AI code reviewer
- GitHub Check: ci (macos, macos-latest)
- GitHub Check: ci (windows, windows-latest)
🔇 Additional comments (4)
apps/desktop/src/components/right-panel/hooks/useChatLogic.ts (1)
1-1: LGTM: imports the new gating service.Import path and usage align with the new modal service.
apps/desktop/src/locales/en/messages.po (1)
274-275: LGTM: only source references updated.Msgids/msgstrs unchanged; refs now match templates.tsx shifts.
Also applies to: 468-471, 650-653, 968-971, 1004-1007, 1146-1149, 1371-1374, 1734-1737
apps/desktop/src/locales/ko/messages.po (1)
274-276: LGTM: only source references updated.Translations unchanged; refs align with templates.tsx updates.
Also applies to: 468-471, 650-653, 968-971, 1004-1007, 1146-1149, 1371-1374, 1734-1737
apps/desktop/src/components/settings/views/templates.tsx (1)
1-1: Import looks correct and used. LGTM.
Summary by cubic
Adds a reusable Pro gating modal to guide free users to upgrade when they hit chat or template limits. Replaces system dialogs and opens Settings > Billing for a smoother upgrade flow.