Skip to content

Conversation

@mtrezza
Copy link
Member

@mtrezza mtrezza commented Oct 29, 2025

New Pull Request Checklist

Issue Description

Media content in info panel such as images, videos, audios is not pre-fetched, making the pre-fetching feature less effective as the user has to wait for the content to load.

Approach

Added new options prefetchImage, prefetchVideo, and prefetchAudio to control media prefetching in the info panel when prefetchObjects is enabled. All media prefetch options default to true, so media prefetching is enabled by default when prefetchObjects is configured. Users can selectively disable specific media types by setting them to false in the configuration.

TODOs before merging

  • Add changes to documentation (guides, repository pages, in-code descriptions)

Summary by CodeRabbit

  • New Features

    • Added three boolean options — prefetchImage, prefetchVideo, prefetchAudio — to allow selective prefetching of images, videos, and audio. All default to true and apply when prefetchObjects is enabled. Media prefetching is opportunistic; failures are logged and do not block normal behavior.
  • Documentation

    • Updated examples and the Prefetching section to document the new flags and their defaults.

@parse-github-assistant
Copy link

parse-github-assistant bot commented Oct 29, 2025

🚀 Thanks for opening this pull request! We appreciate your effort in improving the project. Please let us know once your pull request is ready for review.

@coderabbitai
Copy link

coderabbitai bot commented Oct 29, 2025

Warning

Rate limit exceeded

@mtrezza has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 10 minutes and 33 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 3427d53 and a99cae0.

📒 Files selected for processing (1)
  • src/dashboard/Data/Browser/DataBrowser.react.js (3 hunks)
📝 Walkthrough

Walkthrough

Adds three per-panel boolean flags—prefetchImage, prefetchVideo, prefetchAudio (default true)—and implements media URL extraction and conditional media prefetching integrated into the existing object prefetch flow; updates README example and Prefetching docs accordingly.

Changes

Cohort / File(s) Summary
Documentation
README.md
Added prefetchImage, prefetchVideo, prefetchAudio options to the infoPanel example and expanded the Prefetching section to document that these flags apply when prefetchObjects is enabled.
Panel Defaults
src/dashboard/Data/Browser/Browser.react.js
Added per-panel default flags prefetchImage, prefetchVideo, prefetchAudio (using nullish coalescing to true) into panel config mapping so panels always expose these settings.
Prefetch Engine
src/dashboard/Data/Browser/DataBrowser.react.js
Added isSafeHttpUrl(url), extractMediaUrls(data), and prefetchMedia(urls, mediaType) methods; updated getPrefetchSettings() to include the three media flags; integrated conditional media prefetching into prefetchObject() using extracted URLs, with errors logged non-fatally.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant DataBrowser
    participant Backend
    participant Browser

    User->>DataBrowser: Request data / trigger prefetch (prefetchObjects=true)
    DataBrowser->>Backend: Fetch object
    Backend-->>DataBrowser: Return object

    rect rgb(230, 245, 255)
    Note over DataBrowser: Conditional media prefetching (new)
    alt prefetchImage enabled
        DataBrowser->>DataBrowser: extractMediaUrls(data) -> imageUrls
        DataBrowser->>Browser: prefetchMedia(imageUrls,'image')
        Browser->>Browser: Load via Image objects
    end
    alt prefetchVideo enabled
        DataBrowser->>DataBrowser: extractMediaUrls(data) -> videoUrls
        DataBrowser->>DataBrowser: prefetchMedia(videoUrls,'video')
        DataBrowser->>Backend: fetch video URLs (cacheable)
    end
    alt prefetchAudio enabled
        DataBrowser->>DataBrowser: extractMediaUrls(data) -> audioUrls
        DataBrowser->>DataBrowser: prefetchMedia(audioUrls,'audio')
        DataBrowser->>Backend: fetch audio URLs (cacheable)
    end
    end

    DataBrowser-->>User: Prefetch complete (errors logged, non-fatal)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Review extractMediaUrls() traversal for nested fields, arrays and null handling.
  • Verify isSafeHttpUrl() correctness and that prefetchMedia() uses safe loading strategies (Image/link/fetch) and cleans up DOM entries.
  • Confirm prefetchObject() integration preserves existing error handling and does not introduce blocking behavior.

Possibly related PRs

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
Title Check ✅ Passed The PR title "feat: Add info panel options prefetchImage, prefetchVideo, prefetchAudio to pre-fetch media content in the info panel" directly and clearly summarizes the main changes in the pull request. The title uses the "feat:" conventional commit prefix, names the three specific new options being added, and concisely explains their purpose. The summary of changes confirms that the PR adds these three boolean options to the infoPanel configuration in both the README documentation and the code implementations (Browser.react.js and DataBrowser.react.js), making the title accurately representative of the primary change. The title is specific and descriptive enough that a teammate scanning commit history would understand the nature of this contribution.
Description Check ✅ Passed The PR description follows the repository's template structure and includes all major required sections: the New Pull Request Checklist is properly completed with both vulnerability and issue reference items checked, the Issue Description section provides a clear explanation of the problem (media content not being prefetched reduces prefetching effectiveness), the Approach section thoroughly describes the solution with details about the new options and their default behavior, and the TODOs section appropriately marks documentation updates as complete. While the "Closes: FILL_THIS_OUT" placeholder line from the template is not present in the description, this is a minor omission of a GitHub linking convention rather than a missing core section, and all substantive information is well-documented.

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.

@parseplatformorg
Copy link
Contributor

parseplatformorg commented Oct 29, 2025

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

Copy link

@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: 2

🧹 Nitpick comments (7)
README.md (4)

227-229: Clarify applicability and defaults interaction

Add an inline note that these media flags only take effect when prefetchObjects > 0, and that defaults of true are applied per panel if the keys are omitted. This avoids misinterpretation when users set them without enabling object prefetching.


1026-1030: Example looks good; optional brevity

LGTM. Optionally omit the three flags here to showcase that true is the default when keys are absent, keeping the example concise.


1330-1336: Document prefetch mechanism and limits

Briefly note the implementation detail that images are warmed via the browser cache and videos/audios may be warmed via background fetch, which can trigger cross-origin requests and bandwidth usage. Recommend adding a sentence about:

  • Potential additional network requests to third-party hosts.
  • That CORS/cache rules of the target host apply and prefetch may not always benefit playback.
  • How to disable per media type.

1340-1341: Add a security and privacy note

Consider adding a warning that prefetching remote media will contact the media host (leaking client IP, user agent, and possibly referrer), and suggest restricting media URLs to trusted domains. Link to any existing security section if available.

src/dashboard/Data/Browser/DataBrowser.react.js (2)

815-838: Deduplicate and sanitize media URLs before prefetch

Current extraction may prefetch duplicate or unsafe URLs (e.g., non-http(s)). Dedup and filter to http/https to reduce risk and noise.

Apply this diff:

-  extractMediaUrls(data) {
-    const urls = { images: [], videos: [], audios: [] };
+  extractMediaUrls(data) {
+    const images = new Set();
+    const videos = new Set();
+    const audios = new Set();
     if (!data?.panel?.segments) {
-      return urls;
+      return { images: [], videos: [], audios: [] };
     }
     data.panel.segments.forEach(segment => {
       if (segment.items) {
         segment.items.forEach(item => {
-          if (item.type === 'image' && item.url) {
-            urls.images.push(item.url);
-          } else if (item.type === 'video' && item.url) {
-            urls.videos.push(item.url);
-          } else if (item.type === 'audio' && item.url) {
-            urls.audios.push(item.url);
+          const u = item?.url;
+          if (!u) return;
+          if (!this.isSafeHttpUrl?.(u)) return;
+          if (item.type === 'image') {
+            images.add(u);
+          } else if (item.type === 'video') {
+            videos.add(u);
+          } else if (item.type === 'audio') {
+            audios.add(u);
           }
         });
       }
     });
-    return urls;
+    return {
+      images: Array.from(images),
+      videos: Array.from(videos),
+      audios: Array.from(audios),
+    };
   }

Add this helper near the class methods:

// Ensure only http(s) URLs are prefetched
isSafeHttpUrl(url) {
  try {
    const u = new URL(url, window.location.href);
    return u.protocol === 'http:' || u.protocol === 'https:';
  } catch {
    return false;
  }
}

883-897: Gate media prefetch and avoid duplicate work

Consider:

  • Gating media prefetch on this.state.isPanelVisible to avoid warming media for a hidden panel.
  • Skipping prefetch when no media flags are enabled to save cycles.
  • No need to wait on setState; prefetch calls can run before/after state update since they are independent.

Example tweak:

-  this.setState(prev => ({
+  this.setState(prev => ({
     prefetchCache: {
       ...prev.prefetchCache,
       [objectId]: { data: result, timestamp: Date.now() },
     },
   }));
-  // Prefetch media if enabled
-  const { prefetchImage, prefetchVideo, prefetchAudio } = this.getPrefetchSettings();
-  const mediaUrls = this.extractMediaUrls(result);
+  // Prefetch media if enabled and panel visible
+  const { prefetchImage, prefetchVideo, prefetchAudio } = this.getPrefetchSettings();
+  if (this.state.isPanelVisible && (prefetchImage || prefetchVideo || prefetchAudio)) {
+    const mediaUrls = this.extractMediaUrls(result);
     if (prefetchImage && mediaUrls.images.length > 0) {
       this.prefetchMedia(mediaUrls.images, 'image');
     }
     if (prefetchVideo && mediaUrls.videos.length > 0) {
       this.prefetchMedia(mediaUrls.videos, 'video');
     }
     if (prefetchAudio && mediaUrls.audios.length > 0) {
       this.prefetchMedia(mediaUrls.audios, 'audio');
     }
+  }
src/dashboard/Data/Browser/Browser.react.js (1)

468-471: Defaults applied consistently

Wiring prefetchImage/prefetchVideo/prefetchAudio with ?? true is consistent with DataBrowser settings. LGTM.

Optionally, centralize defaulting in a helper to avoid drift between files.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f83a975 and 8b5161f.

📒 Files selected for processing (3)
  • README.md (3 hunks)
  • src/dashboard/Data/Browser/Browser.react.js (1 hunks)
  • src/dashboard/Data/Browser/DataBrowser.react.js (3 hunks)
🧰 Additional context used
🪛 GitHub Check: Lint
src/dashboard/Data/Browser/DataBrowser.react.js

[failure] 855-855:
'error' is defined but never used

⏰ 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). (1)
  • GitHub Check: Docker linux/amd64
🔇 Additional comments (1)
src/dashboard/Data/Browser/DataBrowser.react.js (1)

771-774: Sane defaults wired correctly

Defaulting media flags with nullish coalescing is correct and consistent with panel mapping. LGTM.

Copy link

@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: 0

🧹 Nitpick comments (1)
src/dashboard/Data/Browser/DataBrowser.react.js (1)

848-873: Good progress on link-based prefetching; consider adding concurrency limiting.

The link element approach is significantly better than the previous fetch strategy. However, the previous review specifically requested a concurrency cap to avoid unbounded in-flight operations. With many media URLs, the current forEach creates all link elements at once, potentially overwhelming the browser.

Consider batching or rate-limiting link creation:

  prefetchMedia(urls, mediaType) {
    if (!urls || urls.size === 0) {
      return;
    }

+   // Limit concurrent prefetch operations
+   const MAX_CONCURRENT = 5;
+   const urlArray = Array.from(urls);
+   let index = 0;
+
+   const prefetchNext = () => {
+     if (index >= urlArray.length) return;
+     const url = urlArray[index++];
-   urls.forEach(url => {
      const link = document.createElement('link');
      link.rel = mediaType === 'image' ? 'preload' : 'prefetch';
      link.as = mediaType;
      link.href = url;

      link.onerror = () => {
        console.error(`Failed to prefetch ${mediaType}: ${url}`);
+       prefetchNext(); // Try next on error
      };

+     link.onload = () => {
+       prefetchNext(); // Try next on success
+     };

      document.head.appendChild(link);

      setTimeout(() => {
        if (link.parentNode) {
          link.parentNode.removeChild(link);
        }
      }, 30000);
-   });
+   };
+
+   // Start initial batch
+   for (let i = 0; i < Math.min(MAX_CONCURRENT, urlArray.length); i++) {
+     prefetchNext();
+   }
  }

Based on previous review comments.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 79b9801 and 3427d53.

📒 Files selected for processing (1)
  • src/dashboard/Data/Browser/DataBrowser.react.js (3 hunks)
⏰ 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). (1)
  • GitHub Check: Docker linux/amd64
🔇 Additional comments (4)
src/dashboard/Data/Browser/DataBrowser.react.js (4)

771-773: LGTM! Media prefetch flags integrate cleanly.

The new flags default to true and follow the existing pattern for prefetch settings. Users can selectively disable specific media types as needed.


815-822: LGTM! Safe URL validation prevents protocol-based exploits.

Restricting to HTTP/HTTPS protocols is appropriate for media prefetching and prevents potentially unsafe schemes.


824-846: LGTM! Media URL extraction is robust and defensive.

The method safely traverses the panel structure, validates URLs, and uses Sets to deduplicate, preventing redundant prefetch operations.


897-910: LGTM! Media prefetching integrates cleanly into the existing flow.

The conditional prefetching respects the per-media-type configuration and only triggers when URLs are present, maintaining consistency with the existing prefetch architecture.

coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 29, 2025
@mtrezza mtrezza merged commit 6796c9e into parse-community:alpha Oct 29, 2025
11 checks passed
@mtrezza mtrezza deleted the feat/add-media-prefetch branch October 29, 2025 11:26
parseplatformorg pushed a commit that referenced this pull request Oct 29, 2025
# [8.0.0-alpha.4](8.0.0-alpha.3...8.0.0-alpha.4) (2025-10-29)

### Features

* Add info panel options `prefetchImage`, `prefetchVideo`, `prefetchAudio` to pre-fetch media content in the info panel ([#3009](#3009)) ([6796c9e](6796c9e))
@parseplatformorg
Copy link
Contributor

🎉 This change has been released in version 8.0.0-alpha.4

@parseplatformorg parseplatformorg added the state:released-alpha Released as alpha version label Oct 29, 2025
parseplatformorg pushed a commit that referenced this pull request Nov 1, 2025
# [8.0.0](7.5.0...8.0.0) (2025-11-01)

### Bug Fixes

* Add missing major version increase of dashboard release ([#3005](#3005)) ([5debb4d](5debb4d))
* Cannot connect to server with error invalid header name ([#3006](#3006)) ([ea4ec07](ea4ec07))
* Currently displayed view reloads when editing and saving a different view ([#3002](#3002)) ([794a35a](794a35a))
* Dashboard config objects stored on server with public read / write access ([#2997](#2997)) ([31a4639](31a4639))
* ESC key does not cancel editing in data browser cell ([#3001](#3001)) ([d1d7241](d1d7241))
* Filter text field in data browser partly looses focus when hitting enter key to apply filter ([#2992](#2992)) ([e3085b9](e3085b9))
* Filter text field in data browser partly looses focus when selecting in drop-down element by hitting enter key to apply filter ([#2993](#2993)) ([f4c17c7](f4c17c7))
* Info panel briefly shows cached media content from previously selected cell when using pre-fetch ([#3008](#3008)) ([dd6a85e](dd6a85e))
* Missing alert when changing data browser browser data while rows are selected ([#2994](#2994)) ([6cabaa3](6cabaa3))
* Security upgrade parse from 3.5.1 to 7.0.1 ([#3003](#3003)) ([5123fbf](5123fbf))
* Security upgrade passport from 0.5.3 to 0.6.0 ([#3000](#3000)) ([fbb5e6d](fbb5e6d))
* Session management issue that causes malformed redirect URLs ([#3011](#3011)) ([1649dd3](1649dd3))
* Storing view on server creates view key with hashed view name instead of UUID ([#2995](#2995)) ([7cb65f3](7cb65f3))
* Switching between browser tabs can cause illegible text color for config parameter value field ([#3010](#3010)) ([77c5c67](77c5c67))
* View table data may be retained when switching between views ([#2996](#2996)) ([ddc91c9](ddc91c9))

### Features

* Add `matches regex` filter to data browser replacing limited `string contains string` filter ([#2991](#2991)) ([64a9f71](64a9f71))
* Add info panel options `prefetchImage`, `prefetchVideo`, `prefetchAudio` to pre-fetch media content in the info panel ([#3009](#3009)) ([6796c9e](6796c9e))
* Add Parse Server version compatibility detection ([#3004](#3004)) ([9a7a60f](9a7a60f))

### Performance Improvements

* Storing, deleting, modifying view in server storage now only affects the specific view instead of updating all views ([#2998](#2998)) ([48cea3c](48cea3c))

### BREAKING CHANGES

* This increases the required minimum version to Parse Server 7. ([5debb4d](5debb4d))
@parseplatformorg
Copy link
Contributor

🎉 This change has been released in version 8.0.0

@parseplatformorg parseplatformorg added the state:released Released as stable version label Nov 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state:released Released as stable version state:released-alpha Released as alpha version

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants