Skip to content

Conversation

@jumarmartin
Copy link

@jumarmartin jumarmartin commented Oct 3, 2025

The Problem (video)

Although my intended video is certainly less than five minutes, I am prevented from exporting to my personal Cap instance and given the "Upgrade to Pro" interstitial.

The Solution

Checking exportEstimates's duration_seconds where available and falling back to metadata.duration where not.

Why? (video)

It seems like when calculating the duration of clips from a Studio export we're given an incorrect total value. As this is a largely frontend barrier, and exportEstimates gives us the correct duration, we can leverage it here to make the duration check with confidence. This may be an issue unrelated to Cap in particular, instead being an issue between the mp4 reader and macOS Tahoe Beta builds or somewhere along the call-chain.

Summary by CodeRabbit

  • Bug Fixes
    • Export dialog now bases sharing eligibility on the estimated export duration, not just the project duration. This ensures upgrade prompts and share options are accurate, especially for projects near the 5-minute limit, reducing false upgrade requirements or incorrect sharing availability.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 3, 2025

Walkthrough

Updated ExportDialog canShare logic to prefer exportEstimates.data?.duration_seconds over metadata.duration when determining share allowance and upgrade requirement; plan checks remain.

Changes

Cohort / File(s) Summary
Export duration gating logic
apps/desktop/src/routes/editor/ExportDialog.tsx
canShare.allowed and canShare.reason now conditionally use exportEstimates.data?.duration_seconds (if present) instead of metadata.duration to evaluate the 5‑minute limit and upgrade_required state.

Sequence Diagram(s)

sequenceDiagram
  actor User
  participant ExportDialog
  participant ExportEstimates as exportEstimates
  participant Plan as PlanStatus

  User->>ExportDialog: Open Share/Export
  ExportDialog->>ExportEstimates: Read data?.duration_seconds (optional)
  ExportDialog->>Plan: Check plan status
  alt Has plan
    ExportDialog-->>User: canShare.allowed = true
  else No plan
    alt exportEstimates duration available
      ExportDialog-->>User: Evaluate limit using duration_seconds
    else Fallback to metadata
      ExportDialog-->>User: Evaluate limit using metadata.duration
    end
  end
  note over ExportDialog: Set canShare.reason = "upgrade_required" when limit exceeded
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

Suggested reviewers

  • Brendonovich

Poem

I thump my paw—time’s in the air,
Five-minute fences, handle with care.
If estimates speak, I lend an ear,
Share gates align, the path is clear.
No plan? I twitch—upgrade’s the cue,
Hop, hop, hooray—logic, renewed! 🐇✨

Pre-merge checks and finishing touches

❌ 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%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title clearly and concisely describes the core fix—correcting a duration check that was wrongly blocking compliant video uploads—which directly matches the changes made in the pull request.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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
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: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5c83606 and e4e8b49.

📒 Files selected for processing (1)
  • apps/desktop/src/routes/editor/ExportDialog.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
apps/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/desktop/**/*.{ts,tsx}: Do not manually import icons in the desktop app; rely on auto-imported icons
In the desktop app, use @tanstack/solid-query for server state management

Files:

  • apps/desktop/src/routes/editor/ExportDialog.tsx
**/*.{ts,tsx,js,jsx,rs}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not add inline, block, or docstring comments in any language; code must be self-explanatory

Files:

  • apps/desktop/src/routes/editor/ExportDialog.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use strict TypeScript and avoid any; leverage shared types from packages

**/*.{ts,tsx}: Use a 2-space indent for TypeScript code.
Use Biome for formatting and linting TypeScript/JavaScript files by running pnpm format.

Files:

  • apps/desktop/src/routes/editor/ExportDialog.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Use kebab-case for filenames for TypeScript/JavaScript modules (e.g., user-menu.tsx).
Use PascalCase for React/Solid components.

Files:

  • apps/desktop/src/routes/editor/ExportDialog.tsx

Comment on lines +317 to +318
allowed: plan || (exportEstimates.data?.duration_seconds ?? metadata.duration < 300),
reason: !plan && (exportEstimates.data?.duration_seconds ?? metadata.duration >= 300) ? "upgrade_required" : null,
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Operator precedence breaks duration check.

The ?? operator has lower precedence than comparison operators, so line 317 is parsed as:

plan || ((exportEstimates.data?.duration_seconds) ?? (metadata.duration < 300))

When exportEstimates.data?.duration_seconds is nullish, the fallback is the boolean metadata.duration < 300, not the numeric metadata.duration. This breaks the duration check entirely. Line 318 has the same issue.

Apply this diff to fix the precedence:

       const canShare = {
-        allowed: plan || (exportEstimates.data?.duration_seconds ?? metadata.duration < 300),
-        reason: !plan && (exportEstimates.data?.duration_seconds ?? metadata.duration >= 300) ? "upgrade_required" : null,
+        allowed: plan || (exportEstimates.data?.duration_seconds ?? metadata.duration) < 300,
+        reason: !plan && (exportEstimates.data?.duration_seconds ?? metadata.duration) >= 300 ? "upgrade_required" : null,
       };
🤖 Prompt for AI Agents
In apps/desktop/src/routes/editor/ExportDialog.tsx around lines 317 to 318, the
nullish coalescing is evaluated before the comparison due to operator
precedence, causing the fallback to be a boolean; wrap the coalescing expression
in parentheses so you first choose the numeric duration and then compare it to
300 (e.g. use (exportEstimates.data?.duration_seconds ?? metadata.duration) <
300 for the allowed check and the analogous >= 300 expression for the reason
check).

@jumarmartin jumarmartin closed this Oct 3, 2025
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