Skip to content

Conversation

@ameer2468
Copy link
Contributor

@ameer2468 ameer2468 commented Aug 19, 2025

This PR: improves duration formatting + confirmation dialog label messages on loading.

Summary by CodeRabbit

  • New Features

    • Video thumbnails now display video duration for caps.
    • Confirmation dialogs show dynamic confirm button text (e.g., “Deleting…”/“Removing…”) while actions are in progress across spaces, caps, folders, members, and custom domains.
  • Chores

    • Removed unused imports in a folder component.
    • Cleaned up a non-functional comment in a type declaration file.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 19, 2025

Walkthrough

Adds dynamic confirmLabel to ConfirmationDialog usages to reflect pending states across multiple delete/remove flows. Refactors cap duration display: removes on-card overlay in CapCard and introduces a videoDuration prop to VideoThumbnail, which now renders a formatted duration badge. Also removes an unused comment in a TypeScript declarations file.

Changes

Cohort / File(s) Summary
Dynamic confirm label wiring
apps/web/app/(org)/dashboard/_components/Navbar/SpacesList.tsx, apps/web/app/(org)/dashboard/caps/components/Folder.tsx, apps/web/app/(org)/dashboard/caps/components/SelectedCapsBar.tsx, apps/web/app/(org)/dashboard/settings/organization/components/CustomDomain.tsx, apps/web/app/(org)/dashboard/settings/organization/components/MembersCard.tsx, apps/web/app/(org)/dashboard/spaces/browse/page.tsx, apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx
ConfirmationDialog confirmLabel now reflects pending state (e.g., "Deleting..." / "Removing...") while preserving existing loading and handlers.
Video duration handling
apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx, apps/web/components/VideoThumbnail.tsx
Removes moment-based duration overlay from CapCard; adds videoDuration?: string to VideoThumbnail and renders a formatted duration badge in the thumbnail using moment.
Type decl cleanup
packages/ui-solid/src/auto-imports.d.ts
Removes a non-functional lint-disable comment; no API changes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant UI as Page/Component
  participant Dialog as ConfirmationDialog
  participant Mut as Mutation

  User->>UI: Initiates delete/remove
  UI->>Dialog: open={true}, loading={pending}, confirmLabel={pending ? "...ing..." : "Delete/Remove"}
  User->>Dialog: Click Confirm
  Dialog->>Mut: onConfirm()
  Mut-->>Dialog: pending=true
  Dialog->>UI: propagate loading + label update
  Mut-->>Dialog: success/error, pending=false
  Dialog->>UI: close (on success or handled error)
Loading
sequenceDiagram
  autonumber
  participant Card as CapCard
  participant Thumb as VideoThumbnail
  participant Helper as formatDuration

  Card->>Thumb: videoDuration=cap.metadata?.duration
  alt videoDuration provided and > 0
    Thumb->>Helper: formatDuration(ms as string)
    Helper-->>Thumb: "X sec/min/hr"
    Thumb-->>Card: Render image + duration badge
  else
    Thumb-->>Card: Render image without badge
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

codex

Suggested reviewers

  • Brendonovich

Poem

A hare taps “Delete?” with twitchy might,
The button now whispers “...ing” mid-flight.
Caps wear their time like a moonlit crown,
Thumbnails brag the seconds down.
I thump approval, code aligned—
Quick paws, clean flows, ship right on time. 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch improve-duration-formatting

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:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • 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.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

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.

@ameer2468 ameer2468 merged commit 74113a4 into main Aug 19, 2025
13 of 15 checks passed
@ameer2468 ameer2468 deleted the improve-duration-formatting branch August 19, 2025 16:04
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 (1)
apps/web/app/(org)/dashboard/settings/organization/components/MembersCard.tsx (1)

115-132: Bug: Dialog description uses hardcoded test data instead of pendingMember

The description references pendingMemberTest instead of the actual selected member. This will show stale/wrong info in production.

Apply this diff to remove the test stub and use pendingMember, also fix capitalization:

- const pendingMemberTest = {
-   id: "1",
-   name: "John Doe",
-   email: "john.doe@example.com",
- };
+ // Removed test stub; use `pendingMember` state for runtime values.

@@
   <ConfirmationDialog
     open={confirmOpen}
     icon={<FontAwesomeIcon icon={faUser} />}
     title="Remove member"
     description={
-      pendingMemberTest
-        ? `Are you sure you want to remove ${pendingMemberTest.name} 
-         from your organization? this action cannot be undone.`
+      pendingMember
+        ? `Are you sure you want to remove ${pendingMember.name} from your organization? This action cannot be undone.`
         : ""
     }
     confirmLabel={removing ? "Removing..." : "Remove"}
🧹 Nitpick comments (3)
apps/web/app/(org)/dashboard/_components/Navbar/SpacesList.tsx (1)

336-353: Consider preventing dialog dismissal while deleting

If not already handled inside ConfirmationDialog, prevent closing the dialog via Escape/backdrop click while loading is true to avoid accidental dismissal mid-request.

Would you like me to add a prop (e.g., disableCloseWhileLoading) to ConfirmationDialog and wire it here?

apps/web/components/VideoThumbnail.tsx (2)

4-4: Replace moment with a tiny formatter and fix “< 1 sec”/“60 secs” edge cases

  • Moment is heavy for this use. A tiny pure-TS formatter trims bundle cost.
  • Current logic makes "< 1 sec" unreachable for sub-second values due to ceil; also can display “60 secs” instead of “1 min”.
  • Recommend accepting number | string, avoiding parse/format churn upstream.

Apply these diffs:

Remove the moment import:

-import moment from "moment";

Broaden the prop type to accept number | string:

-  videoDuration?: string;
+  videoDuration?: number | string;

Replace formatDuration with a lightweight, edge-case-safe version:

-const formatDuration = (duration: string) => {
-  const durationMs = parseFloat(duration);
-  const momentDuration = moment.duration(durationMs, "milliseconds");
-
-  const totalHours = Math.floor(momentDuration.asHours());
-  const totalMinutes = Math.floor(momentDuration.asMinutes());
-  const remainingSeconds = Math.ceil(momentDuration.asSeconds() % 60); // Use ceil to avoid 0 secs
-
-  if (totalHours > 0) {
-    return `${totalHours} hr${totalHours > 1 ? "s" : ""}`;
-  } else if (totalMinutes > 0) {
-    return `${totalMinutes} min${totalMinutes > 1 ? "s" : ""}`;
-  } else if (remainingSeconds > 0) {
-    return `${remainingSeconds} sec${remainingSeconds !== 1 ? "s" : ""}`;
-  } else {
-    return "< 1 sec"; // For very short durations
-  }
-};
+const formatDuration = (duration: string | number): string => {
+  const ms = typeof duration === "number" ? duration : Number.parseFloat(duration);
+  if (!Number.isFinite(ms) || ms < 0) return "< 1 sec";
+
+  // Use integer seconds; sub-second shows "< 1 sec"
+  const totalSeconds = Math.floor(ms / 1000);
+  if (totalSeconds < 1) return "< 1 sec";
+
+  const hours = Math.floor(totalSeconds / 3600);
+  const minutes = Math.floor((totalSeconds % 3600) / 60);
+  const seconds = totalSeconds % 60;
+
+  if (hours > 0) return `${hours} hr${hours > 1 ? "s" : ""}`;
+  if (minutes > 0) return `${minutes} min${minutes > 1 ? "s" : ""}`;
+  return `${seconds} sec${seconds !== 1 ? "s" : ""}`;
+};

Also applies to: 16-16, 19-36


111-115: Tailwind leading-0 may not exist (use leading-none)

If you’re on default Tailwind, leading-0 isn’t defined. Suggest leading-none for consistent line-height.

-  <p className="text-white leading-0 px-2 left-3 rounded-full backdrop-blur-sm absolute z-10 bottom-3 bg-black/50 text-[11px]">
+  <p className="text-white leading-none px-2 left-3 rounded-full backdrop-blur-sm absolute z-10 bottom-3 bg-black/50 text-[11px]">
📜 Review details

Configuration used: CodeRabbit UI
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 9bcc095 and 6e6cd83.

📒 Files selected for processing (9)
  • apps/web/app/(org)/dashboard/_components/Navbar/SpacesList.tsx (1 hunks)
  • apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx (2 hunks)
  • apps/web/app/(org)/dashboard/caps/components/Folder.tsx (1 hunks)
  • apps/web/app/(org)/dashboard/caps/components/SelectedCapsBar.tsx (1 hunks)
  • apps/web/app/(org)/dashboard/settings/organization/components/CustomDomain.tsx (1 hunks)
  • apps/web/app/(org)/dashboard/settings/organization/components/MembersCard.tsx (1 hunks)
  • apps/web/app/(org)/dashboard/spaces/browse/page.tsx (1 hunks)
  • apps/web/components/VideoThumbnail.tsx (4 hunks)
  • packages/ui-solid/src/auto-imports.d.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • packages/ui-solid/src/auto-imports.d.ts
⏰ 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 (8)
apps/web/app/(org)/dashboard/_components/Navbar/SpacesList.tsx (2)

336-353: Dynamic confirm label improves perceived responsiveness

Using confirmLabel={removing ? "Deleting..." : "Delete"} aligns the CTA text with the in-flight state. Looks good and consistent with loading={removing}.


336-353: ConfirmationDialog’s confirmLabel is correctly typed and defaulted
The ConfirmationDialog component declares confirmLabel?: string and assigns it a default of "Confirm", so existing usages that omit it will fall back to “Confirm.”

apps/web/app/(org)/dashboard/caps/components/SelectedCapsBar.tsx (1)

79-93: Good UX: confirm label reflects deletion state

confirmLabel={isDeleting ? "Deleting..." : "Delete"} is consistent with loading={isDeleting} and the disabled/spinner states on the trigger button. All good.

apps/web/app/(org)/dashboard/spaces/browse/page.tsx (1)

226-242: LGTM – dynamic label matches loading state

confirmLabel toggles with removing and mirrors loading={removing}. This improves clarity during the async delete.

apps/web/app/(org)/dashboard/settings/organization/components/CustomDomain.tsx (1)

69-79: LGTM – confirm label tied to mutation state

confirmLabel uses removeDomainMutation.isPending and aligns with loading. Nice consistency with other dialogs in the PR.

apps/web/app/(org)/dashboard/settings/organization/components/MembersCard.tsx (1)

123-141: LGTM – removal label toggles with state

confirmLabel={removing ? "Removing..." : "Remove"} is consistent with loading={removing}. Good.

apps/web/app/(org)/dashboard/caps/components/Folder.tsx (1)

377-386: ConfirmationDialog.confirmLabel prop verified

The ConfirmationDialog component’s props include the optional confirmLabel string (with a default of "Confirm"), so your dynamic label override (deleteFolder.isPending ? "Deleting..." : "Delete") will be applied correctly. Nice UX enhancement to reflect the pending state directly on the button.

apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx (1)

380-387: Dynamic confirmLabel on ConfirmationDialog: good consistency with pending state

Matches the pattern used elsewhere in the PR and improves UX while the delete mutation is pending.

Comment on lines 431 to 434
<VideoThumbnail
videoDuration={cap.metadata?.duration}
imageClass={clsx(
anyCapSelected
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify duration type/units passed to VideoThumbnail

You’re passing cap.metadata?.duration into videoDuration (typed as string in VideoThumbnail). Please confirm:

  • Type is string or update to number | string (recommended in my VideoThumbnail comment).
  • Units are milliseconds (the formatter assumes ms; if it’s seconds, it will undercount by 1000x).

Run this to find the VideoMetadata definition and the duration field’s type and docstring/usages:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo 'Searching for VideoMetadata definition...'
rg -n -C3 -P '(interface|type)\s+VideoMetadata\b' --type=ts || true

echo 'Searching for duration field within VideoMetadata...'
rg -n -C3 -P 'VideoMetadata|duration\s*:\s*' --type=ts | sed 's/^/• /' || true

echo 'Searching for where metadata.duration is set (to infer units)...'
rg -n -C3 -P '\bmetadata\b[^;]*\bduration\b' --type=ts -- apps || true

Length of output: 95791


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== VideoMetadata interface snippet (first 50 lines) ==="
sed -n '1,50p' packages/database/types/metadata.ts || true

echo
echo "=== Searching for 'duration' property in VideoMetadata ==="
rg -n '^\s*duration\s*:' -C2 packages/database/types/metadata.ts || echo "No duration property found"

Length of output: 1423


Align VideoMetadata.duration (seconds) with VideoThumbnail (milliseconds)

We discovered that VideoMetadata.duration is defined as string | number in seconds:

/** Duration of the video in seconds */
duration?: string | number;

However, VideoThumbnail expects a string representing milliseconds:

interface VideoThumbnailProps {
  videoDuration?: string;
}
const formatDuration = (duration: string) => {
  const durationMs = parseFloat(duration);
  return moment.duration(durationMs, "milliseconds")  
};

Passing raw seconds into a formatter that treats its input as milliseconds will undercount by 1 000×. Please address this mismatch:

In CapCard.tsx (lines 431–434)

  • Convert seconds → milliseconds at the call site, e.g.:
    - <VideoThumbnail
    -   videoDuration={cap.metadata?.duration}
    -
    - />
    + <VideoThumbnail
    +   videoDuration={
    +     cap.metadata?.duration != null
    +       ? String(Number(cap.metadata.duration) * 1000)
    +       : undefined
    +   }
    +
    + />

In VideoThumbnail.tsx

  • Update prop type to accept both string | number:
    - interface VideoThumbnailProps { videoDuration?: string }
    + interface VideoThumbnailProps { videoDuration?: string | number }
  • Enhance formatDuration to detect numbers or adjust the unit (e.g., use "seconds" when appropriate) or normalize all inputs to milliseconds.
🤖 Prompt for AI Agents
In apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx around lines
431–434, the video duration (seconds) is being passed directly to VideoThumbnail
which expects milliseconds; convert the value to milliseconds at the call site
(e.g., multiply numeric seconds by 1000 and ensure a string is passed). Also
update VideoThumbnail.tsx to accept videoDuration?: string | number and
normalize inside (accept number or string, parse/convert seconds → milliseconds
when needed or treat numeric input as milliseconds consistently), and make
formatDuration resilient by parsing numbers and ensuring it always calls
moment.duration with milliseconds.

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.

2 participants