Skip to content

added a pro gating modal#1414

Merged
duckduckhero merged 1 commit intomainfrom
pro-new-modal
Aug 27, 2025
Merged

added a pro gating modal#1414
duckduckhero merged 1 commit intomainfrom
pro-new-modal

Conversation

@duckduckhero
Copy link
Contributor

@duckduckhero duckduckhero commented Aug 27, 2025

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.

  • New Features
    • Added ProGateModal with monthly/annual toggle, benefits, and “Get Pro Plan”.
    • Introduced showProGateModal helper for easy, self-cleaning usage.
    • Integrated gating in chat (4 messages per conversation) and templates (2 custom templates).
    • “Get Pro Plan” opens Settings and deep-links to the Billing tab; removed duplicate “what you get” block from Billing; updated i18n references.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 27, 2025

📝 Walkthrough

Walkthrough

Adds 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

Cohort / File(s) Summary
Pro Gate Modal Components
apps/desktop/src/components/pro-gate-modal/index.tsx, .../pro-gate-modal/service.ts, .../pro-gate-modal/types.ts
New ProGateModal UI with pricing toggle, content by type ("template" or "chat"), and upgrade action that closes modal and routes to Settings Billing. Service showProGateModal(type) mounts/unmounts modal imperatively. Types exported for props and type alias.
License Gate Integration (Chat + Templates)
apps/desktop/src/components/right-panel/hooks/useChatLogic.ts, apps/desktop/src/components/settings/views/templates.tsx
Replaces TAURI dialog with `showProGateModal("chat"
Billing View Update
apps/desktop/src/components/settings/views/billing.tsx
Removes “What you get with Pro” feature card block; rest of checkout UI unchanged.
Locales Reference Updates
apps/desktop/src/locales/en/messages.po, apps/desktop/src/locales/ko/messages.po
Updates source line references only; no string content 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
Loading
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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Overall optimization #1250 — Also modifies useChatLogic gating threshold; related to this PR’s gating UI change in the same hook.
  • Project loop #1376 — Adds the “What you get with Pro” panel in Billing; this PR removes that panel.
  • Minor fixes 0808 #1305 — Adjusts free-message threshold and text in useChatLogic; overlaps with this PR’s substitution of the modal in the same path.

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 Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch pro-new-modal

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

‼️ IMPORTANT
Auto-reply has been disabled for this repository in the CodeRabbit settings. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 8 files

React with 👍 or 👎 to teach cubic. You can also tag @cubic-dev-ai to give feedback, ask questions, or re-run the review.

Copy link
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: 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 readiness

I didn’t find any existing “did-show”, windowIsVisible, or “ready”–style events in @hypr/plugin-windows across 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-windows actually emits a readiness event via its windowsEvents API (for example, windowsEvents.didShow or similar). If such an event exists, subscribe to it instead of using setTimeout.

If the plugin does not expose a built-in readiness signal, consider one of these optional refactors:

• Polling fallback
– Repeatedly call windowsCommands.windowExists({ type: "settings" }) or a hypothetical windowsCommands.windowIsVisible in a short retry loop with backoff, resolving once the window is ready.
• Encapsulated helper
– Abstract showAndNavigate(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.

📥 Commits

Reviewing files that changed from the base of the PR and between 123eb03 and 837bb3b.

📒 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.ts
  • apps/desktop/src/components/pro-gate-modal/types.ts
  • apps/desktop/src/components/pro-gate-modal/service.ts
  • apps/desktop/src/components/settings/views/templates.tsx
  • apps/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.

@duckduckhero duckduckhero merged commit f01ee8e into main Aug 27, 2025
21 of 22 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Aug 29, 2025
@ComputelessComputer ComputelessComputer deleted the pro-new-modal branch December 14, 2025 15:20
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