Skip to content

Conversation

@viva-jinyi
Copy link
Member

@viva-jinyi viva-jinyi commented Nov 14, 2025

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

┆Issue is synchronized with this Notion page by Unito

@github-actions
Copy link

github-actions bot commented Nov 14, 2025

🎨 Storybook Build Status

Build completed successfully!

⏰ Completed at: 11/17/2025, 11:56:30 PM UTC

🔗 Links


🎉 Your Storybook is ready for review!

@github-actions
Copy link

github-actions bot commented Nov 14, 2025

🎭 Playwright Test Results

⚠️ Tests passed with flaky tests

⏰ Completed at: 11/18/2025, 12:06:19 AM UTC

📈 Summary

  • Total Tests: 496
  • Passed: 463 ✅
  • Failed: 0
  • Flaky: 3 ⚠️
  • Skipped: 30 ⏭️

📊 Test Reports by Browser

  • chromium: View Report • ✅ 454 / ❌ 0 / ⚠️ 3 / ⏭️ 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.

@viva-jinyi viva-jinyi force-pushed the feature/media-asset-action branch from 7430819 to 91af228 Compare November 14, 2025 05:54
@socket-security
Copy link

socket-security bot commented Nov 14, 2025

No dependency changes detected. Learn more about Socket for GitHub.

👍 No dependency changes detected in pull request

@github-actions
Copy link

github-actions bot commented Nov 14, 2025

Bundle Size Report

Summary

  • Raw size: 13.7 MB baseline 13.6 MB — 🔴 +8.37 kB
  • Gzip: 2.75 MB baseline 2.74 MB — 🔴 +1.81 kB
  • Brotli: 2.16 MB baseline 2.16 MB — 🔴 +867 B
  • Bundles: 97 current • 97 baseline • 45 added / 45 removed

Category Glance
App Entry Points 🔴 +8.37 kB (3.14 MB) · Vendor & Third-Party ⚪ 0 B (5.32 MB) · Other ⚪ 0 B (3.94 MB) · Graph Workspace ⚪ 0 B (789 kB) · Panels & Settings ⚪ 0 B (307 kB) · UI Components ⚪ 0 B (136 kB) · + 3 more

Per-category breakdown
App Entry Points — 3.14 MB (baseline 3.13 MB) • 🔴 +8.37 kB

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-CWo7AMMz.js (new) 2.77 MB 🔴 +2.77 MB 🔴 +577 kB 🔴 +438 kB
assets/index-DOXpOse5.js (removed) 2.76 MB 🟢 -2.76 MB 🟢 -575 kB 🟢 -437 kB
assets/index-B7JFThGD.js (removed) 364 kB 🟢 -364 kB 🟢 -75.2 kB 🟢 -61.4 kB
assets/index-DYjpc3v6.js (new) 364 kB 🔴 +364 kB 🔴 +75.2 kB 🔴 +61.3 kB
assets/index-4flSADMs.js (removed) 345 B 🟢 -345 B 🟢 -245 B 🟢 -235 B
assets/index-DaV-51f_.js (new) 345 B 🔴 +345 B 🔴 +246 B 🔴 +234 B

Status: 3 added / 3 removed

Graph Workspace — 789 kB (baseline 789 kB) • ⚪ 0 B

Graph editor runtime, canvas, workflow orchestration

File Before After Δ Raw Δ Gzip Δ Brotli
assets/GraphView-DdseHHtb.js (removed) 789 kB 🟢 -789 kB 🟢 -155 kB 🟢 -119 kB
assets/GraphView-DiuKRp5M.js (new) 789 kB 🔴 +789 kB 🔴 +155 kB 🔴 +119 kB

Status: 1 added / 1 removed

Views & Navigation — 8.03 kB (baseline 8.03 kB) • ⚪ 0 B

Top-level views, pages, and routed surfaces

File Before After Δ Raw Δ Gzip Δ Brotli
assets/UserSelectView-CnSc9MNV.js (removed) 8.03 kB 🟢 -8.03 kB 🟢 -2.45 kB 🟢 -2.15 kB
assets/UserSelectView-DCY4gUaS.js (new) 8.03 kB 🔴 +8.03 kB 🔴 +2.45 kB 🔴 +2.15 kB

Status: 1 added / 1 removed

Panels & Settings — 307 kB (baseline 307 kB) • ⚪ 0 B

Configuration panels, inspectors, and settings screens

File Before After Δ Raw Δ Gzip Δ Brotli
assets/CreditsPanel-C9RU0QRz.js (new) 23 kB 🔴 +23 kB 🔴 +5.47 kB 🔴 +4.78 kB
assets/CreditsPanel-CWtutUxD.js (removed) 23 kB 🟢 -23 kB 🟢 -5.47 kB 🟢 -4.79 kB
assets/KeybindingPanel-B-iElWvC.js (removed) 15.1 kB 🟢 -15.1 kB 🟢 -3.74 kB 🟢 -3.29 kB
assets/KeybindingPanel-tV7vF0O1.js (new) 15.1 kB 🔴 +15.1 kB 🔴 +3.75 kB 🔴 +3.3 kB
assets/ExtensionPanel-D7yDu_PO.js (removed) 12 kB 🟢 -12 kB 🟢 -2.81 kB 🟢 -2.46 kB
assets/ExtensionPanel-DHWsLmhO.js (new) 12 kB 🔴 +12 kB 🔴 +2.81 kB 🔴 +2.46 kB
assets/AboutPanel-D0domTaV.js (new) 10.2 kB 🔴 +10.2 kB 🔴 +2.64 kB 🔴 +2.32 kB
assets/AboutPanel-DrwG8pMm.js (removed) 10.2 kB 🟢 -10.2 kB 🟢 -2.64 kB 🟢 -2.32 kB
assets/ServerConfigPanel-DFE6a_Bh.js (removed) 8.09 kB 🟢 -8.09 kB 🟢 -2.14 kB 🟢 -1.89 kB
assets/ServerConfigPanel-DJEZLt9k.js (new) 8.09 kB 🔴 +8.09 kB 🔴 +2.14 kB 🔴 +1.89 kB
assets/UserPanel-CBn-J7xc.js (removed) 7.8 kB 🟢 -7.8 kB 🟢 -2.04 kB 🟢 -1.78 kB
assets/UserPanel-M7GvcjVq.js (new) 7.8 kB 🔴 +7.8 kB 🔴 +2.04 kB 🔴 +1.78 kB
assets/settings-BXTtSH4O.js 33.3 kB 33.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-C9Pzn-NG.js 25.2 kB 25.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CCy2fA_h.js 27.3 kB 27.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CQpqEFfl.js 26.6 kB 26.6 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-DHcnxypw.js 21.7 kB 21.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-DhFTK9fY.js 25.1 kB 25.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-DlT4t_ui.js 25.9 kB 25.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-DRgSrIdD.js 24.2 kB 24.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-tjkeqiZq.js 21.1 kB 21.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 6 added / 6 removed

UI Components — 136 kB (baseline 136 kB) • ⚪ 0 B

Reusable component library chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/Load3D.vue_vue_type_script_setup_true_lang-02Ryjtkq.js (new) 53.9 kB 🔴 +53.9 kB 🔴 +8.43 kB 🔴 +7.24 kB
assets/Load3D.vue_vue_type_script_setup_true_lang-Bd-JY5Jv.js (removed) 53.9 kB 🟢 -53.9 kB 🟢 -8.43 kB 🟢 -7.25 kB
assets/WidgetSelect.vue_vue_type_script_setup_true_lang-1mtPmj5E.js (new) 48.1 kB 🔴 +48.1 kB 🔴 +10.4 kB 🔴 +8.98 kB
assets/WidgetSelect.vue_vue_type_script_setup_true_lang-wxBBuyQH.js (removed) 48.1 kB 🟢 -48.1 kB 🟢 -10.4 kB 🟢 -8.99 kB
assets/ComfyQueueButton-ApQOgdpO.js (removed) 11.2 kB 🟢 -11.2 kB 🟢 -2.8 kB 🟢 -2.47 kB
assets/ComfyQueueButton-BgPLq9s5.js (new) 11.2 kB 🔴 +11.2 kB 🔴 +2.8 kB 🔴 +2.47 kB
assets/WidgetSelectButton-B4hOLyf1.js (new) 6.59 kB 🔴 +6.59 kB 🔴 +1.96 kB 🔴 +1.72 kB
assets/WidgetSelectButton-CcUXD0Mp.js (removed) 6.59 kB 🟢 -6.59 kB 🟢 -1.95 kB 🟢 -1.71 kB
assets/WidgetLayoutField.vue_vue_type_script_setup_true_lang-BQnlPUxV.js (new) 2.16 kB 🔴 +2.16 kB 🔴 +811 B 🔴 +703 B
assets/WidgetLayoutField.vue_vue_type_script_setup_true_lang-BUcUG4vu.js (removed) 2.16 kB 🟢 -2.16 kB 🟢 -811 B 🟢 -709 B
assets/MediaTitle.vue_vue_type_script_setup_true_lang-5meadRgq.js (removed) 848 B 🟢 -848 B 🟢 -473 B 🟢 -412 B
assets/MediaTitle.vue_vue_type_script_setup_true_lang-Ck9NuSjE.js (new) 848 B 🔴 +848 B 🔴 +476 B 🔴 +415 B
assets/LazyImage.vue_vue_type_script_setup_true_lang-Wi-CcgaU.js 10.7 kB 10.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/UserAvatar.vue_vue_type_script_setup_true_lang-D2s8tnS2.js 1.26 kB 1.26 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetButton-ByrPd5jr.js 1.62 kB 1.62 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 6 added / 6 removed

Data & Services — 12.6 kB (baseline 12.6 kB) • ⚪ 0 B

Stores, services, APIs, and repositories

File Before After Δ Raw Δ Gzip Δ Brotli
assets/keybindingService-BMbpYGon.js (removed) 7.6 kB 🟢 -7.6 kB 🟢 -1.84 kB 🟢 -1.59 kB
assets/keybindingService-DYw1WkEB.js (new) 7.6 kB 🔴 +7.6 kB 🔴 +1.85 kB 🔴 +1.59 kB
assets/serverConfigStore-B-x6001d.js (new) 2.79 kB 🔴 +2.79 kB 🔴 +891 B 🔴 +773 B
assets/serverConfigStore-Ck2njjuK.js (removed) 2.79 kB 🟢 -2.79 kB 🟢 -890 B 🟢 -775 B
assets/audioService-D3Ve237a.js (removed) 2.2 kB 🟢 -2.2 kB 🟢 -961 B 🟢 -823 B
assets/audioService-k3DO7STT.js (new) 2.2 kB 🔴 +2.2 kB 🔴 +962 B 🔴 +824 B

Status: 3 added / 3 removed

Utilities & Hooks — 5.87 kB (baseline 5.87 kB) • ⚪ 0 B

Helpers, composables, and utility bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/audioUtils-DbTmzYLV.js (new) 1.41 kB 🔴 +1.41 kB 🔴 +652 B 🔴 +546 B
assets/audioUtils-DqZ6Dr5V.js (removed) 1.41 kB 🟢 -1.41 kB 🟢 -651 B 🟢 -548 B
assets/mathUtil-CTARWQ-l.js 1.07 kB 1.07 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeFilterUtil-CXKCRJ-m.js 460 B 460 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/useTransformCompatOverlayProps-YaCpDdzr.js 486 B 486 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/useWidgetValue-IC6pgigJ.js 2.45 kB 2.45 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 1 added / 1 removed

Vendor & Third-Party — 5.32 MB (baseline 5.32 MB) • ⚪ 0 B

External libraries and shared vendor chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/vendor-other-6R86j2Wt.js (new) 3.22 MB 🔴 +3.22 MB 🔴 +685 kB 🔴 +549 kB
assets/vendor-other-BAd7J_3K.js (removed) 3.22 MB 🟢 -3.22 MB 🟢 -685 kB 🟢 -549 kB
assets/vendor-tiptap-CL1pw3Mp.js (removed) 232 kB 🟢 -232 kB 🟢 -45.7 kB 🟢 -37.7 kB
assets/vendor-tiptap-CSqz1Oiv.js (new) 232 kB 🔴 +232 kB 🔴 +45.7 kB 🔴 +37.7 kB
assets/vendor-vue-2hzdqNpF.js (removed) 92.6 kB 🟢 -92.6 kB 🟢 -23.9 kB 🟢 -20.8 kB
assets/vendor-vue-Cp6hwTh6.js (new) 92.6 kB 🔴 +92.6 kB 🔴 +23.9 kB 🔴 +20.8 kB
assets/vendor-primevue-PESgPnbc.js 517 B 517 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-three-aR6ntw5X.js 1.37 MB 1.37 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-xterm-BZLod3g9.js 407 kB 407 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 3 added / 3 removed

Other — 3.94 MB (baseline 3.94 MB) • ⚪ 0 B

Bundles that do not match a named category

File Before After Δ Raw Δ Gzip Δ Brotli
assets/WidgetRecordAudio-CSUxhfhm.js (removed) 22.1 kB 🟢 -22.1 kB 🟢 -5.57 kB 🟢 -4.92 kB
assets/WidgetRecordAudio-DkuXKCTa.js (new) 22.1 kB 🔴 +22.1 kB 🔴 +5.57 kB 🔴 +4.92 kB
assets/AudioPreviewPlayer-C7zOsbPq.js (new) 15 kB 🔴 +15 kB 🔴 +3.7 kB 🔴 +3.31 kB
assets/AudioPreviewPlayer-YxLJ40--.js (removed) 15 kB 🟢 -15 kB 🟢 -3.7 kB 🟢 -3.31 kB
assets/WidgetInputNumber-CCVNVfAI.js (new) 14.6 kB 🔴 +14.6 kB 🔴 +3.79 kB 🔴 +3.36 kB
assets/WidgetInputNumber-DtCcygpd.js (removed) 14.6 kB 🟢 -14.6 kB 🟢 -3.79 kB 🟢 -3.35 kB
assets/WidgetGalleria-B955RagP.js (removed) 5.62 kB 🟢 -5.62 kB 🟢 -1.76 kB 🟢 -1.55 kB
assets/WidgetGalleria-I9N7iLXA.js (new) 5.62 kB 🔴 +5.62 kB 🔴 +1.76 kB 🔴 +1.55 kB
assets/WidgetColorPicker-BY374V7e.js (removed) 4.91 kB 🟢 -4.91 kB 🟢 -1.69 kB 🟢 -1.48 kB
assets/WidgetColorPicker-DHXCa64j.js (new) 4.91 kB 🔴 +4.91 kB 🔴 +1.69 kB 🔴 +1.47 kB
assets/WidgetMarkdown-PaXMN5FS.js (new) 4.88 kB 🔴 +4.88 kB 🔴 +1.71 kB 🔴 +1.47 kB
assets/WidgetMarkdown-uJIhjJVn.js (removed) 4.88 kB 🟢 -4.88 kB 🟢 -1.7 kB 🟢 -1.47 kB
assets/WidgetAudioUI-Ce2N5LGN.js (new) 4.49 kB 🔴 +4.49 kB 🔴 +1.5 kB 🔴 +1.34 kB
assets/WidgetAudioUI-D-xUDOJb.js (removed) 4.49 kB 🟢 -4.49 kB 🟢 -1.5 kB 🟢 -1.34 kB
assets/WidgetMultiSelect-BAY907nE.js (new) 4.3 kB 🔴 +4.3 kB 🔴 +1.46 kB 🔴 +1.27 kB
assets/WidgetMultiSelect-MppY0eTN.js (removed) 4.3 kB 🟢 -4.3 kB 🟢 -1.46 kB 🟢 -1.27 kB
assets/WidgetTreeSelect-BwbAqMSF.js (removed) 4.03 kB 🟢 -4.03 kB 🟢 -1.38 kB 🟢 -1.21 kB
assets/WidgetTreeSelect-dVM3hlgk.js (new) 4.03 kB 🔴 +4.03 kB 🔴 +1.38 kB 🔴 +1.21 kB
assets/WidgetTextarea-CZ5dP1eo.js (removed) 3.74 kB 🟢 -3.74 kB 🟢 -1.3 kB 🟢 -1.14 kB
assets/WidgetTextarea-DXA40-Q_.js (new) 3.74 kB 🔴 +3.74 kB 🔴 +1.3 kB 🔴 +1.14 kB
assets/WidgetInputText-CxUJrriE.js (new) 3.66 kB 🔴 +3.66 kB 🔴 +1.28 kB 🔴 +1.12 kB
assets/WidgetInputText-DWWz-N8R.js (removed) 3.66 kB 🟢 -3.66 kB 🟢 -1.28 kB 🟢 -1.13 kB
assets/WidgetToggleSwitch-BTFhhBYL.js (new) 3.52 kB 🔴 +3.52 kB 🔴 +1.23 kB 🔴 +1.09 kB
assets/WidgetToggleSwitch-cBgJbNXi.js (removed) 3.52 kB 🟢 -3.52 kB 🟢 -1.22 kB 🟢 -1.07 kB
assets/MediaImageBottom-f4bFY8Pl.js (new) 3.11 kB 🔴 +3.11 kB 🔴 +1.07 kB 🔴 +921 B
assets/MediaImageBottom-O7FoICQy.js (removed) 3.11 kB 🟢 -3.11 kB 🟢 -1.07 kB 🟢 -945 B
assets/MediaAudioBottom-DcMJNEBv.js (removed) 3.06 kB 🟢 -3.06 kB 🟢 -1.06 kB 🟢 -955 B
assets/MediaAudioBottom-DwInxUoe.js (new) 3.06 kB 🔴 +3.06 kB 🔴 +1.06 kB 🔴 +937 B
assets/MediaVideoBottom-CogfY6m-.js (new) 3.06 kB 🔴 +3.06 kB 🔴 +1.06 kB 🔴 +924 B
assets/MediaVideoBottom-CXsjJzGN.js (removed) 3.06 kB 🟢 -3.06 kB 🟢 -1.06 kB 🟢 -945 B
assets/Media3DBottom-BRc2t_Fj.js (removed) 3.04 kB 🟢 -3.04 kB 🟢 -1.05 kB 🟢 -939 B
assets/Media3DBottom-CoANfF5X.js (new) 3.04 kB 🔴 +3.04 kB 🔴 +1.05 kB 🔴 +937 B
assets/Media3DTop-Bu0AoyTq.js (removed) 2.9 kB 🟢 -2.9 kB 🟢 -1.03 kB 🟢 -869 B
assets/Media3DTop-CSU8rTtE.js (new) 2.9 kB 🔴 +2.9 kB 🔴 +1.03 kB 🔴 +867 B
assets/WidgetSelect-CETgig4K.js (removed) 2.33 kB 🟢 -2.33 kB 🟢 -734 B 🟢 -627 B
assets/WidgetSelect-WVVnRQz7.js (new) 2.33 kB 🔴 +2.33 kB 🔴 +734 B 🔴 +623 B
assets/Load3D-DSkQaXpV.js (removed) 2.01 kB 🟢 -2.01 kB 🟢 -612 B 🟢 -513 B
assets/Load3D-YjEhGqAg.js (new) 2.01 kB 🔴 +2.01 kB 🔴 +614 B 🔴 +515 B
assets/WidgetLegacy-Qlu5NfPO.js (new) 1.95 kB 🔴 +1.95 kB 🔴 +575 B 🔴 +513 B
assets/WidgetLegacy-zQjONH51.js (removed) 1.95 kB 🟢 -1.95 kB 🟢 -578 B 🟢 -523 B
assets/MediaImageTop-_-90D04u.js (new) 1.58 kB 🔴 +1.58 kB 🔴 +748 B 🔴 +638 B
assets/MediaImageTop-CI5eGAOw.js (removed) 1.58 kB 🟢 -1.58 kB 🟢 -749 B 🟢 -638 B
assets/commands-_6uSNVYB.js 14.9 kB 14.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BaAvtVOT.js 14.7 kB 14.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BRKOlMPq.js 15.4 kB 15.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-C1kmJUO0.js 14.9 kB 14.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-CHLkz7NH.js 17.4 kB 17.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-cLsDwHMQ.js 14 kB 14 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-Ct50VUT9.js 16.2 kB 16.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-DOEnM922.js 14.1 kB 14.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-Ds4Sq2CW.js 15.7 kB 15.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BjHbZI-o.js 97.5 kB 97.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BsmSUEg9.js 75.9 kB 75.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-C1dqVsBC.js 103 kB 103 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-CTcPPkuZ.js 87.4 kB 87.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-CwX98cQA.js 89.7 kB 89.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-DFyT7zKX.js 84.8 kB 84.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-DHvyJYQT.js 74.9 kB 74.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-ruI2u5eb.js 118 kB 118 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-UdMyOcTd.js 86.4 kB 86.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaAudioTop-vw5Yfif7.js 1.27 kB 1.27 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaVideoTop-BnZGofq2.js 2.6 kB 2.6 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-_Px5dSNW.js 306 kB 306 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-7z21KPoS.js 285 kB 285 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-BWKZzBPK.js 346 kB 346 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CGbgH4Yl.js 320 kB 320 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CjjjdWkV.js 313 kB 313 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CVrNtxvj.js 288 kB 288 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-DLRSA0IK.js 309 kB 309 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-DQV2gnwA.js 372 kB 372 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-ofqLG5vz.js 310 kB 310 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetChart-rDmYEWg5.js 2.39 kB 2.39 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetFileUpload-Cx6dGznS.js 11.9 kB 11.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetImageCompare-Ds3K3ULR.js 2.15 kB 2.15 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widgetPropFilter-BIbGSUAt.js 1.28 kB 1.28 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 21 added / 21 removed

@viva-jinyi viva-jinyi force-pushed the feature/media-asset-action branch from 81ff174 to b242969 Compare November 17, 2025 02:58
@github-actions
Copy link

🔧 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
Copy link
Member Author

This PR is being split into smaller, more reviewable PRs:

  • PR 1: Copy Job ID action + shared utilities
  • PR 2: Add to Current Workflow action
  • PR 3: Open/Export Workflow actions

Each PR will be independent and can be reviewed/merged separately. Closing this PR in favor of the new ones.

@viva-jinyi viva-jinyi closed this Nov 17, 2025
@viva-jinyi viva-jinyi reopened this Nov 17, 2025
@viva-jinyi viva-jinyi marked this pull request as ready for review November 17, 2025 04:20
@dosubot dosubot bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Nov 17, 2025
@viva-jinyi viva-jinyi added the claude-review Add to trigger a PR code review from Claude Code label Nov 17, 2025
// This supports PNG, WEBP, FLAC, and other formats with metadata
try {
const fileUrl = getAssetUrl(asset)
const response = await fetch(fileUrl)
Copy link

Choose a reason for hiding this comment

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

[architecture] medium Priority

Issue: Network request without proper error handling could expose internal errors to users
Context: fetch() call on line 43 could expose network errors that reveal internal system information
Suggestion: Add proper error handling and sanitize error messages before user-facing display

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: [feat] Implement media asset workflow actions with shared utilities (#6696)
Impact: 588 additions, 110 deletions across 12 files

Issue Distribution

  • Critical: 0
  • High: 0
  • Medium: 3
  • Low: 2

Category Breakdown

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

Key Findings

Architecture & Design

This PR follows good architectural patterns by:

  • Creating shared utility functions to eliminate code duplication (~150+ lines eliminated)
  • Using proper composable patterns with useMediaAssetActions
  • Implementing clean separation of concerns between UI components and business logic
  • Following established error handling patterns with toast notifications

The new utilities (assetTypeUtil, assetUrlUtil, workflowActionsService) are well-designed and reusable. The workflow extraction pattern is particularly well-architected, supporting both output assets with metadata and input assets with embedded workflows.

Security Considerations

  • Minor concern about filename validation in URL construction - while encodeURIComponent provides basic protection, additional validation would be safer
  • Network error handling could potentially expose internal system information to users
  • Overall security posture is good with proper use of existing validation utilities

Performance Impact

  • Promise.all usage in bulk operations has some error swallowing that could mask partial failures
  • Network requests lack timeout handling, which could impact user experience
  • Bundle impact is positive due to code deduplication and shared utilities
  • No significant performance regressions expected

Integration Points

  • Good integration with existing stores (assetsStore, workflowStore)
  • Proper use of existing composables (useCopyToClipboard, useToast)
  • Clean integration with the node creation system via litegraphService
  • Maintains compatibility with both cloud and OSS environments

Positive Observations

  • Excellent code deduplication: The refactoring eliminates ~150+ lines of duplicate code
  • Consistent error handling: Uses established toast notification patterns
  • Good TypeScript usage: Proper typing throughout, no any types
  • Internationalization: All user-facing strings properly localized with i18n keys
  • Clean utilities: Well-documented utility functions with good JSDoc comments
  • Composable architecture: Follows Vue 3 best practices with proper composable patterns
  • Proper testing considerations: Code is structured to be testable

References

Next Steps

  1. Address medium priority issues in error handling and Promise.all patterns
  2. Consider adding filename validation for enhanced security
  3. Add timeout handling for network requests
  4. Consider adding unit tests for the new utility functions
  5. Update documentation if needed

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

@github-actions github-actions bot removed the claude-review Add to trigger a PR code review from Claude Code label Nov 17, 2025
@viva-jinyi viva-jinyi force-pushed the feature/media-asset-action branch from 225a14a to d3070b4 Compare November 17, 2025 11:14
export function useMediaAssetActions() {
const toast = useToast()
const dialogStore = useDialogStore()
const mediaContext = inject(MediaAssetKey, null)
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like a lot of things depend on this being present. Could it be a required argument to the composable instead of being Provided?

life: 3000
})
}
} catch (error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

half-nit, half-actual-concern:
When there are so many things happening in the try block, it's easy for the operations to have partially completed which can leave the store in an invalid state.
Could you use multiple smaller try blocks, maybe tracking which pieces specifically failed?

Copy link
Contributor

Choose a reason for hiding this comment

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

Very nit, but this seems like it could be a single module, src/platform/assets/utils.ts that exports multiple utility functions (each of which would then be tested in src/platform/assets/utils.test.ts)

Comment on lines +43 to +45
): Promise<{
success: boolean
error?: string
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: I like a good Result<T> monad, but this seems more like it could be an Optional<Error> with absence indicating success, a la form validation.

* supportsWorkflowMetadata('image.png') // true
* supportsWorkflowMetadata('image.jpg') // false
*/
export function supportsWorkflowMetadata(filename: string): boolean {
Copy link
Contributor

Choose a reason for hiding this comment

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

quest: I think there's a similar list elsewhere in the codebase...
(Also, I think there are a lot more file formats that support the metadata than you'd think)

Copy link
Contributor

@DrJKL DrJKL 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 a few comments, but I don't think anything that couldn't be a follow-up.

viva-jinyi and others added 6 commits November 18, 2025 08:54
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>
In OSS environments, asset.id is the promptId directly.
In Cloud environments, promptId is in user_metadata.
Updated copyJobId to check both sources (same as deletion logic).

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

Co-Authored-By: Claude <noreply@anthropic.com>
Refactored downloadAsset and downloadMultipleAssets functions to use
the shared getAssetUrl utility instead of duplicating URL construction logic.

Changes:
- Added getAssetUrl import from assetUrlUtil
- Replaced inline api.apiURL construction in downloadAsset (lines 74-77)
- Replaced inline api.apiURL construction in downloadMultipleAssets (lines 112-115)

Benefits:
- Removes code duplication (2 occurrences)
- Centralizes URL construction logic
- Improves maintainability
- Ensures consistent asset type handling

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

Co-Authored-By: Claude <noreply@anthropic.com>
Fixed issue where partial deletion failures were not reported to users.
Previously, if some assets failed to delete, the UI would still show
"all assets deleted successfully" which could mislead users about data loss.

Changes:
- Replaced Promise.all with Promise.allSettled in deleteMultipleAssets
- Track individual success/failure for each asset deletion
- Show different toast messages based on results:
  - All success: success toast with count
  - All failed: error toast
  - Partial success: warning toast with succeeded/failed counts
- Improved error logging with asset names for debugging

Added i18n:
- mediaAsset.selection.partialDeleteSuccess: "{succeeded} deleted successfully, {failed} failed"

This addresses PR review comment #2 (Medium Priority).

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

Co-Authored-By: Claude <noreply@anthropic.com>
@viva-jinyi viva-jinyi force-pushed the feature/media-asset-action branch from 629eead to 3e9f906 Compare November 17, 2025 23:54
@viva-jinyi viva-jinyi enabled auto-merge (squash) November 17, 2025 23:55
@viva-jinyi
Copy link
Member Author

Since this feature is currently missing on main, I’ll create an additional refactor branch to add it.

@viva-jinyi viva-jinyi merged commit a4d979e into main Nov 18, 2025
27 checks passed
@viva-jinyi viva-jinyi deleted the feature/media-asset-action branch November 18, 2025 00:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants