Skip to content

Make dashboard video links reliable public shares#48

Open
bmdavis419 wants to merge 2 commits into
mainfrom
codex/robust-video-sharing
Open

Make dashboard video links reliable public shares#48
bmdavis419 wants to merge 2 commits into
mainfrom
codex/robust-video-sharing

Conversation

@bmdavis419

@bmdavis419 bmdavis419 commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Summary

  • make signed-out and non-member dashboard video URLs reliably redirect to the public watch route without racing Clerk and Convex authentication
  • keep public links stable through uploading, processing, ready, and failed lifecycle states while preserving private-video access boundaries
  • unify robust clipboard behavior across Quick Share and the Share dialog, including race guards, visible errors, and manual-copy recovery
  • make sharing controls role-aware and isolate delayed mutations when dialogs close or switch videos

User impact

Videos remain public by default. Copying a public dashboard video URL now works as a share link: team members stay in the dashboard, while everyone else is sent to the watch page. Private videos are never auto-published or exposed.

Validation

  • bun run check
    • Prettier
    • TypeScript
    • Convex typecheck
    • ESLint
    • 35 Bun unit tests
    • 35 Vitest/Convex tests
  • independent correctness review: no remaining P0-P3 findings
  • independent design/UX review: no remaining P0-P3 findings
  • git diff --check

No dev server or build command was run, per repository instructions.

Note

Make dashboard video links redirect unauthenticated users to public watch pages

  • Adds resolveDashboardAccess to determine routing outcome (loading, dashboard, public redirect, sign-in redirect, not-found, auth-unavailable) from auth and workspace context state, replacing ad-hoc redirect logic in DashboardLayout.
  • The Share action in ProjectPage and ShareDialog now copies a public watch URL (via watchPath) when the video is public, with success/error feedback and a manual-copy fallback input on clipboard failure.
  • workspace.resolveContext now accepts raw string IDs and normalizes them, returning null for malformed input instead of throwing.
  • videos.getPublicIdByVideoId now returns a publicId for public videos in any status (uploading, processing, ready, failed), not only ready.
  • Adds a copyTextToClipboard utility with navigator.clipboard and execCommand fallback, and a createRequestEpoch helper to guard against stale async results.
  • Behavioral Change: unauthenticated users visiting a dashboard video link with a public video are now redirected to the public watch page instead of the sign-in page.

Macroscope summarized 16039fd.

Summary by CodeRabbit

  • New Features

    • Added a robust “copy to clipboard” helper with native support and fallback behavior.
    • Enhanced the share dialog with better success/error feedback, an optional dismissable toast, and a read-only copied-link input.
  • Bug Fixes

    • Prevented stale share/copy results from updating the UI after navigation, dialog close, or rapid repeat actions.
    • Improved dashboard access routing for public vs signed-in users, including dedicated loading/redirect states.
    • Updated public video aliasing to apply to public videos across statuses.
    • Disabled share actions while requests are pending to avoid duplicates.

@vercel

vercel Bot commented Jun 21, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lawn Ready Ready Preview, Comment Jun 21, 2026 11:04am

Request Review

@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Introduces createRequestEpoch and copyTextToClipboard utilities, then uses them to add epoch-guarded async handling across ShareDialog and the project share toast. Adds a resolveDashboardAccess resolver with a DashboardAccessState discriminated union and refactors DashboardLayout to render access-state-specific screens. Backend changes make workspace.resolveContext accept raw string IDs (normalizing internally) and expand getPublicIdByVideoId to return public IDs for all video statuses, not just ready.

Changes

Dashboard Access Control & Share UX

