mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-21 23:34:31 +00:00
[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>
This commit is contained in:
38
src/utils/loaderNodeUtil.ts
Normal file
38
src/utils/loaderNodeUtil.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* 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 }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user