-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix Rive crashes in New Folder/Subfolder dialogs and shared folder components (#1409) #1426
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughWraps Rive animation calls with error handling, guards mouse handlers and rendering on missing Rive files, stops animations when dialogs close, and renders skeleton placeholders when Rive resources are unavailable. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (1)
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx (1)
183-185: Consider consistent class ordering for skeleton placeholders.The skeleton placeholder works correctly, but the class order (
bg-gray-4 rounded) differs from SubfolderDialog's (rounded bg-gray-4). While functionally equivalent, consistent ordering improves maintainability.Apply this diff for consistency with SubfolderDialog:
- <div className="w-[50px] h-[50px] bg-gray-4 rounded animate-pulse" /> + <div className="w-[50px] h-[50px] rounded bg-gray-4 animate-pulse" />
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/web/app/(org)/dashboard/caps/components/Folders.tsx(5 hunks)apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx(2 hunks)apps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsx(2 hunks)
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx,js,jsx,rs,py,sh}
📄 CodeRabbit inference engine (CLAUDE.md)
Never add any form of comments to code (single-line //, multi-line /* /, documentation ///, //!, /* */, or any other comment syntax). Code must be self-explanatory through naming, types, and structure.
Files:
apps/web/app/(org)/dashboard/caps/components/Folders.tsxapps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsxapps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsx
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
Use Server Actions for mutations; perform precise cache updates with setQueryData/setQueriesData rather than broad invalidations
Use Tailwind CSS only for styling; maintain consistency with spacing and tokens
React Query hooks should wrap Effect workflows with useEffectQuery/useEffectMutation from apps/web/lib/EffectRuntime.ts
Use Drizzle ORM for all database operations; leverage shared services like Videos and VideosPolicy rather than ad-hoc queries
Memoize expensive work, code-split naturally, and use Next/Image for remote assetsOn the server, run effects through
EffectRuntime.runPromisefrom@/lib/server, typically afterprovideOptionalAuth
Files:
apps/web/app/(org)/dashboard/caps/components/Folders.tsxapps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsxapps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsx
apps/web/app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/app/**/*.{ts,tsx}: Prefer Server Components for SEO/initial rendering; hydrate interactivity in client components
Server components needing Effect services should call EffectRuntime.runPromise with provideOptionalAuth to maintain request context and tracing consistency
Files:
apps/web/app/(org)/dashboard/caps/components/Folders.tsxapps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsxapps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsx
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use PascalCase for component names; use camelCase starting with 'use' for hook names
Use PascalCase for component names in TypeScript/JavaScript
Files:
apps/web/app/(org)/dashboard/caps/components/Folders.tsxapps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsxapps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Enforce strict TypeScript; avoid 'any' type; leverage shared types from packages/utils and other shared packages
Files:
apps/web/app/(org)/dashboard/caps/components/Folders.tsxapps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsxapps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use Biome for linting and formatting; run pnpm format and pnpm lint regularly and at the end of each coding session
**/*.{ts,tsx,js,jsx}: Use 2-space indentation in TypeScript files
Format all TypeScript and JavaScript code using Biome (viapnpm format)
Files:
apps/web/app/(org)/dashboard/caps/components/Folders.tsxapps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsxapps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsx
apps/web/**/*.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/**/*.tsx: Minimize useEffect usage: compute during render, handle logic in event handlers, and ensure cleanups for subscriptions/timers
Use static skeletons that mirror content for loading states; avoid bouncing animations
Files:
apps/web/app/(org)/dashboard/caps/components/Folders.tsxapps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsxapps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsx
**/*.{ts,tsx,js,jsx,rs}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx,rs}: Use kebab-case for file names (e.g.,user-menu.tsx)
Never add comments to code in any language (no//,/* */,///,//!,#, etc.). Code must be self-explanatory through naming, types, and structure
Files:
apps/web/app/(org)/dashboard/caps/components/Folders.tsxapps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsxapps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsx
apps/web/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
On the client, use
useEffectQuery/useEffectMutationfrom@/lib/EffectRuntimeand do not callEffectRuntime.run*directly in components
Files:
apps/web/app/(org)/dashboard/caps/components/Folders.tsxapps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsxapps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsx
🪛 GitHub Actions: CI
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
[error] 84-86: Biome format check failed. File content differs from formatting output.
apps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsx
[error] 182-186: Biome format check failed. File content differs from formatting output.
🔇 Additional comments (4)
apps/web/app/(org)/dashboard/caps/components/Folders.tsx (1)
32-44: LGTM! Defensive error handling prevents crashes.The try/catch blocks around
rive.play()andrive.stop()effectively prevent uncaught exceptions from crashing the app when Rive objects are in an invalid state. The pattern is applied consistently across all folder components.apps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsx (2)
94-97: LGTM! Proper animation cleanup on dialog close.Stopping all folder animations when the dialog closes prevents memory leaks and ensures animations don't continue running in the background.
169-182: LGTM! Guards prevent crashes during async Rive loading.The early return when
riveFileis undefined prevents accessing animation methods before the Rive file has loaded, addressing the root cause described in the PR objectives.apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx (1)
164-177: LGTM! Guards prevent crashes during async Rive loading.The early return when
riveFileis undefined prevents accessing animation methods before the Rive file has loaded, consistent with the defensive pattern applied across folder components.
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
Outdated
Show resolved
Hide resolved
apps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this 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
🧹 Nitpick comments (1)
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx (1)
179-186: Consider using a static skeleton instead of animate-pulse.The conditional rendering logic is correct and provides a good fallback while the Rive file loads. However, per the coding guidelines, static skeletons are preferred over animated loading states.
As per coding guidelines ("Use static skeletons that mirror content for loading states; avoid bouncing animations"):
-<div className="w-[50px] h-[50px] bg-gray-4 rounded animate-pulse" /> +<div className="w-[50px] h-[50px] bg-gray-4 rounded" />
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx(2 hunks)apps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsx(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsx
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx,js,jsx,rs,py,sh}
📄 CodeRabbit inference engine (CLAUDE.md)
Never add any form of comments to code (single-line //, multi-line /* /, documentation ///, //!, /* */, or any other comment syntax). Code must be self-explanatory through naming, types, and structure.
Files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
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
Use Server Actions for mutations; perform precise cache updates with setQueryData/setQueriesData rather than broad invalidations
Use Tailwind CSS only for styling; maintain consistency with spacing and tokens
React Query hooks should wrap Effect workflows with useEffectQuery/useEffectMutation from apps/web/lib/EffectRuntime.ts
Use Drizzle ORM for all database operations; leverage shared services like Videos and VideosPolicy rather than ad-hoc queries
Memoize expensive work, code-split naturally, and use Next/Image for remote assetsOn the server, run effects through
EffectRuntime.runPromisefrom@/lib/server, typically afterprovideOptionalAuth
Files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
apps/web/app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/app/**/*.{ts,tsx}: Prefer Server Components for SEO/initial rendering; hydrate interactivity in client components
Server components needing Effect services should call EffectRuntime.runPromise with provideOptionalAuth to maintain request context and tracing consistency
Files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use PascalCase for component names; use camelCase starting with 'use' for hook names
Use PascalCase for component names in TypeScript/JavaScript
Files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Enforce strict TypeScript; avoid 'any' type; leverage shared types from packages/utils and other shared packages
Files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use Biome for linting and formatting; run pnpm format and pnpm lint regularly and at the end of each coding session
**/*.{ts,tsx,js,jsx}: Use 2-space indentation in TypeScript files
Format all TypeScript and JavaScript code using Biome (viapnpm format)
Files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
apps/web/**/*.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/**/*.tsx: Minimize useEffect usage: compute during render, handle logic in event handlers, and ensure cleanups for subscriptions/timers
Use static skeletons that mirror content for loading states; avoid bouncing animations
Files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
**/*.{ts,tsx,js,jsx,rs}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx,rs}: Use kebab-case for file names (e.g.,user-menu.tsx)
Never add comments to code in any language (no//,/* */,///,//!,#, etc.). Code must be self-explanatory through naming, types, and structure
Files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
apps/web/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
On the client, use
useEffectQuery/useEffectMutationfrom@/lib/EffectRuntimeand do not callEffectRuntime.run*directly in components
Files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
🧠 Learnings (2)
📚 Learning: 2025-11-29T04:31:05.289Z
Learnt from: CR
Repo: CapSoftware/Cap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T04:31:05.289Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Biome for linting and formatting; run pnpm format and pnpm lint regularly and at the end of each coding session
Applied to files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
📚 Learning: 2025-11-29T04:31:23.896Z
Learnt from: CR
Repo: CapSoftware/Cap PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-29T04:31:23.896Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Format all TypeScript and JavaScript code using Biome (via `pnpm format`)
Applied to files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
🔇 Additional comments (1)
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx (1)
164-177: LGTM! Guards prevent crashes when Rive file hasn't loaded.The early returns on lines 165 and 172 correctly prevent attempting to call methods on
folderRefwhenriveFileis undefined, addressing the root cause of the intermittent crashes described in the PR objectives.
There was a problem hiding this 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
📒 Files selected for processing (2)
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx(2 hunks)apps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsx(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsx
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx,js,jsx,rs,py,sh}
📄 CodeRabbit inference engine (CLAUDE.md)
Never add any form of comments to code (single-line //, multi-line /* /, documentation ///, //!, /* */, or any other comment syntax). Code must be self-explanatory through naming, types, and structure.
Files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
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
Use Server Actions for mutations; perform precise cache updates with setQueryData/setQueriesData rather than broad invalidations
Use Tailwind CSS only for styling; maintain consistency with spacing and tokens
React Query hooks should wrap Effect workflows with useEffectQuery/useEffectMutation from apps/web/lib/EffectRuntime.ts
Use Drizzle ORM for all database operations; leverage shared services like Videos and VideosPolicy rather than ad-hoc queries
Memoize expensive work, code-split naturally, and use Next/Image for remote assetsOn the server, run effects through
EffectRuntime.runPromisefrom@/lib/server, typically afterprovideOptionalAuth
Files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
apps/web/app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/app/**/*.{ts,tsx}: Prefer Server Components for SEO/initial rendering; hydrate interactivity in client components
Server components needing Effect services should call EffectRuntime.runPromise with provideOptionalAuth to maintain request context and tracing consistency
Files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use PascalCase for component names; use camelCase starting with 'use' for hook names
Use PascalCase for component names in TypeScript/JavaScript
Files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Enforce strict TypeScript; avoid 'any' type; leverage shared types from packages/utils and other shared packages
Files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use Biome for linting and formatting; run pnpm format and pnpm lint regularly and at the end of each coding session
**/*.{ts,tsx,js,jsx}: Use 2-space indentation in TypeScript files
Format all TypeScript and JavaScript code using Biome (viapnpm format)
Files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
apps/web/**/*.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/**/*.tsx: Minimize useEffect usage: compute during render, handle logic in event handlers, and ensure cleanups for subscriptions/timers
Use static skeletons that mirror content for loading states; avoid bouncing animations
Files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
**/*.{ts,tsx,js,jsx,rs}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx,rs}: Use kebab-case for file names (e.g.,user-menu.tsx)
Never add comments to code in any language (no//,/* */,///,//!,#, etc.). Code must be self-explanatory through naming, types, and structure
Files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
apps/web/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
On the client, use
useEffectQuery/useEffectMutationfrom@/lib/EffectRuntimeand do not callEffectRuntime.run*directly in components
Files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
🧠 Learnings (4)
📚 Learning: 2025-11-29T04:31:05.289Z
Learnt from: CR
Repo: CapSoftware/Cap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T04:31:05.289Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Biome for linting and formatting; run pnpm format and pnpm lint regularly and at the end of each coding session
Applied to files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
📚 Learning: 2025-11-29T04:31:23.896Z
Learnt from: CR
Repo: CapSoftware/Cap PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-29T04:31:23.896Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Format all TypeScript and JavaScript code using Biome (via `pnpm format`)
Applied to files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
📚 Learning: 2025-11-29T04:31:23.896Z
Learnt from: CR
Repo: CapSoftware/Cap PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-29T04:31:23.896Z
Learning: Applies to **/*.{ts,tsx,js,jsx,rs} : Never add comments to code in any language (no `//`, `/* */`, `///`, `//!`, `#`, etc.). Code must be self-explanatory through naming, types, and structure
Applied to files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
📚 Learning: 2025-11-29T04:31:05.289Z
Learnt from: CR
Repo: CapSoftware/Cap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T04:31:05.289Z
Learning: Applies to **/*.{ts,tsx,js,jsx,rs,py,sh} : Never add any form of comments to code (single-line //, multi-line /* */, documentation ///, //!, /** */, or any other comment syntax). Code must be self-explanatory through naming, types, and structure.
Applied to files:
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx
🔇 Additional comments (2)
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx (2)
86-93: LGTM! Proper animation cleanup on dialog close.The effect correctly stops all folder animations and resets selection state when the dialog closes, preventing memory leaks and stale animations.
163-176: LGTM! Hover handlers properly guarded.Both mouse handlers correctly check
riveFileavailability before attempting animation control, preventing crashes during async Rive file loading.
Description
Fixes #1409 - The "New Folder" and "New Subfolder" dialogs occasionally crashed with "Cannot read properties of undefined (reading 'isPlaying/stateMachines')" when opened or hovered too quickly.
Root Cause
Rive animations load asynchronously, but the dialogs rendered folder components and attached hover handlers before the animation file finished loading, causing calls to undefined Rive objects.
Changes
if (!riveFile) return, render folders only once file is loaded, show skeleton placeholder while loading, stop animations on dialog closerive.play/stopcalls in try/catch to prevent uncaught errorsTesting
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.