Skip to content

Conversation

viva-jinyi
Copy link
Member

@viva-jinyi viva-jinyi commented Oct 1, 2025

Summary

Implements a comprehensive media asset card component system for the Asset Manager sidebar, enabling display and interaction with various media types (images, videos, audio, and 3D models).

Changes

New Components

  • MediaAssetCard: Main card component for displaying media assets
  • Media type-specific components: Specialized display logic for each media type
    • MediaImageTop/Bottom
    • MediaVideoTop/Bottom
    • MediaAudioTop/Bottom
    • Media3DTop/Bottom
  • MediaAssetActions: Top-left action buttons (delete, download, more options)
  • MediaAssetMoreMenu: Dropdown menu for additional actions
  • SquareChip: Chip component for displaying duration and file format with dark/light variants
  • MediaAssetButtonDivider: Visual separator for button groups

Features

  • Video playback: Autoplay with native video controls
    • Dynamic duration chip positioning based on control visibility
    • Hides overlays when video is playing
  • Audio playback: Audio icon with HTML5 audio element
    • Duration chip with consistent positioning
  • 3D model support: Icon display for 3D assets
  • Selection state: Proper hover and selected state handling with CSS priority fixes

Architecture Improvements

  • Domain-Driven Design structure: Organized under src/platform/mediaAsset/ following DDD principles
  • Provide/Inject pattern: Eliminates props drilling with MediaAssetKey InjectionKey
  • Composable pattern: useMediaAssetActions manages all action handlers
  • Type safety: Comprehensive TypeScript types for media assets and actions

UI/UX Enhancements

  • CardTop component: Added custom class props for slot positioning
  • SquareChip component: Backdrop blur effects with variant system
  • Lazy loading: Image optimization with LazyImage component
  • Responsive states: Loading, selected, and hover states

Utilities

  • formatDuration: Converts milliseconds to human-readable format (45s, 1m 23s, 1h 2m)

Testing

  • Comprehensive Storybook stories for all media types
  • Grid layout examples
  • Loading and selected state demonstrations

File Structure

src/platform/assets/
├── components/
│   ├── MediaAssetCard.vue
│   ├── MediaAssetCard.stories.ts
│   ├── MediaAssetActions.vue
│   ├── MediaAssetMoreMenu.vue
│   ├── MediaAssetButtonDivider.vue
│   ├── MediaImageTop.vue
│   ├── MediaImageBottom.vue
│   ├── MediaVideoTop.vue
│   ├── MediaVideoBottom.vue
│   ├── MediaAudioTop.vue
│   ├── MediaAudioBottom.vue
│   ├── Media3DTop.vue
│   └── Media3DBottom.vue
├── composables/
│   └── useMediaAssetActions.ts
└── schemas/
    └── mediaAssetSchema.ts

Screenshots

media_asset_record.webm

Copy link

github-actions bot commented Oct 1, 2025

🎨 Storybook Build Status

Build completed successfully!

⏰ Completed at: 10/11/2025, 11:17:19 AM UTC

🔗 Links


🎉 Your Storybook is ready for review!

Copy link

github-actions bot commented Oct 1, 2025

🎭 Playwright Test Results

⚠️ Tests passed with flaky tests

⏰ Completed at: 10/11/2025, 11:32:59 AM UTC

📈 Summary

  • Total Tests: 492
  • Passed: 458 ✅
  • Failed: 0
  • Flaky: 4 ⚠️
  • Skipped: 30 ⏭️

📊 Test Reports by Browser

  • chromium: View Report • ✅ 449 / ❌ 0 / ⚠️ 4 / ⏭️ 30
  • chromium-2x: View Report • ✅ 2 / ❌ 0 / ⚠️ 0 / ⏭️ 0
  • chromium-0.5x: View Report • ✅ 1 / ❌ 0 / ⚠️ 0 / ⏭️ 0
  • mobile-chrome: View Report • ✅ 6 / ❌ 0 / ⚠️ 0 / ⏭️ 0

🎉 Click on the links above to view detailed test results for each browser configuration.

Copy link

github-actions bot commented Oct 1, 2025

🔧 Auto-fixes Applied

This PR has been automatically updated to fix linting and formatting issues.

⚠️ Important: Your local branch is now behind. Run git pull before making additional changes to avoid conflicts.

Changes made:

  • ESLint auto-fixes
  • Prettier formatting

@christian-byrne christian-byrne added the claude-review Add to trigger a PR code review from Claude Code label Oct 3, 2025
>
<video
controls
autoplay
Copy link

Choose a reason for hiding this comment

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

[security] low Priority

Issue: Autoplay video without user consent
Context: Video autoplay can consume bandwidth, battery, and be accessibility unfriendly without explicit user consent
Suggestion: Remove autoplay or make it conditional based on user preferences/settings

Copy link

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Comprehensive PR Review

This review is generated by Claude. It may not always be accurate, as with human reviewers. If you believe that any of the comments are invalid or incorrect, please state why for each. For others, please implement the changes in one way or another.

Review Summary

PR: [Draft] Add QueueAssetCard presentation components (#5878)
Impact: 1499 additions, 0 deletions across 11 files

Issue Distribution

  • Critical: 1
  • High: 0
  • Medium: 6
  • Low: 3

Category Breakdown

  • Architecture: 2 issues
  • Security: 1 issues
  • Performance: 2 issues
  • Code Quality: 5 issues

Key Findings

Architecture & Design

The component architecture follows Vue 3 Composition API patterns well with proper type-specific card components. However, there's a critical import path issue that will cause build failures. The component mapping for 'pose' type needs reconsideration for semantic correctness.

Security Considerations

Video autoplay without user consent could impact bandwidth and accessibility. Consider implementing user preference controls.

Performance Impact

Hardcoded asset paths and inefficient video fallback chains may impact build optimization and runtime performance.

Integration Points

Missing event handler forwarding may break parent-child communication. The formatUtil import path mismatch is the most critical issue requiring immediate attention.

Positive Observations

  • Excellent use of TypeScript with proper type definitions
  • Good accessibility with ARIA labels and keyboard support
  • Consistent use of Tailwind utility classes following project guidelines
  • Comprehensive test coverage and Storybook stories
  • Proper component composition with clear separation of concerns
  • Good error and loading state handling

References

Next Steps

  1. Address critical import path issue before merge
  2. Fix missing event handler forwarding
  3. Extract duplicate formatDuration utility function
  4. Add i18n support for hardcoded text
  5. Consider accessibility improvements for keyboard navigation

This is a comprehensive automated review. For architectural decisions requiring human judgment, please request additional manual review.

Copy link

github-actions bot commented Oct 9, 2025

🔧 Auto-fixes Applied

This PR has been automatically updated to fix linting and formatting issues.

⚠️ Important: Your local branch is now behind. Run git pull before making additional changes to avoid conflicts.

Changes made:

  • ESLint auto-fixes
  • Prettier formatting

@viva-jinyi viva-jinyi changed the title [Draft] Add QueueAssetCard presentation components [Draft] Add AssetCard presentation components Oct 9, 2025
@viva-jinyi viva-jinyi marked this pull request as ready for review October 10, 2025 09:53
@dosubot dosubot bot added the size:XXL This PR changes 1000+ lines, ignoring generated files. label Oct 10, 2025
@Comfy-Org Comfy-Org deleted a comment from claude bot Oct 10, 2025
@viva-jinyi viva-jinyi added claude-review Add to trigger a PR code review from Claude Code New Browser Test Expectations New browser test screenshot should be set by github action and removed claude-review Add to trigger a PR code review from Claude Code labels Oct 10, 2025
Copy link

Updating Playwright Expectations

@viva-jinyi viva-jinyi added the claude-review Add to trigger a PR code review from Claude Code label Oct 10, 2025
@github-actions github-actions bot removed the New Browser Test Expectations New browser test screenshot should be set by github action label Oct 10, 2025
viva-jinyi and others added 18 commits October 11, 2025 20:14
  MediaAssetCard

  - Add shared state for video controls visibility between MediaAssetCard
   and MediaVideoTop
  - Show video controls by default and when video starts playing
  - Hide overlay elements (actions, zoom, duration chips, output count)
  during video playback
  - Extract overlay visibility conditions into computed properties for
  better maintainability
  - Update MediaAssetProviderValue type to include showVideoControls
  state
  - Emit control visibility changes from MediaVideoTop to parent
  component
  on code review

  - Replace double negative props (noBorder, noBackground, etc.)
  with positive boolean props (hasBorder, hasBackground, etc.) in
  CardContainer for better readability
  - Extract constant values outside of computed properties in
  CardContainer for performance
  - Update MoreButton to extend BaseButtonProps for type safety
  and add type prop support
  - Add ClassValue type import to LazyImage for proper class prop
  typing
  - Remove unused imports (onBeforeUnmount) from media card
  components
  - Update all Storybook stories to use new prop names
  - Convert CardTop getSlotClasses function to computed property
  for better performance
  - Extract SquareChip constants outside computed property
  - Refactor useMediaAssetActions from emit pattern to direct
  composable pattern
  - Remove redundant MediaAssetEmits type and MediaAssetActions
  interface
  platform/assets with Zod schemas

  - Move MediaAsset components from /mediaAsset
  to /assets directory
  - Replace interface-based types with Zod
  schemas for runtime validation
  - Extend existing assetItemSchema instead of
  duplicating fields
  - Add assetContextSchema for type-safe context
   handling
  - Leverage existing AssetItem fields
  (preview_url, created_at, tags)
  - Remove redundant fields (thumbnailUrl →
  preview_url, timestamp → created_at)
@viva-jinyi
Copy link
Member Author

@christian-byrne @arjansingh I’ve revised almost everything based on the review.
For the comments I marked as “resolved” without adding a reply — those were issues I already fixed elsewhere while addressing similar feedback in other parts of the code.
For the areas that didn’t require changes, I left explanatory comments instead.

Copy link
Contributor

@christian-byrne christian-byrne left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@arjansingh arjansingh left a comment

Choose a reason for hiding this comment

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

I have some questions and follow up requests (see comments) but we can merge this. Approved!


// Asset context schema
const zAssetContextSchema = z.object({
type: z.enum(['input', 'output']),
Copy link
Contributor

Choose a reason for hiding this comment

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

comment: FYI for future work, the types are going to come as asset tags.
The openapi schema for assets is here.

as you continue to develop, you probably should standardize your types around the records the API is returning.

Comment on lines +16 to +24
// New required fields
kind: zMediaKindSchema,
src: z.string().url(),

// New optional fields
duration: z.number().nonnegative().optional(),
dimensions: zDimensionsSchema.optional(),
jobId: z.string().optional(),
isMulti: z.boolean().optional()
Copy link
Contributor

Choose a reason for hiding this comment

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

question: where is this data going to be coming from?


const { context, asset, loading, selected } = defineProps<{
context: AssetContext
asset?: AssetMeta
Copy link
Contributor

Choose a reason for hiding this comment

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

Follow Up:

To avoid confusion this should be renamed assetMeta.

asset conventionally refers to full record from the API. See here.

Comment on lines +227 to +237
{
id: 'grid-1',
name: 'image-file.jpg',
kind: 'image',
size: 2097152,
duration: 4500,
created_at: Date.now().toString(),
src: SAMPLE_MEDIA.image1,
dimensions: { width: 1920, height: 1080 },
tags: []
},
Copy link
Contributor

Choose a reason for hiding this comment

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

Where is this data coming from?

Comment on lines +40 to +42
if (asset.value) {
actions.deleteAsset(asset.value.id)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

nit:

Suggested change
if (asset.value) {
actions.deleteAsset(asset.value.id)
}
if (!asset.value) return
actions.deleteAsset(asset.value.id)

Comment on lines +46 to +48
if (asset.value) {
actions.downloadAsset(asset.value.id)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

nit:

Suggested change
if (asset.value) {
actions.downloadAsset(asset.value.id)
}
if (!asset.value) return
actions.downloadAsset(asset.value.id)

Comment on lines +229 to +231
if (asset) {
actions.selectAsset(asset)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

nit:

Suggested change
if (asset) {
actions.selectAsset(asset)
}
if (!asset) return
actions.selectAsset(asset)

@arjansingh arjansingh merged commit 9c0b3c4 into main Oct 11, 2025
26 checks passed
@arjansingh arjansingh deleted the feature/asset-card branch October 11, 2025 21:39
arjansingh pushed a commit that referenced this pull request Oct 12, 2025
## Summary

Implements a comprehensive media asset card component system for the
Asset Manager sidebar, enabling display and interaction with various
media types (images, videos, audio, and 3D models).

## Changes

### New Components
- **MediaAssetCard**: Main card component for displaying media assets
- **Media type-specific components**: Specialized display logic for each
media type
  - MediaImageTop/Bottom
  - MediaVideoTop/Bottom  
  - MediaAudioTop/Bottom
  - Media3DTop/Bottom
- **MediaAssetActions**: Top-left action buttons (delete, download, more
options)
- **MediaAssetMoreMenu**: Dropdown menu for additional actions
- **SquareChip**: Chip component for displaying duration and file format
with dark/light variants
- **MediaAssetButtonDivider**: Visual separator for button groups

### Features
- **Video playback**: Autoplay with native video controls
  - Dynamic duration chip positioning based on control visibility
  - Hides overlays when video is playing
- **Audio playback**: Audio icon with HTML5 audio element
  - Duration chip with consistent positioning
- **3D model support**: Icon display for 3D assets
- **Selection state**: Proper hover and selected state handling with CSS
priority fixes

### Architecture Improvements
- **Domain-Driven Design structure**: Organized under
`src/platform/mediaAsset/` following DDD principles
- **Provide/Inject pattern**: Eliminates props drilling with
MediaAssetKey InjectionKey
- **Composable pattern**: `useMediaAssetActions` manages all action
handlers
- **Type safety**: Comprehensive TypeScript types for media assets and
actions

### UI/UX Enhancements
- **CardTop component**: Added custom class props for slot positioning
- **SquareChip component**: Backdrop blur effects with variant system
- **Lazy loading**: Image optimization with LazyImage component
- **Responsive states**: Loading, selected, and hover states

### Utilities
- **formatDuration**: Converts milliseconds to human-readable format
(45s, 1m 23s, 1h 2m)

## Testing
- Comprehensive Storybook stories for all media types
- Grid layout examples
- Loading and selected state demonstrations

## File Structure
```
src/platform/assets/
├── components/
│   ├── MediaAssetCard.vue
│   ├── MediaAssetCard.stories.ts
│   ├── MediaAssetActions.vue
│   ├── MediaAssetMoreMenu.vue
│   ├── MediaAssetButtonDivider.vue
│   ├── MediaImageTop.vue
│   ├── MediaImageBottom.vue
│   ├── MediaVideoTop.vue
│   ├── MediaVideoBottom.vue
│   ├── MediaAudioTop.vue
│   ├── MediaAudioBottom.vue
│   ├── Media3DTop.vue
│   └── Media3DBottom.vue
├── composables/
│   └── useMediaAssetActions.ts
└── schemas/
    └── mediaAssetSchema.ts
```

## Screenshots

[media_asset_record.webm](https://github.com/user-attachments/assets/d13b5cc0-a262-4850-bb81-ca1daa0dd969)

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: GitHub Action <[email protected]>
Co-authored-by: github-actions <[email protected]>
arjansingh pushed a commit that referenced this pull request Oct 13, 2025
## Summary

Implements a comprehensive media asset card component system for the
Asset Manager sidebar, enabling display and interaction with various
media types (images, videos, audio, and 3D models).

## Changes

### New Components
- **MediaAssetCard**: Main card component for displaying media assets
- **Media type-specific components**: Specialized display logic for each
media type
  - MediaImageTop/Bottom
  - MediaVideoTop/Bottom  
  - MediaAudioTop/Bottom
  - Media3DTop/Bottom
- **MediaAssetActions**: Top-left action buttons (delete, download, more
options)
- **MediaAssetMoreMenu**: Dropdown menu for additional actions
- **SquareChip**: Chip component for displaying duration and file format
with dark/light variants
- **MediaAssetButtonDivider**: Visual separator for button groups

### Features
- **Video playback**: Autoplay with native video controls
  - Dynamic duration chip positioning based on control visibility
  - Hides overlays when video is playing
- **Audio playback**: Audio icon with HTML5 audio element
  - Duration chip with consistent positioning
- **3D model support**: Icon display for 3D assets
- **Selection state**: Proper hover and selected state handling with CSS
priority fixes

### Architecture Improvements
- **Domain-Driven Design structure**: Organized under
`src/platform/mediaAsset/` following DDD principles
- **Provide/Inject pattern**: Eliminates props drilling with
MediaAssetKey InjectionKey
- **Composable pattern**: `useMediaAssetActions` manages all action
handlers
- **Type safety**: Comprehensive TypeScript types for media assets and
actions

### UI/UX Enhancements
- **CardTop component**: Added custom class props for slot positioning
- **SquareChip component**: Backdrop blur effects with variant system
- **Lazy loading**: Image optimization with LazyImage component
- **Responsive states**: Loading, selected, and hover states

### Utilities
- **formatDuration**: Converts milliseconds to human-readable format
(45s, 1m 23s, 1h 2m)

## Testing
- Comprehensive Storybook stories for all media types
- Grid layout examples
- Loading and selected state demonstrations

## File Structure
```
src/platform/assets/
├── components/
│   ├── MediaAssetCard.vue
│   ├── MediaAssetCard.stories.ts
│   ├── MediaAssetActions.vue
│   ├── MediaAssetMoreMenu.vue
│   ├── MediaAssetButtonDivider.vue
│   ├── MediaImageTop.vue
│   ├── MediaImageBottom.vue
│   ├── MediaVideoTop.vue
│   ├── MediaVideoBottom.vue
│   ├── MediaAudioTop.vue
│   ├── MediaAudioBottom.vue
│   ├── Media3DTop.vue
│   └── Media3DBottom.vue
├── composables/
│   └── useMediaAssetActions.ts
└── schemas/
    └── mediaAssetSchema.ts
```

## Screenshots

[media_asset_record.webm](https://github.com/user-attachments/assets/d13b5cc0-a262-4850-bb81-ca1daa0dd969)

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: GitHub Action <[email protected]>
Co-authored-by: github-actions <[email protected]>
@arjansingh arjansingh mentioned this pull request Oct 14, 2025
arjansingh added a commit that referenced this pull request Oct 14, 2025
## What's Changed

### 🚀 Features
- Add MediaAssetCard presentation components (#5878)
- Make Vue nodes' outputs/previews responsively sized and work with node
resizing (#5970)
- Allow connection to subgraphIOs in vue mode (#6016)
- Add distribution detection pattern (#6028)
- Make nodeData.widgets reactive (#6019)

### 🐛 Bug Fixes
- Fix FLOAT widget incrementing broken & disabled state styles on widget
number input (Vue) (#6036)
- Fix Vue node border styles in different states (executing, error,
selected) (#6018)
- Fix Vue node opacity conditions (user node opacity, bypass state,
muted state) (#6022)
- Fix: emit layout change for batch node bounds (#5939)
- Safer restoration of widgets_values on subgraph nodes (#6015)
- Fix(execution): reset progress state after runs to unfreeze tab
title/favicon (main) (#6026)
- Use type check instead of cast (#6041)

### 🎨 Style & Design
- [style] match widget border/outline styles with designs (#6021)
- [style] make Vue widget/slot/label width and spacing align with
designs (#6023)

### ♿ Accessibility
- Add aria labels on vue node widgets (#6032)

### 🔧 Maintenance
- [refactor] adjust Vue node fixtures to not be coupled to Litegraph
(#6033)
- [refactor] reorganize devtools test nodes into modules (#6020)

### 🧪 Testing
- [test] add browser test for control+a selection of Vue nodes (#6031)

### 🔄 CI/CD
- [ci] fix update locales workflow (#6017)

**Full Changelog**:
v1.29.1...v1.29.2

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6045-1-29-2-28c6d73d3650817a8c36fba944ce69a8)
by [Unito](https://www.unito.io)

---------

Co-authored-by: arjansingh <[email protected]>
Co-authored-by: github-actions <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:assets area:ui General user interface and experience improvements size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants