Skip to content

Conversation

ameer2468
Copy link
Collaborator

@ameer2468 ameer2468 commented Oct 7, 2025

This PR:

  • Shows org name + image on share page.
  • In the new org dialog, org names have been set to 25 characters max.
Screenshot 2025-10-07 at 17 55 10

Summary by CodeRabbit

  • New Features

    • Display organization icon and name in the share header and related views.
    • Show creation time (relative) alongside edited info in the share header.
    • Enforce a 25-character limit on organization name when creating a new organization.
  • Bug Fixes

    • Prevents updating the share title when it hasn’t changed.
  • Style

    • Reduced navbar item text weight for visual consistency.
    • Refined share header layout and dashboard action alignment for improved responsiveness.

Copy link
Contributor

coderabbitai bot commented Oct 7, 2025

Warning

Rate limit exceeded

@ameer2468 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 25 minutes and 57 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 518f3b9 and 7cadce2.

📒 Files selected for processing (3)
  • apps/web/app/(org)/dashboard/caps/Caps.tsx (2 hunks)
  • apps/web/app/(org)/dashboard/caps/components/Folder.tsx (1 hunks)
  • apps/web/app/s/[videoId]/_components/ShareHeader.tsx (7 hunks)

Walkthrough

Adds optional organizationIconUrl and organizationName to video data and props; updates ShareHeader to render Next/Image or Avatar, adds a blur guard to skip no-op title updates, restructures header layout and status/time/action placement; removes font-medium from a Navbar extraText class; enforces 25-character max for new organization names.

Changes

Cohort / File(s) Summary
Sharing data & UI
apps/web/app/s/[videoId]/page.tsx, apps/web/app/s/[videoId]/_components/ShareHeader.tsx
Adds optional organizationIconUrl and organizationName to video types and props; propagates fields through queries and AuthorizedContent; ShareHeader conditionally renders Next/Image when organizationIconUrl is present or Avatar fallback; adds a blur guard to skip updates when title unchanged; reorganizes header layout and action/status/time placement.
Navbar typography
apps/web/app/(org)/dashboard/_components/Navbar/Items.tsx
Removes font-medium from the extraText paragraph className, changing it to ml-auto text-xs text-gray-11.
Organization form validation
apps/web/components/forms/NewOrganization.tsx
Adds .max(25) to the organization name validation schema and sets maxLength={25} on the Input component.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Page as /s/[videoId]/page
  participant Loader as DataLoader
  participant Share as ShareHeader
  participant Image as Next/Image
  participant Avatar as Avatar

  User->>Page: navigate to /s/[videoId]
  Page->>Loader: fetch video + organization fields
  Loader-->>Page: returns { ..., organizationIconUrl?, organizationName? }
  Page->>Share: render ShareHeader(data)

  alt organizationIconUrl present
    Share->>Image: render organizationIconUrl
  else
    Share->>Avatar: render organizationName fallback
  end

  note right of Share: Title input interaction
  User->>Share: edit title -> blur
  alt title changed
    Share->>Share: handleBlur updates title
  else
    Share-->>User: no update (guarded)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • Brendonovich

Poem

A hop, a tweak, a tiny nod,
An icon peeks where data trod.
Titles wait — only change when true,
Names trimmed short to fit the view.
Dashboard hums — a rabbit’s cheer 🥕🐇

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 accurately and concisely describes the primary UI change of displaying the organization name and image on the share page, matching the PR’s main objective without unnecessary detail.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web/app/s/[videoId]/page.tsx (1)

351-366: Fix TypeScript error: Add organizationName to the video type.

The static analysis correctly flags that organizationName is missing from the video type definition. While organizationIconUrl is included at line 364, organizationName is omitted. This causes a type error at line 687 where video.organizationName is accessed.

Apply this diff to add the missing property:

 	video: Omit<
 		InferSelectModel<typeof videos>,
 		"folderId" | "password" | "settings"
 	> & {
 		sharedOrganization: { organizationId: string } | null;
 		hasPassword: boolean;
 		ownerIsPro?: boolean;
 		orgSettings?: OrganizationSettings | null;
 		videoSettings?: OrganizationSettings | null;
 		organizationIconUrl?: string | null;
+		organizationName?: string | null;
 	};
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 889cafb and 6cf5e1f.