Layer / File(s) Summary
Shared async utilities: requestEpoch and clipboard
src/lib/requestEpoch.ts, src/lib/requestEpoch.test.ts, src/lib/clipboard.ts, src/lib/clipboard.test.ts
createRequestEpoch() exposes next/invalidate/isCurrent to detect stale completions. copyTextToClipboard() tries the native Clipboard API and falls back to a hidden textarea + execCommand. Both are fully unit-tested including fallback and failure paths.
Backend: string-ID normalization and public-status expansion
convex/workspace.ts, convex/videos.ts, convex/publicWatch.vitest.ts
resolveContext argument schema changes from typed Convex IDs to optional strings, normalizing via ctx.db.normalizeId and returning null on invalid input. getPublicIdByVideoId drops the status === "ready" restriction. New tests cover all upload-lifecycle statuses and negative cases.
DashboardAccessState resolver
src/lib/dashboardAccess.ts, src/lib/dashboardAccess.test.ts
Defines the DashboardAccessState discriminated union and implements resolveDashboardAccess with ordered branches across Clerk/Convex auth and workspace context signals, producing loading, dashboard, redirect-public, redirect-sign-in, not-found, or auth-unavailable. Unit tests cover all branches.
DashboardLayout access-state wiring
app/routes/dashboard/-layout.tsx
Adds useConvexAuth, derives raw route IDs, conditionally issues queries, and computes access via resolveDashboardAccess. Replaces isLoaded/userId redirect logic with useEffect-driven window.location.replace and dedicated early-return screens per access.kind.
ShareDialog epoch-guarded state and ARIA
src/components/ShareDialog.tsx
Replaces straightforward state with epoch-guarded handlers for all async mutations (visibility, version browsing, copy, create/delete link). Adds accessible mutation-error and copy-status panels, a manual-copy input on clipboard failure, and canManageSharing-gated link creation and delete controls.
Project share flow: epoch gating and toast UX
app/routes/dashboard/-project.tsx
Extends ShareToastState with an optional url field, adds shareRequestEpochRef/sharePending state, and rewrites handleShareVideo with epoch gating and copyTextToClipboard. Share dropdown items disable while pending. Toast gains role/aria-live and a read-only link input with dismiss button.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant DashboardLayout
  participant resolveDashboardAccess
  participant ConvexWorkspace
  participant ClerkAuth

  User->>DashboardLayout: navigate to dashboard route
  DashboardLayout->>ClerkAuth: useAuth() / useConvexAuth()
  ClerkAuth-->>DashboardLayout: {isLoaded, userId, isAuthenticated}
  DashboardLayout->>ConvexWorkspace: resolveContext(rawProjectId, rawVideoId) [conditional]
  ConvexWorkspace-->>DashboardLayout: workspaceContext | null
  DashboardLayout->>resolveDashboardAccess: resolve(clerkState, convexAuthState, workspaceContext, publicId)
  resolveDashboardAccess-->>DashboardLayout: access.kind (loading | dashboard | redirect-public | redirect-sign-in | not-found | auth-unavailable)
  alt access.kind === "dashboard"
    DashboardLayout-->>User: render dashboard content
  else access.kind === "redirect-public"
    DashboardLayout-->>User: window.location.replace(watchPath)
  else access.kind === "redirect-sign-in"
    DashboardLayout-->>User: window.location.replace(/sign-in?redirect_url=...)
  else access.kind === "loading"
    DashboardLayout-->>User: "Checking access..." screen
  else access.kind === "not-found" | "auth-unavailable"
    DashboardLayout-->>User: error screen with recovery actions
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 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 'Make dashboard video links reliable public shares' accurately captures the primary objective of the PR: improving reliability of public video sharing from the dashboard.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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 codex/robust-video-sharing

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/components/ShareDialog.tsx (1)

271-272: ⚡ Quick win

Align new feedback surfaces with the required palette.

Line 271 uses bg-[#e8e8e0] and Line 297 uses bg-white; both conflict with the defined cream background system for this UI.

Suggested fix
-          <p className="border-2 border-[`#1a1a1a`] bg-[`#e8e8e0`] px-3 py-2 text-sm text-[`#1a1a1a`]">
+          <p className="border-2 border-[`#1a1a1a`] bg-[`#f0f0e8`] px-3 py-2 text-sm text-[`#1a1a1a`]">
...
-                className="mt-2 bg-white font-mono text-xs font-normal"
+                className="mt-2 bg-[`#f0f0e8`] font-mono text-xs font-normal"

As per coding guidelines, "Use warm cream (#f0f0e8) for backgrounds".

Also applies to: 297-297

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/ShareDialog.tsx` around lines 271 - 272, Update the background
color styling in the ShareDialog component to match the defined warm cream
palette. Replace the background color in the paragraph element at line 271
(currently using `bg-[`#e8e8e0`]`) and at line 297 (currently using `bg-white`)
with the correct warm cream color `bg-[`#f0f0e8`]` as specified in the coding
guidelines for UI backgrounds.

Source: Coding guidelines

app/routes/dashboard/-project.tsx (1)

908-911: ⚡ Quick win

Update share toast styling to match UI rules.

Line 908 introduces a strong shadow, and Line 919 uses bg-white; both diverge from the declared primary UI styling rules for this codebase.

Suggested fix
-              "border-2 px-3 py-2 text-sm font-bold shadow-[4px_4px_0px_0px_var(--shadow-color)]",
+              "border-2 px-3 py-2 text-sm font-bold",
...
-                  className="bg-white font-mono text-xs font-normal"
+                  className="bg-[`#f0f0e8`] font-mono text-xs font-normal"

As per coding guidelines, "Do not use gradients or shadows in primary UI elements (except subtle where functional)" and "Use warm cream (#f0f0e8) for backgrounds".

Also applies to: 919-919

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/routes/dashboard/-project.tsx` around lines 908 - 911, The shareToast
styling violates UI guidelines by using a strong shadow effect and bg-white
background. Remove the shadow-[4px_4px_0px_0px_var(--shadow-color)] class from
the toast className to comply with the "no strong shadows in primary UI
elements" rule, and replace any bg-white background class with bg-[`#f0f0e8`] to
use the designated warm cream color throughout the share toast component,
including the styling at line 919.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/ShareDialog.tsx`:
- Around line 67-69: The canManageSharing variable does not properly handle null
values for the video object. Currently, the condition checks video !== undefined
which returns true when video is null (since null !== undefined), potentially
allowing share management controls to be enabled when video is in an invalid
null state. Fix this by changing the condition to properly check that video is
not null, such as using video != null or video !== null instead of video !==
undefined, ensuring manage sharing actions are only enabled when a valid video
object exists and the user is not a viewer.

---

Nitpick comments:
In `@app/routes/dashboard/-project.tsx`:
- Around line 908-911: The shareToast styling violates UI guidelines by using a
strong shadow effect and bg-white background. Remove the
shadow-[4px_4px_0px_0px_var(--shadow-color)] class from the toast className to
comply with the "no strong shadows in primary UI elements" rule, and replace any
bg-white background class with bg-[`#f0f0e8`] to use the designated warm cream
color throughout the share toast component, including the styling at line 919.

In `@src/components/ShareDialog.tsx`:
- Around line 271-272: Update the background color styling in the ShareDialog
component to match the defined warm cream palette. Replace the background color
in the paragraph element at line 271 (currently using `bg-[`#e8e8e0`]`) and at
line 297 (currently using `bg-white`) with the correct warm cream color
`bg-[`#f0f0e8`]` as specified in the coding guidelines for UI backgrounds.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 297f2604-dba6-457d-926d-7033d322ad21

📥 Commits

Reviewing files that changed from the base of the PR and between 67a39a5 and c6ddc8c.

📒 Files selected for processing (12)
  • app/routes/dashboard/-layout.tsx
  • app/routes/dashboard/-project.tsx
  • convex/publicWatch.vitest.ts
  • convex/videos.ts
  • convex/workspace.ts
  • src/components/ShareDialog.tsx
  • src/lib/clipboard.test.ts
  • src/lib/clipboard.ts
  • src/lib/dashboardAccess.test.ts
  • src/lib/dashboardAccess.ts
  • src/lib/requestEpoch.test.ts
  • src/lib/requestEpoch.ts

Comment thread src/components/ShareDialog.tsx
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