Files
ComfyUI_frontend/src/utils/loaderNodeUtil.ts
Jin Yi a4d979e4c9 [feat] Implement media asset workflow actions with shared utilities (#6696)
## Summary

Implements 4 missing media asset workflow features and creates shared
utilities to eliminate code duplication.

## Implemented Features

### 1. Copy Job ID 
- Properly extracts promptId using `getOutputAssetMetadata`
- Uses `useCopyToClipboard` composable

### 2. Add to Current Workflow 
- Adds LoadImage/LoadVideo/LoadAudio nodes to canvas
- Supports all media file types (JPEG, PNG, MP4, etc.)
- Auto-detects appropriate node type using `detectNodeTypeFromFilename`
utility

### 3. Open Workflow in New Tab 
- Extracts workflow from asset metadata or embedded PNG
- Opens workflow in new tab

### 4. Export Workflow 
- Exports workflow as JSON file
- Supports optional filename prompt

## Code Refactoring

### Created Shared Utilities:
1. **`assetTypeUtil.ts`** - `getAssetType()` function eliminates 6
instances of `asset.tags?.[0] || 'output'`
2. **`assetUrlUtil.ts`** - `getAssetUrl()` function consolidates 3 URL
construction patterns
3. **`workflowActionsService.ts`** - Shared service for workflow
export/open operations
4. **`workflowExtractionUtil.ts`** - Extract workflows from jobs/assets
5. **`loaderNodeUtil.ts`** - Detect loader node types from filenames

### Improvements to Existing Code:
- Refactored to use `formatUtil.getMediaTypeFromFilename()`
- Extracted `deleteAssetApi()` helper to reduce deletion logic
duplication (~40 lines)
- Moved `isResultItemType` type guard to shared `typeGuardUtil.ts`
- Added 9 i18n strings for proper localization
- Added `@comfyorg/shared-frontend-utils` dependency

## Input Assets Support

Improved input assets to support workflow features where applicable:
-  All media files (JPEG/PNG/MP4, etc.) → "Add to current workflow"
enabled
-  PNG/WEBP/FLAC with embedded metadata → "Open/Export workflow"
enabled

## Impact

- **~150+ lines** of duplicate code eliminated
- **5 new utility files** created to improve code reusability
- **11 files** changed, **483 insertions**, **234 deletions**

## Testing

 TypeScript typecheck passed  
 ESLint passed  
 Knip passed

🤖 Generated with [Claude Code](https://claude.com/claude-code)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6696-feat-Implement-media-asset-workflow-actions-with-shared-utilities-2ab6d73d365081fb8ae9d71ce6e38589)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: GitHub Action <action@github.com>
2025-11-18 00:04:45 +00:00

39 lines
1.4 KiB
TypeScript

/**
* Utilities for detecting and configuring loader nodes
* Used by both job menu and media asset actions to determine
* which loader node type to add to the canvas
*/
import { getMediaTypeFromFilename } from '@comfyorg/shared-frontend-utils/formatUtil'
/**
* Detect loader node type from filename extension
* Uses shared formatUtil for consistent file type detection across the codebase
*
* @param filename The filename to check
* @returns Object with nodeType and widgetName, or nulls if unsupported
*
* @example
* detectNodeTypeFromFilename('image.png') // { nodeType: 'LoadImage', widgetName: 'image' }
* detectNodeTypeFromFilename('video.mp4') // { nodeType: 'LoadVideo', widgetName: 'file' }
* detectNodeTypeFromFilename('audio.mp3') // { nodeType: 'LoadAudio', widgetName: 'audio' }
*/
export function detectNodeTypeFromFilename(filename: string): {
nodeType: 'LoadImage' | 'LoadVideo' | 'LoadAudio' | null
widgetName: 'image' | 'file' | 'audio' | null
} {
const mediaType = getMediaTypeFromFilename(filename)
switch (mediaType) {
case 'image':
return { nodeType: 'LoadImage', widgetName: 'image' }
case 'video':
return { nodeType: 'LoadVideo', widgetName: 'file' }
case 'audio':
return { nodeType: 'LoadAudio', widgetName: 'audio' }
default:
// 3D and other types don't have loader nodes
return { nodeType: null, widgetName: null }
}
}