Skip to content

feat: replace Fluid Player with Video.js IMA#149

Open
AlejandroAkbal wants to merge 3 commits into
mainfrom
feature/videojs-ima-player
Open

feat: replace Fluid Player with Video.js IMA#149
AlejandroAkbal wants to merge 3 commits into
mainfrom
feature/videojs-ima-player

Conversation

@AlejandroAkbal

@AlejandroAkbal AlejandroAkbal commented Jul 13, 2026

Copy link
Copy Markdown
Member

Summary

  • replace Fluid Player with Video.js, contrib-ads, and Google IMA
  • preserve ExoClick preroll and explicit-user pause-ad cadence with bounded fail-open behavior
  • disable VPAID, remove Fluid-specific Sentry filtering, and remove CSP unsafe-eval
  • add tested ad scheduling and pause eligibility policy

Safety and UX

  • cap VAST redirects and request/creative timeouts
  • prevent late ads from interrupting content after timeout
  • suppress pause ads for programmatic/offscreen pauses, active or pending ads, ended content, and repeated pauses
  • skip all ad modules and network requests for premium users
  • leave content playback usable when IMA loading or initialization fails

Verification

  • pnpm check
  • pnpm audit --prod — no known vulnerabilities
  • security review — no critical/high findings

Deployment gate

Live ExoClick inventory, blocker extensions, iPhone Safari, Android Chrome, and revenue parity still require a production canary because deterministic repository tests cannot prove third-party creative behavior.

Summary by CodeRabbit

  • New Features
    • Updated video ads to use Video.js with Google IMA, including policy-driven pre-roll and pause-roll scheduling.
  • Security
    • Tightened Content Security Policy by removing unsafe-eval from script-src.
    • Updated error-reporting URL filtering for deprecated player assets.
  • Bug Fixes
    • Prevented pause-roll requests during programmatic pauses and during stale/partial player initialization.
    • Improved pause behavior when the video leaves the viewport and ensured user-interaction gating for ad setup.
  • Tests
    • Added unit tests for ad scheduling/loading/eligibility and expanded PostMedia player assertions.

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9dc4c866-f745-4731-8c1b-d7ec9b60d04c

📥 Commits

Reviewing files that changed from the base of the PR and between aaef562 and 2014abe.

📒 Files selected for processing (2)
  • app/components/pages/posts/post/PostMedia.vue
  • test/pages/posts.test.ts
📜 Recent review details
🧰 Additional context used
📓 Path-based instructions (8)
test/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

test/**/*.{test,spec}.{ts,tsx}: Use Vitest with @nuxt/test-utils and Playwright browser mode for testing
Use @nuxt/test-utils with Playwright inside describe blocks calling await setup({ browser: true })
Mock server-side API calls via test-only Nitro plugin at test/server-mocks/plugin.ts injected through nuxt.config.ts $test.nitro.plugins
Use debugBrowserOptions from test/helper.ts for headful Playwright playback with slowMo in tests
Keep repository/pure modules importable through relative paths in plain Vitest suites that do not get Nuxt's runtime alias resolution
Use fetch from @nuxt/test-utils with { redirect: 'manual' } to access redirect status and Location headers; @nuxt/test-utils $fetch has no .raw method
Import localeCodes, prefixedLocaleCodes, and removedLocaleCodes from config/i18n in tests instead of hardcoding locale lists

Files:

  • test/pages/posts.test.ts
**/*.{vue,ts,tsx,js,jsx,json,css,scss}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier for formatting with 120-char print width, no semicolons, single quotes, trailing commas removed, and single attribute per line in Vue templates

Files:

  • test/pages/posts.test.ts
  • app/components/pages/posts/post/PostMedia.vue
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

Use Nuxt flat ESLint via @nuxt/eslint for linting

Files:

  • test/pages/posts.test.ts
  • app/components/pages/posts/post/PostMedia.vue
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,vue}: Define locales in config/i18n.ts as the single source of truth; do not hardcode locale lists in application code
Use PocketBase batch writes for multi-record replacement/reorder operations instead of one HTTP write per changed row

Files:

  • test/pages/posts.test.ts
  • app/components/pages/posts/post/PostMedia.vue
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: For URL validation/parsing, prefer URL.canParse() or URL.parse() over constructor try/catch
Use URL.parse() when the parsed URL object is needed, with URL.canParse() fallback in browser code if compatibility matters

Files:

  • test/pages/posts.test.ts
app/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

app/**/*.{vue,ts,tsx}: Use Nuxt 4 with Vue 3 and TypeScript for the frontend application
Use useLazyToast() to lazy-load vue-sonner; wait for ClientToaster to mount before calling toast.* using a proper async wait instead of plain nextTick()
Build reordered array synchronously instead of reading VueUse moveArrayElement() result before nextTick for state immediately persisted