📒 Files selected for processing (4)
  • apps/web/app/(org)/dashboard/_components/Navbar/Items.tsx (1 hunks)
  • apps/web/app/s/[videoId]/_components/ShareHeader.tsx (7 hunks)
  • apps/web/app/s/[videoId]/page.tsx (4 hunks)
  • apps/web/components/forms/NewOrganization.tsx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
apps/web/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/web/**/*.{ts,tsx}: Use TanStack Query v5 for all client-side server state and data fetching in the web app
Web mutations should call Server Actions directly and perform targeted cache updates with setQueryData/setQueriesData rather than broad invalidations
Client code should use useEffectQuery/useEffectMutation and useRpcClient from apps/web/lib/EffectRuntime.ts; do not create ManagedRuntime inside components

Files:

  • apps/web/app/(org)/dashboard/_components/Navbar/Items.tsx
  • apps/web/app/s/[videoId]/_components/ShareHeader.tsx
  • apps/web/app/s/[videoId]/page.tsx
  • apps/web/components/forms/NewOrganization.tsx
apps/web/app/**/*.{tsx,ts}

📄 CodeRabbit inference engine (CLAUDE.md)

Prefer Server Components for initial data in the Next.js App Router and pass initialData to client components

Files:

  • apps/web/app/(org)/dashboard/_components/Navbar/Items.tsx
  • apps/web/app/s/[videoId]/_components/ShareHeader.tsx
  • apps/web/app/s/[videoId]/page.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/web/app/(org)/dashboard/_components/Navbar/Items.tsx
  • apps/web/app/s/[videoId]/_components/ShareHeader.tsx
  • apps/web/app/s/[videoId]/page.tsx
  • apps/web/components/forms/NewOrganization.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/web/app/(org)/dashboard/_components/Navbar/Items.tsx
  • apps/web/app/s/[videoId]/_components/ShareHeader.tsx
  • apps/web/app/s/[videoId]/page.tsx
  • apps/web/components/forms/NewOrganization.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/web/app/(org)/dashboard/_components/Navbar/Items.tsx
  • apps/web/app/s/[videoId]/_components/ShareHeader.tsx
  • apps/web/app/s/[videoId]/page.tsx
  • apps/web/components/forms/NewOrganization.tsx
apps/web/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

On the client, always use useEffectQuery or useEffectMutation from @/lib/EffectRuntime; never call EffectRuntime.run* directly in components.

Files:

  • apps/web/app/(org)/dashboard/_components/Navbar/Items.tsx
  • apps/web/app/s/[videoId]/_components/ShareHeader.tsx
  • apps/web/app/s/[videoId]/page.tsx
  • apps/web/components/forms/NewOrganization.tsx
🧬 Code graph analysis (2)
apps/web/app/s/[videoId]/_components/ShareHeader.tsx (1)
packages/database/schema.ts (1)
  • videos (256-311)
apps/web/app/s/[videoId]/page.tsx (1)
packages/database/schema.ts (1)
  • organizations (152-180)
🪛 GitHub Check: Typecheck
apps/web/app/s/[videoId]/page.tsx

[failure] 687-687:
Property 'organizationName' does not exist on type 'Omit<{ metadata: VideoMetadata | null; name: string; id: string & Brand<"VideoId">; ownerId: string; settings: { disableSummary?: boolean | undefined; disableCaptions?: boolean | undefined; disableChapters?: boolean | undefined; disableReactions?: boolean | undefined; disableTranscript?: boolean | undefined; disable...'.

⏰ 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: Build Desktop (x86_64-pc-windows-msvc, windows-latest)
  • GitHub Check: Build Desktop (aarch64-apple-darwin, macos-latest)
  • GitHub Check: Analyze (rust)
🔇 Additional comments (1)
apps/web/app/s/[videoId]/_components/ShareHeader.tsx (1)

79-81: LGTM!

The guard prevents unnecessary title updates when the value hasn't changed, avoiding redundant API calls.

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 6cf5e1f and 87021b0.

📒 Files selected for processing (1)
  • apps/web/app/s/[videoId]/page.tsx (4 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
apps/web/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/web/**/*.{ts,tsx}: Use TanStack Query v5 for all client-side server state and data fetching in the web app
Web mutations should call Server Actions directly and perform targeted cache updates with setQueryData/setQueriesData rather than broad invalidations
Client code should use useEffectQuery/useEffectMutation and useRpcClient from apps/web/lib/EffectRuntime.ts; do not create ManagedRuntime inside components

Files:

  • apps/web/app/s/[videoId]/page.tsx
apps/web/app/**/*.{tsx,ts}

📄 CodeRabbit inference engine (CLAUDE.md)

Prefer Server Components for initial data in the Next.js App Router and pass initialData to client components

Files:

  • apps/web/app/s/[videoId]/page.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/web/app/s/[videoId]/page.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/web/app/s/[videoId]/page.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/web/app/s/[videoId]/page.tsx
apps/web/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

On the client, always use useEffectQuery or useEffectMutation from @/lib/EffectRuntime; never call EffectRuntime.run* directly in components.

Files:

  • apps/web/app/s/[videoId]/page.tsx
🧬 Code graph analysis (1)
apps/web/app/s/[videoId]/page.tsx (1)
packages/database/schema.ts (1)
  • organizations (152-180)
⏰ 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: Build Desktop (aarch64-apple-darwin, macos-latest)
  • GitHub Check: Build Desktop (x86_64-pc-windows-msvc, windows-latest)
  • GitHub Check: Analyze (rust)
🔇 Additional comments (2)
apps/web/app/s/[videoId]/page.tsx (2)

108-109: Type definitions are correct but require proper data fetching.

The type definitions for organizationIconUrl and organizationName are syntactically correct. However, ensure these fields are properly fetched from the database (see comment on lines 687-688).

Also applies to: 364-365


484-485: Selection is correct but only executes conditionally.

The selection of organizationIconUrl and organizationName is correct. However, this query only executes when transcription is not COMPLETE or PROCESSING (line 452), meaning these fields won't be available for videos with completed transcription.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/web/app/s/[videoId]/_components/ShareHeader.tsx (2)

136-138: Fix owner check to avoid false negatives in upgrade banner.

Use the computed isOwner for consistency with the toString comparison.

-  const showUpgradeBanner =
-    user && data.ownerId === user.id && !userIsPro(user);
+  const showUpgradeBanner = isOwner && !userIsPro(user);

Also applies to: 67-68


152-171: Use semantic button for share status (keyboard accessible).

Interactive

is not focusable and breaks keyboard navigation.

-          <p
-            className={clsx(baseClassName, "cursor-pointer hover:text-gray-12")}
-            onClick={() => setIsSharingDialogOpen(true)}
-          >
-            Not shared{" "}
-            <FontAwesomeIcon className="ml-2 size-2.5" icon={faChevronDown} />
-          </p>
+          <button
+            type="button"
+            className={clsx(baseClassName, "cursor-pointer hover:text-gray-12")}
+            onClick={() => setIsSharingDialogOpen(true)}
+          >
+            Not shared{" "}
+            <FontAwesomeIcon className="ml-2 size-2.5" icon={faChevronDown} />
+          </button>
-          <p
-            className={clsx(baseClassName, "cursor-pointer hover:text-gray-12")}
-            onClick={() => setIsSharingDialogOpen(true)}
-          >
-            Shared{" "}
-            <FontAwesomeIcon className="ml-1 size-2.5" icon={faChevronDown} />
-          </p>
+          <button
+            type="button"
+            className={clsx(baseClassName, "cursor-pointer hover:text-gray-12")}
+            onClick={() => setIsSharingDialogOpen(true)}
+          >
+            Shared{" "}
+            <FontAwesomeIcon className="ml-1 size-2.5" icon={faChevronDown} />
+          </button>
🧹 Nitpick comments (5)
apps/web/app/s/[videoId]/_components/ShareHeader.tsx (5)

225-227: Fallback and truncate organization name to avoid null/overflow.

-                <p className="text-sm font-medium text-gray-12">
-                  {data.organizationName}
-                </p>
+                <p
+                  className="text-sm font-medium text-gray-12 max-w-[200px] truncate"
+                  title={data.organizationName ?? "Organization"}
+                >
+                  {data.organizationName ?? "Organization"}
+                </p>

269-277: Clear clipboard timer to avoid state updates after unmount.

Store timeout id in a ref and clean it up.

-                  onClick={() => {
-                    navigator.clipboard.writeText(getVideoLink());
-                    setLinkCopied(true);
-                    setTimeout(() => {
-                      setLinkCopied(false);
-                    }, 2000);
-                  }}
+                  onClick={() => {
+                    navigator.clipboard.writeText(getVideoLink());
+                    setLinkCopied(true);
+                    if (copyTimer.current) clearTimeout(copyTimer.current);
+                    copyTimer.current = window.setTimeout(() => {
+                      setLinkCopied(false);
+                    }, 2000);
+                  }}

Add these outside changes:

// import line
import { useEffect, useRef, useState } from "react";

// near other state
const copyTimer = useRef<number>();

// cleanup
useEffect(() => {
  return () => {
    if (copyTimer.current) clearTimeout(copyTimer.current);
  };
}, []);

82-84: Avoid full refresh; prefer targeted updates.

After editTitle, update local/UI state or targeted caches instead of refresh(), per project guidelines.

As per coding guidelines


117-133: Optional: normalize display link (strip protocol for consistency).

-      return `${webUrl}/s/${data.id}`;
+      return `${webUrl.replace(/^https?:\/\//, "")}/s/${data.id}`;

210-218: Improve organization icon alt text and specify sizes

  • Change alt to {data.organizationName ?? "Organization"} and add sizes="36px" on the <Image />.
  • apps/web/next.config.mjs already permits all hosts via remotePatterns.hostname = "**".
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 87021b0 and 518f3b9.

📒 Files selected for processing (2)
  • apps/web/app/s/[videoId]/_components/ShareHeader.tsx (6 hunks)
  • apps/web/app/s/[videoId]/page.tsx (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/app/s/[videoId]/page.tsx
🧰 Additional context used
📓 Path-based instructions (6)
apps/web/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/web/**/*.{ts,tsx}: Use TanStack Query v5 for all client-side server state and data fetching in the web app
Web mutations should call Server Actions directly and perform targeted cache updates with setQueryData/setQueriesData rather than broad invalidations
Client code should use useEffectQuery/useEffectMutation and useRpcClient from apps/web/lib/EffectRuntime.ts; do not create ManagedRuntime inside components

Files:

  • apps/web/app/s/[videoId]/_components/ShareHeader.tsx
apps/web/app/**/*.{tsx,ts}

📄 CodeRabbit inference engine (CLAUDE.md)

Prefer Server Components for initial data in the Next.js App Router and pass initialData to client components

Files:

  • apps/web/app/s/[videoId]/_components/ShareHeader.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/web/app/s/[videoId]/_components/ShareHeader.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/web/app/s/[videoId]/_components/ShareHeader.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/web/app/s/[videoId]/_components/ShareHeader.tsx
apps/web/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

On the client, always use useEffectQuery or useEffectMutation from @/lib/EffectRuntime; never call EffectRuntime.run* directly in components.

Files:

  • apps/web/app/s/[videoId]/_components/ShareHeader.tsx
🧬 Code graph analysis (1)
apps/web/app/s/[videoId]/_components/ShareHeader.tsx (1)
packages/database/schema.ts (1)
  • videos (256-311)
⏰ 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: Build Desktop (aarch64-apple-darwin, macos-latest)
  • GitHub Check: Build Desktop (x86_64-pc-windows-msvc, windows-latest)
  • GitHub Check: Analyze (rust)
🔇 Additional comments (1)
apps/web/app/s/[videoId]/_components/ShareHeader.tsx (1)

219-224: Avatar fallback looks good.

@ameer2468 ameer2468 merged commit e287051 into main Oct 7, 2025
15 checks passed
@ameer2468 ameer2468 deleted the org-on-share-page branch October 7, 2025 15:32
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