Skip to content

Commit 91af228

Browse files
viva-jinyiclaude
andcommitted
[feat] Implement media asset workflow actions and refactor duplications
Implemented 4 missing workflow features for media assets: - copyJobId: Fixed to properly extract promptId from metadata - addWorkflow: Add loader nodes (LoadImage/LoadVideo/LoadAudio) to canvas - openWorkflow: Open workflow from asset metadata/embedded PNG in new tab - exportWorkflow: Export workflow as JSON file Created shared utilities to eliminate code duplication: - assetTypeUtil.ts: Extract asset type with fallback (replaced 6 duplications) - assetUrlUtil.ts: Construct asset URLs (replaced 3 duplications) - workflowActionsService.ts: Shared workflow export/open operations - workflowExtractionUtil.ts: Extract workflows from jobs/assets - loaderNodeUtil.ts: Detect loader node types from filenames Refactored existing code: - Used formatUtil.getMediaTypeFromFilename() in loaderNodeUtil - Extracted deleteAssetApi() helper to reduce deletion logic duplication - Moved isResultItemType type guard to shared typeGuardUtil.ts - Added 9 i18n strings for proper localization - Added @comfyorg/shared-frontend-utils dependency Input assets now support workflow features where applicable: - All media files (JPEG/PNG/MP4/etc) can be added to current workflow - PNG/WEBP/FLAC files with embedded metadata support open/export workflow 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 839e7c1 commit 91af228

File tree

11 files changed

+483
-234
lines changed

11 files changed

+483
-234
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@
131131
"@comfyorg/comfyui-electron-types": "0.4.73-0",
132132
"@comfyorg/design-system": "workspace:*",
133133
"@comfyorg/registry-types": "workspace:*",
134+
"@comfyorg/shared-frontend-utils": "workspace:*",
134135
"@comfyorg/tailwind-utils": "workspace:*",
135136
"@iconify/json": "catalog:",
136137
"@primeuix/forms": "catalog:",

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/locales/en/main.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2044,7 +2044,16 @@
20442044
"downloadsStarted": "Started downloading {count} file(s)",
20452045
"assetsDeletedSuccessfully": "{count} asset(s) deleted successfully",
20462046
"failedToDeleteAssets": "Failed to delete selected assets"
2047-
}
2047+
},
2048+
"noJobIdFound": "No job ID found for this asset",
2049+
"unsupportedFileType": "Unsupported file type for loader node",
2050+
"nodeTypeNotFound": "Node type {nodeType} not found",
2051+
"failedToCreateNode": "Failed to create node",
2052+
"nodeAddedToWorkflow": "{nodeType} node added to workflow",
2053+
"noWorkflowDataFound": "No workflow data found in this asset",
2054+
"workflowOpenedInNewTab": "Workflow opened in new tab",
2055+
"failedToExportWorkflow": "Failed to export workflow",
2056+
"workflowExportedSuccessfully": "Workflow exported successfully"
20482057
},
20492058
"actionbar": {
20502059
"dockToTop": "Dock to top",

src/platform/assets/components/MediaAssetMoreMenu.vue

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<template>
22
<div class="flex flex-col">
3+
<!-- TODO: 3D assets currently excluded from inspection.
4+
When 3D loader nodes are implemented, update detectNodeTypeFromFilename
5+
to return appropriate node type for .gltf, .glb files and remove this exclusion -->
36
<IconTextButton
47
v-if="asset?.kind !== '3D'"
58
type="transparent"
@@ -12,7 +15,7 @@
1215
</IconTextButton>
1316

1417
<IconTextButton
15-
v-if="showWorkflowOptions"
18+
v-if="showAddToWorkflow"
1619
type="transparent"
1720
label="Add to current workflow"
1821
@click="handleAddToWorkflow"
@@ -28,10 +31,10 @@
2831
</template>
2932
</IconTextButton>
3033

31-
<MediaAssetButtonDivider v-if="showWorkflowOptions" />
34+
<MediaAssetButtonDivider v-if="showAddToWorkflow || showWorkflowActions" />
3235

3336
<IconTextButton
34-
v-if="showWorkflowOptions"
37+
v-if="showWorkflowActions"
3538
type="transparent"
3639
label="Open as workflow in new tab"
3740
@click="handleOpenWorkflow"
@@ -42,7 +45,7 @@
4245
</IconTextButton>
4346

4447
<IconTextButton
45-
v-if="showWorkflowOptions"
48+
v-if="showWorkflowActions"
4649
type="transparent"
4750
label="Export workflow"
4851
@click="handleExportWorkflow"
@@ -52,7 +55,7 @@
5255
</template>
5356
</IconTextButton>
5457

55-
<MediaAssetButtonDivider v-if="showWorkflowOptions && showCopyJobId" />
58+
<MediaAssetButtonDivider v-if="showWorkflowActions && showCopyJobId" />
5659

5760
<IconTextButton
5861
v-if="showCopyJobId"
@@ -85,6 +88,8 @@ import { computed, inject } from 'vue'
8588
8689
import IconTextButton from '@/components/button/IconTextButton.vue'
8790
import { isCloud } from '@/platform/distribution/types'
91+
import { supportsWorkflowMetadata } from '@/platform/workflow/utils/workflowExtractionUtil'
92+
import { detectNodeTypeFromFilename } from '@/utils/loaderNodeUtil'
8893
8994
import { useMediaAssetActions } from '../composables/useMediaAssetActions'
9095
import { MediaAssetKey } from '../schemas/mediaAssetSchema'
@@ -107,7 +112,35 @@ const assetType = computed(() => {
107112
return asset.value?.tags?.[0] || context.value?.type || 'output'
108113
})
109114
110-
const showWorkflowOptions = computed(() => assetType.value === 'output')
115+
// Show "Add to current workflow" for all media files (images, videos, audio)
116+
// This works for any file type that has a corresponding loader node
117+
const showAddToWorkflow = computed(() => {
118+
// Output assets can always be added
119+
if (assetType.value === 'output') return true
120+
121+
// Input assets: check if file type is supported by loader nodes
122+
// Use the same utility as the actual addWorkflow function for consistency
123+
if (assetType.value === 'input' && asset.value?.name) {
124+
const { nodeType } = detectNodeTypeFromFilename(asset.value.name)
125+
return nodeType !== null
126+
}
127+
128+
return false
129+
})
130+
131+
// Show "Open/Export workflow" only for files with workflow metadata
132+
// This is more restrictive - only PNG, WEBP, FLAC support embedded workflows
133+
const showWorkflowActions = computed(() => {
134+
// Output assets always have workflow metadata
135+
if (assetType.value === 'output') return true
136+
137+
// Input assets: only formats that support workflow metadata
138+
if (assetType.value === 'input' && asset.value?.name) {
139+
return supportsWorkflowMetadata(asset.value.name)
140+
}
141+
142+
return false
143+
})
111144
112145
// Only show Copy Job ID for output assets (not for imported/input assets)
113146
const showCopyJobId = computed(() => {

0 commit comments

Comments
 (0)