Files:

  • app/components/pages/posts/post/PostMedia.vue
app/components/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

app/components/**/*.vue: Register Vue components without path prefix using pathPrefix: false in nuxt.config.ts; import them as not <Input/DomainSelector>
Auto-import components from app/components/ flat structure without folder prefix
Use custom imgproxy provider for images; generate images at 1x density only in webp format to reduce bandwidth
Use @nuxt/image v2 preload API (preload: { fetchPriority: 'high' }) for image preload priority instead of patching rendered HTML in Nitro
Use Nuxt Lazy* components, dynamic imports, or similarly deferred boundaries for components and composables only needed after user interaction (menu, sheet, dialog)

Files:

  • app/components/pages/posts/post/PostMedia.vue
app/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

app/**/*.vue: Use project.urls.production for canonical URLs to point to production (https://r34.app/...) even when served from clone domains
Keep breadcrumb Schema.org source item URLs local/locale-relative; do not convert to project.urls.production since nuxt-schema-org resolves against site.url
When triggering a premium prompt from a nested dialog/bottom sheet, let the sheet owner close local UI, open the prompt, and restore UI after prompt closes
Premium auth transitions are reload-backed in dashboard/sign-in flow; rely on page reload to clear memory state instead of tracking PocketBase user ids in useState

Files:

  • app/components/pages/posts/post/PostMedia.vue
🧠 Learnings (1)
📚 Learning: 2026-06-22T07:50:54.935Z
Learnt from: AlejandroAkbal
Repo: Rule-34/App PR: 144
File: test/server/fix-canonical-queries.test.ts:174-178
Timestamp: 2026-06-22T07:50:54.935Z
Learning: In this Nuxt 3/4 project using `nuxt-schema-org` (v6.2.1), breadcrumb `source`/`itemListElement` URL values may be provided via `localePath()` (locale-relative in source code), but `nuxt-schema-org` renders JSON-LD with production-absolute URLs using `site.url` during schema rendering. When asserting JSON-LD breadcrumb `itemListElement` URLs in tests, expect production-absolute URLs (e.g., prefix with `project.urls.production.origin`), not the locale-relative `localePath()` forms. Do not flag production-absolute URL strings in JSON-LD breadcrumb tests as incorrect.

Applied to files:

  • test/pages/posts.test.ts
🔇 Additional comments (2)
app/components/pages/posts/post/PostMedia.vue (1)

5-837: LGTM!

test/pages/posts.test.ts (1)

1-88: LGTM!


📝 Walkthrough

Walkthrough

Changes

The PR replaces fluid-player with Video.js and Google IMA, adds reusable video ad policy helpers and tests, updates player lifecycle and pause handling, introduces IMA typings and dependencies, tightens CSP configuration, and changes Sentry URL filtering.

Video.js IMA ad integration

Layer / File(s) Summary
Ad policy contracts and validation
app/assets/js/video-ad-policy.ts, test/assets/video-ad-policy.test.ts
Adds schedule, ad-loading, and pause-ad eligibility helpers with table-driven tests.
Video.js and IMA player flow
app/components/pages/posts/post/PostMedia.vue, app/types/videojs-ima.d.ts, test/pages/posts.test.ts
Configures Video.js with IMA, loads the SDK, handles ad events and pause-roll requests, manages player teardown and visibility changes, and verifies initialization ordering and SDK timeout behavior.
Runtime dependencies and security configuration
package.json, nuxt.config.ts, sentry.client.options.ts
Replaces fluid-player dependencies, adds IMA-related packages, removes unsafe-eval from CSP, and updates Sentry URL filtering.

Sequence Diagram(s)

sequenceDiagram
  participant Viewer
  participant PostMedia
  participant VideoJS
  participant GoogleIMA
  Viewer->>PostMedia: Focus or pointer interaction
  PostMedia->>GoogleIMA: Initialize ad display container
  PostMedia->>VideoJS: Create player and configure IMA
  VideoJS->>GoogleIMA: Load configured ad tag
  GoogleIMA-->>PostMedia: Emit ad lifecycle events
  PostMedia->>GoogleIMA: Request eligible pause ad
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: replacing Fluid Player with Video.js IMA.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ 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 feature/videojs-ima-player
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch feature/videojs-ima-player

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@app/components/pages/posts/post/PostMedia.vue`:
- Around line 368-371: Update onVideoUserInteraction so initializeVideoPlayer
runs before attempting IMA setup, then initialize the ad display container on
the created player within the same user-interaction flow. Ensure the container
initialization is not skipped when videoPlayer is initially undefined, while
preserving optional handling for unavailable IMA APIs.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: 54ef8795-a312-4921-877a-8d002701ddea

📥 Commits

Reviewing files that changed from the base of the PR and between d2bfd14 and 041b70d.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (7)
  • app/assets/js/video-ad-policy.ts
  • app/components/pages/posts/post/PostMedia.vue
  • app/types/videojs-ima.d.ts
  • nuxt.config.ts
  • package.json
  • sentry.client.options.ts
  • test/assets/video-ad-policy.test.ts
💤 Files with no reviewable changes (1)
  • sentry.client.options.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (9)
app/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

app/**/*.{vue,ts,tsx}: Use Nuxt 4 with Vue 3 and TypeScript for the frontend application
Use useLazyToast() to lazy-load vue-sonner; wait for ClientToaster to mount before calling toast.* using a proper async wait instead of plain nextTick()
Build reordered array synchronously instead of reading VueUse moveArrayElement() result before nextTick for state immediately persisted

Files:

  • app/assets/js/video-ad-policy.ts
  • app/types/videojs-ima.d.ts
  • app/components/pages/posts/post/PostMedia.vue
**/*.{vue,ts,tsx,js,jsx,json,css,scss}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier for formatting with 120-char print width, no semicolons, single quotes, trailing commas removed, and single attribute per line in Vue templates

Files:

  • app/assets/js/video-ad-policy.ts
  • app/types/videojs-ima.d.ts
  • test/assets/video-ad-policy.test.ts
  • nuxt.config.ts
  • app/components/pages/posts/post/PostMedia.vue
  • package.json
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

Use Nuxt flat ESLint via @nuxt/eslint for linting

Files:

  • app/assets/js/video-ad-policy.ts
  • app/types/videojs-ima.d.ts
  • test/assets/video-ad-policy.test.ts
  • nuxt.config.ts
  • app/components/pages/posts/post/PostMedia.vue
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,vue}: Define locales in config/i18n.ts as the single source of truth; do not hardcode locale lists in application code
Use PocketBase batch writes for multi-record replacement/reorder operations instead of one HTTP write per changed row

Files:

  • app/assets/js/video-ad-policy.ts
  • app/types/videojs-ima.d.ts
  • test/assets/video-ad-policy.test.ts
  • nuxt.config.ts
  • app/components/pages/posts/post/PostMedia.vue
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: For URL validation/parsing, prefer URL.canParse() or URL.parse() over constructor try/catch
Use URL.parse() when the parsed URL object is needed, with URL.canParse() fallback in browser code if compatibility matters

Files:

  • app/assets/js/video-ad-policy.ts
  • app/types/videojs-ima.d.ts
  • test/assets/video-ad-policy.test.ts
  • nuxt.config.ts
test/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

test/**/*.{test,spec}.{ts,tsx}: Use Vitest with @nuxt/test-utils and Playwright browser mode for testing
Use @nuxt/test-utils with Playwright inside describe blocks calling await setup({ browser: true })
Mock server-side API calls via test-only Nitro plugin at test/server-mocks/plugin.ts injected through nuxt.config.ts $test.nitro.plugins
Use debugBrowserOptions from test/helper.ts for headful Playwright playback with slowMo in tests
Keep repository/pure modules importable through relative paths in plain Vitest suites that do not get Nuxt's runtime alias resolution
Use fetch from @nuxt/test-utils with { redirect: 'manual' } to access redirect status and Location headers; @nuxt/test-utils $fetch has no .raw method
Import localeCodes, prefixedLocaleCodes, and removedLocaleCodes from config/i18n in tests instead of hardcoding locale lists

Files:

  • test/assets/video-ad-policy.test.ts
nuxt.config.ts

📄 CodeRabbit inference engine (AGENTS.md)

nuxt.config.ts: In test mode, set $test.runtimeConfig.public.apiUrl to '' so $fetch(baseURL: '') routes to local Nitro test server
Fully disable Sentry in tests via $test.sentry.enabled: false in nuxt.config.ts

Files:

  • nuxt.config.ts
app/components/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

app/components/**/*.vue: Register Vue components without path prefix using pathPrefix: false in nuxt.config.ts; import them as not <Input/DomainSelector>
Auto-import components from app/components/ flat structure without folder prefix
Use custom imgproxy provider for images; generate images at 1x density only in webp format to reduce bandwidth
Use @nuxt/image v2 preload API (preload: { fetchPriority: 'high' }) for image preload priority instead of patching rendered HTML in Nitro
Use Nuxt Lazy* components, dynamic imports, or similarly deferred boundaries for components and composables only needed after user interaction (menu, sheet, dialog)

Files:

  • app/components/pages/posts/post/PostMedia.vue
app/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

app/**/*.vue: Use project.urls.production for canonical URLs to point to production (https://r34.app/...) even when served from clone domains
Keep breadcrumb Schema.org source item URLs local/locale-relative; do not convert to project.urls.production since nuxt-schema-org resolves against site.url
When triggering a premium prompt from a nested dialog/bottom sheet, let the sheet owner close local UI, open the prompt, and restore UI after prompt closes
Premium auth transitions are reload-backed in dashboard/sign-in flow; rely on page reload to clear memory state instead of tracking PocketBase user ids in useState

Files:

  • app/components/pages/posts/post/PostMedia.vue
🧠 Learnings (1)
📚 Learning: 2026-06-22T07:50:54.935Z
Learnt from: AlejandroAkbal
Repo: Rule-34/App PR: 144
File: test/server/fix-canonical-queries.test.ts:174-178
Timestamp: 2026-06-22T07:50:54.935Z
Learning: In this Nuxt 3/4 project using `nuxt-schema-org` (v6.2.1), breadcrumb `source`/`itemListElement` URL values may be provided via `localePath()` (locale-relative in source code), but `nuxt-schema-org` renders JSON-LD with production-absolute URLs using `site.url` during schema rendering. When asserting JSON-LD breadcrumb `itemListElement` URLs in tests, expect production-absolute URLs (e.g., prefix with `project.urls.production.origin`), not the locale-relative `localePath()` forms. Do not flag production-absolute URL strings in JSON-LD breadcrumb tests as incorrect.

Applied to files:

  • test/assets/video-ad-policy.test.ts
🔇 Additional comments (9)
package.json (1)

59-59: LGTM!

Also applies to: 69-71

nuxt.config.ts (1)

447-447: 🔒 Security & Privacy

Verify the nonce chain for the dynamically loaded IMA SDK.

With 'strict-dynamic', confirm that loadImaSdk() is executed by a nonce-trusted script; otherwise the new policy may block the IMA SDK and silently disable ads because initialization errors are swallowed.

app/assets/js/video-ad-policy.ts (1)

1-30: LGTM!

test/assets/video-ad-policy.test.ts (1)

1-66: LGTM!

app/types/videojs-ima.d.ts (1)

1-16: LGTM!

app/components/pages/posts/post/PostMedia.vue (4)

502-514: 🎯 Functional Correctness | ⚡ Quick win

isProgrammaticPause guard is defeated by microtask/macrotask ordering.

videoPlayer.pause() triggers the media pause event as a task (macrotask), but isProgrammaticPause is cleared in a queueMicrotask, which runs first. By the time the 'pause' handler calls requestPauseAd, isProgrammatic is already false, so that eligibility check contributes nothing. It's currently harmless only because this same branch also sets isVideoVisible = false, and the isVisible check rejects the offscreen pause — but the intended programmatic-pause guard is effectively dead code and will silently fail if the visibility logic ever changes. Consider clearing the flag after the pause event settles (e.g., in the 'pause'/'seeked' handler or a setTimeout(…, 0)), or drop the redundant flag.


156-204: LGTM!


206-272: LGTM!


353-366: LGTM!

Comment thread app/components/pages/posts/post/PostMedia.vue
@AlejandroAkbal

Copy link
Copy Markdown
Member Author

Addressed the mobile IMA initialization feedback in aaef562: Video.js loads independently, the ad layer initializes after the first site interaction, and later video gestures synchronously initialize the available IMA display container. Also corrected programmatic-pause flag timing. Full pnpm check and pnpm audit --prod pass.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@app/components/pages/posts/post/PostMedia.vue`:
- Around line 220-225: Update the dynamic import initialization around
loadImaSdk so loadImaSdk() and videojs-contrib-ads complete before importing
videojs-ima; preserve the CSS import as appropriate, but ensure videojs-ima is
evaluated only after both dependencies have resolved.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: b77f2836-a8c0-46f0-8b36-7ca6cb0deb3f

📥 Commits

Reviewing files that changed from the base of the PR and between 041b70d and aaef562.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (2)
  • app/components/pages/posts/post/PostMedia.vue
  • package.json
📜 Review details
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{vue,ts,tsx,js,jsx,json,css,scss}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier for formatting with 120-char print width, no semicolons, single quotes, trailing commas removed, and single attribute per line in Vue templates

Files:

  • package.json
  • app/components/pages/posts/post/PostMedia.vue
app/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

app/**/*.{vue,ts,tsx}: Use Nuxt 4 with Vue 3 and TypeScript for the frontend application
Use useLazyToast() to lazy-load vue-sonner; wait for ClientToaster to mount before calling toast.* using a proper async wait instead of plain nextTick()
Build reordered array synchronously instead of reading VueUse moveArrayElement() result before nextTick for state immediately persisted

Files:

  • app/components/pages/posts/post/PostMedia.vue
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

Use Nuxt flat ESLint via @nuxt/eslint for linting

Files:

  • app/components/pages/posts/post/PostMedia.vue
app/components/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

app/components/**/*.vue: Register Vue components without path prefix using pathPrefix: false in nuxt.config.ts; import them as not <Input/DomainSelector>
Auto-import components from app/components/ flat structure without folder prefix
Use custom imgproxy provider for images; generate images at 1x density only in webp format to reduce bandwidth
Use @nuxt/image v2 preload API (preload: { fetchPriority: 'high' }) for image preload priority instead of patching rendered HTML in Nitro
Use Nuxt Lazy* components, dynamic imports, or similarly deferred boundaries for components and composables only needed after user interaction (menu, sheet, dialog)

Files:

  • app/components/pages/posts/post/PostMedia.vue
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,vue}: Define locales in config/i18n.ts as the single source of truth; do not hardcode locale lists in application code
Use PocketBase batch writes for multi-record replacement/reorder operations instead of one HTTP write per changed row

Files:

  • app/components/pages/posts/post/PostMedia.vue
app/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

app/**/*.vue: Use project.urls.production for canonical URLs to point to production (https://r34.app/...) even when served from clone domains
Keep breadcrumb Schema.org source item URLs local/locale-relative; do not convert to project.urls.production since nuxt-schema-org resolves against site.url
When triggering a premium prompt from a nested dialog/bottom sheet, let the sheet owner close local UI, open the prompt, and restore UI after prompt closes
Premium auth transitions are reload-backed in dashboard/sign-in flow; rely on page reload to clear memory state instead of tracking PocketBase user ids in useState

Files:

  • app/components/pages/posts/post/PostMedia.vue
🔇 Additional comments (2)
package.json (1)

59-59: LGTM!

Also applies to: 70-72

app/components/pages/posts/post/PostMedia.vue (1)

5-5: LGTM!

Also applies to: 11-11, 30-36, 39-39, 104-106, 108-110, 112-116, 288-299, 312-312, 332-333, 385-386, 536-538

Comment on lines +220 to +225
await Promise.all([
loadImaSdk(),
import('videojs-contrib-ads'),
import('videojs-ima'),
import('videojs-ima/dist/videojs.ima.css')
])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Fix race condition in dynamic plugin imports.

Using Promise.all to fetch and execute both videojs-contrib-ads and videojs-ima concurrently causes a race condition. videojs-ima modifies the Video.js module under the assumption that videojs-contrib-ads has already been fully evaluated. Furthermore, the IMA plugin requires the window.google.ima object to be populated by the time it executes.

Load videojs-ima sequentially only after videojs-contrib-ads and the loadImaSdk() promise have successfully resolved to prevent initialization crashes.

🐛 Proposed fix to ensure sequential dependency evaluation
-    await Promise.all([
-      loadImaSdk(),
-      import('videojs-contrib-ads'),
-      import('videojs-ima'),
-      import('videojs-ima/dist/videojs.ima.css')
-    ])
+    await Promise.all([
+      loadImaSdk(),
+      import('videojs-contrib-ads'),
+      import('videojs-ima/dist/videojs.ima.css')
+    ])
+    await import('videojs-ima')
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
await Promise.all([
loadImaSdk(),
import('videojs-contrib-ads'),
import('videojs-ima'),
import('videojs-ima/dist/videojs.ima.css')
])
await Promise.all([
loadImaSdk(),
import('videojs-contrib-ads'),
import('videojs-ima/dist/videojs.ima.css')
])
await import('videojs-ima')
🤖 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/components/pages/posts/post/PostMedia.vue` around lines 220 - 225, Update
the dynamic import initialization around loadImaSdk so loadImaSdk() and
videojs-contrib-ads complete before importing videojs-ima; preserve the CSS
import as appropriate, but ensure videojs-ima is evaluated only after both
dependencies have resolved.

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