Skip to content

feat(studio): Support image renders in fileset preview#770

Open
steramae-nvidia wants to merge 2 commits into
mainfrom
steramae/image-fileset-preview
Open

feat(studio): Support image renders in fileset preview#770
steramae-nvidia wants to merge 2 commits into
mainfrom
steramae/image-fileset-preview

Conversation

@steramae-nvidia

@steramae-nvidia steramae-nvidia commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Signed-off-by: Sean Teramae steramae@nvidia.com

Summary by CodeRabbit

  • New Features

    • Added image previews for supported dataset files, including loading, error, and unavailable-content states.
    • Image files now display as images instead of opening in the text editor.
    • Added recognition for common image formats, including PNG, JPG, SVG, and WebP.
  • Bug Fixes

    • Improved file and folder explorer icon layout to prevent icons from shrinking.
    • Updated the telemetry resource link to include a valid destination when enabled.
  • Tests

    • Added coverage for image detection, rendering, downloads, loading, and error handling.

Signed-off-by: Sean Teramae <steramae@nvidia.com>
Signed-off-by: Sean Teramae <steramae@nvidia.com>
@steramae-nvidia

Copy link
Copy Markdown
Contributor Author

This change is part of the following stack:

Change managed by git-spice.

@steramae-nvidia
steramae-nvidia requested review from a team as code owners July 17, 2026 20:23
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Image files are now detected through a shared extension registry and displayed with authenticated image previews. Related tests cover extension detection, rendering, download errors, and object URL cleanup. File icons receive shrink-resistant styling, and the telemetry resource link gains a hash href.

Changes

Image preview flow

Layer / File(s) Summary
Image extension contract
web/packages/studio/src/api/datasets/constants.ts, web/packages/studio/src/util/binaryFile.ts, web/packages/studio/src/util/binaryFile.test.ts
Image extensions are centralized, reused for binary detection, and covered by case-insensitive tests.
Preview content integration
web/packages/studio/src/components/FilesetFilePreviewPanel/FilesetFilePreviewContent/*
Image paths skip text fetching and render FilesetImagePreview; integration tests verify the image path replaces the code editor.
Authenticated image rendering
web/packages/studio/src/components/FilesetFilePreviewPanel/FilesetImagePreview.*
The preview downloads images, creates object URLs, handles loading and errors, and revokes URLs after loading.

File explorer icon sizing

Layer / File(s) Summary
Non-shrinking file icons
web/packages/studio/src/components/FilesetFilePreviewPanel/components/FilesetFilePreviewHeader/index.tsx, web/packages/studio/src/components/filesets/FilesetFileExplorer/useFilesetFileExplorerRows.tsx
Folder and file icons now use shrink-0 styling.

Telemetry resource link

Layer / File(s) Summary
Report a Trace link
web/packages/studio/src/routes/WorkspaceDashboardRoute/ResourcesSection.tsx
The telemetry-enabled resource item now includes href: '#'.

Suggested labels: feat

Sequence Diagram(s)

sequenceDiagram
  participant FilesetFilePreviewContent
  participant FilesetImagePreview
  participant useFilesDownloadFile
  participant BrowserImage
  FilesetFilePreviewContent->>FilesetImagePreview: render image preview props
  FilesetImagePreview->>useFilesDownloadFile: request file with object URL selection
  useFilesDownloadFile-->>FilesetImagePreview: image URL or error
  FilesetImagePreview->>BrowserImage: render image URL
  BrowserImage-->>FilesetImagePreview: load event
  FilesetImagePreview->>BrowserImage: revoke object URL
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Title matches the main change: adding image rendering support in the Studio fileset preview.
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 steramae/image-fileset-preview

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
`@web/packages/studio/src/components/FilesetFilePreviewPanel/FilesetImagePreview.tsx`:
- Around line 22-46: Update the ImagePreview component to add an effect cleanup
that calls the existing revokeImageUrl helper when the component unmounts, while
preserving the current load/error cleanup behavior. Add a test covering
unmounting before the image loads and verify that URL.revokeObjectURL is called.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 1a159ee4-7117-4a1f-bf05-cf349c615ca8

📥 Commits

Reviewing files that changed from the base of the PR and between f979b63 and 5ecf4c8.

📒 Files selected for processing (10)
  • web/packages/studio/src/api/datasets/constants.ts
  • web/packages/studio/src/components/FilesetFilePreviewPanel/FilesetFilePreviewContent/index.test.tsx
  • web/packages/studio/src/components/FilesetFilePreviewPanel/FilesetFilePreviewContent/index.tsx
  • web/packages/studio/src/components/FilesetFilePreviewPanel/FilesetImagePreview.test.tsx
  • web/packages/studio/src/components/FilesetFilePreviewPanel/FilesetImagePreview.tsx
  • web/packages/studio/src/components/FilesetFilePreviewPanel/components/FilesetFilePreviewHeader/index.tsx
  • web/packages/studio/src/components/filesets/FilesetFileExplorer/useFilesetFileExplorerRows.tsx
  • web/packages/studio/src/routes/WorkspaceDashboardRoute/ResourcesSection.tsx
  • web/packages/studio/src/util/binaryFile.test.ts
  • web/packages/studio/src/util/binaryFile.ts

Comment on lines +22 to +46
const ImagePreview: FC<ImagePreviewProps> = ({ imageUrl, filePath }) => {
const [imageLoadError, setImageLoadError] = useState(false);

const revokeImageUrl = () => URL.revokeObjectURL(imageUrl);

if (imageLoadError) {
return (
<Flex align="center" justify="center" className="h-full">
<Text className="text-danger-base">Error: Image could not be displayed.</Text>
</Flex>
);
}

return (
<Flex className="h-full items-center justify-center overflow-auto rounded-lg border border-base bg-surface-raised p-4">
<img
src={imageUrl}
alt={getFileName(filePath)}
className="max-h-full max-w-full object-contain"
onLoad={revokeImageUrl}
onError={() => {
revokeImageUrl();
setImageLoadError(true);
}}
/>

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 | 🟠 Major | ⚡ Quick win

Revoke the object URL when the preview unmounts.

Cleanup currently runs only on load/error. If the user changes files while the image is loading, the component unmounts and the blob URL remains allocated. Add an effect cleanup using the same idempotent revoke helper, and cover the unmount-before-load case in a test.

Proposed cleanup
-import { useState, type FC } from 'react';
+import { useCallback, useEffect, useState, type FC } from 'react';

   const [imageLoadError, setImageLoadError] = useState(false);

-  const revokeImageUrl = () => URL.revokeObjectURL(imageUrl);
+  const revokeImageUrl = useCallback(() => URL.revokeObjectURL(imageUrl), [imageUrl]);
+
+  useEffect(() => {
+    return () => revokeImageUrl();
+  }, [revokeImageUrl]);
📝 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
const ImagePreview: FC<ImagePreviewProps> = ({ imageUrl, filePath }) => {
const [imageLoadError, setImageLoadError] = useState(false);
const revokeImageUrl = () => URL.revokeObjectURL(imageUrl);
if (imageLoadError) {
return (
<Flex align="center" justify="center" className="h-full">
<Text className="text-danger-base">Error: Image could not be displayed.</Text>
</Flex>
);
}
return (
<Flex className="h-full items-center justify-center overflow-auto rounded-lg border border-base bg-surface-raised p-4">
<img
src={imageUrl}
alt={getFileName(filePath)}
className="max-h-full max-w-full object-contain"
onLoad={revokeImageUrl}
onError={() => {
revokeImageUrl();
setImageLoadError(true);
}}
/>
import { useCallback, useEffect, useState, type FC } from 'react';
const ImagePreview: FC<ImagePreviewProps> = ({ imageUrl, filePath }) => {
const [imageLoadError, setImageLoadError] = useState(false);
const revokeImageUrl = useCallback(() => URL.revokeObjectURL(imageUrl), [imageUrl]);
useEffect(() => {
return () => revokeImageUrl();
}, [revokeImageUrl]);
if (imageLoadError) {
return (
<Flex align="center" justify="center" className="h-full">
<Text className="text-danger-base">Error: Image could not be displayed.</Text>
</Flex>
);
}
return (
<Flex className="h-full items-center justify-center overflow-auto rounded-lg border border-base bg-surface-raised p-4">
<img
src={imageUrl}
alt={getFileName(filePath)}
className="max-h-full max-w-full object-contain"
onLoad={revokeImageUrl}
onError={() => {
revokeImageUrl();
setImageLoadError(true);
}}
/>
🤖 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
`@web/packages/studio/src/components/FilesetFilePreviewPanel/FilesetImagePreview.tsx`
around lines 22 - 46, Update the ImagePreview component to add an effect cleanup
that calls the existing revokeImageUrl helper when the component unmounts, while
preserving the current load/error cleanup behavior. Add a test covering
unmounting before the image loads and verify that URL.revokeObjectURL is called.

@github-actions github-actions Bot added the feat label Jul 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 25556/32773 78.0% 62.6%
Integration Tests 14747/31422 46.9% 19.2%

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant