From 60267fc64c7c245d068be14f5681effad9609561 Mon Sep 17 00:00:00 2001 From: Dante Date: Fri, 6 Mar 2026 10:20:18 +0900 Subject: [PATCH] refactor: unify image classification and fix cloud preview param handling (#9408) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Addresses review feedback from PR #9298 and resolves the divergence between `ResultItemImpl.isImage` and `appendCloudResParam`'s image classification. ### Changes - **Unify suffix-based classification**: Replace narrow `isImageBySuffix` (gif/webp only), `isVideoBySuffix` (webm/mp4), and `isAudioBySuffix` with `getMediaTypeFromFilename()` from shared-frontend-utils, using the same `IMAGE_EXTENSIONS` set (png, jpg, jpeg, gif, webp, bmp, avif, tif, tiff) that `appendCloudResParam` uses - **imageCompare.ts**: Pass `record.filename` to `appendCloudResParam` (was called without filename, bypassing image-extension guard) - **imagePreviewStore.ts**: Use per-image `image.filename` instead of first image's filename for all images in batch - **LinearControls.vue**: Use `resultItem.filename` (already a string) instead of `String(filename)` which converts undefined to `"undefined"` ### Related review comments - [imageCompare.ts — missing filename](https://github.com/Comfy-Org/ComfyUI_frontend/pull/9298#discussion_r2886137498) - [imagePreviewStore.ts — per-image filename](https://github.com/Comfy-Org/ComfyUI_frontend/pull/9298#discussion_r2886138718) - [LinearControls.vue — String(filename)](https://github.com/Comfy-Org/ComfyUI_frontend/pull/9298#discussion_r2886140159) - [queueStore.ts — diverging image classification](https://github.com/Comfy-Org/ComfyUI_frontend/pull/9298#discussion_r2886142886) ## Test plan - [x] 66 unit tests pass (queueStore + cloudPreviewUtil) - [x] `pnpm typecheck` passes - [x] `pnpm lint` passes - Fixes #9386 --------- Co-authored-by: Claude Opus 4.6 --- src/extensions/core/imageCompare.ts | 2 +- .../extensions/linearMode/LinearControls.vue | 2 +- src/stores/nodeOutputStore.ts | 3 +-- src/stores/queueStore.ts | 17 ++++++----------- 4 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/extensions/core/imageCompare.ts b/src/extensions/core/imageCompare.ts index 70e2c0e022..de0ffa61c5 100644 --- a/src/extensions/core/imageCompare.ts +++ b/src/extensions/core/imageCompare.ts @@ -29,7 +29,7 @@ useExtensionService().registerExtension({ const toUrl = (record: Record) => { const params = new URLSearchParams(record) - appendCloudResParam(params) + appendCloudResParam(params, record.filename) return api.apiURL(`/view?${params}${rand}`) } diff --git a/src/renderer/extensions/linearMode/LinearControls.vue b/src/renderer/extensions/linearMode/LinearControls.vue index 442f7caab9..05e4aec2a6 100644 --- a/src/renderer/extensions/linearMode/LinearControls.vue +++ b/src/renderer/extensions/linearMode/LinearControls.vue @@ -90,7 +90,7 @@ function getDropIndicator(node: LGraphNode) { const buildImageUrl = () => { if (!filename) return undefined const params = new URLSearchParams(resultItem) - appendCloudResParam(params, String(filename)) + appendCloudResParam(params, resultItem.filename) return api.apiURL(`/view?${params}${app.getPreviewFormatParam()}`) } diff --git a/src/stores/nodeOutputStore.ts b/src/stores/nodeOutputStore.ts index 8ef589694a..aa576717e2 100644 --- a/src/stores/nodeOutputStore.ts +++ b/src/stores/nodeOutputStore.ts @@ -121,11 +121,10 @@ export const useNodeOutputStore = defineStore('nodeOutput', () => { const rand = app.getRandParam() const previewParam = getPreviewParam(node, outputs) const isImage = isImageOutputs(node, outputs) - const firstFilename = outputs.images[0]?.filename return outputs.images.map((image) => { const params = new URLSearchParams(image) - if (isImage) appendCloudResParam(params, firstFilename) + if (isImage) appendCloudResParam(params, image.filename) return api.apiURL(`/view?${params}${previewParam}${rand}`) }) } diff --git a/src/stores/queueStore.ts b/src/stores/queueStore.ts index ff69c36ae3..b5a2af67d6 100644 --- a/src/stores/queueStore.ts +++ b/src/stores/queueStore.ts @@ -114,6 +114,9 @@ export class ResultItemImpl { if (this.isMp4) { return 'video/mp4' } + if (this.filename.endsWith('.mov')) { + return 'video/quicktime' + } if (this.isVhsFormat) { if (this.format?.endsWith('webm')) { @@ -142,14 +145,6 @@ export class ResultItemImpl { return undefined } - get isGif(): boolean { - return this.filename.endsWith('.gif') - } - - get isWebp(): boolean { - return this.filename.endsWith('.webp') - } - get isWebm(): boolean { return this.filename.endsWith('.webm') } @@ -159,11 +154,11 @@ export class ResultItemImpl { } get isVideoBySuffix(): boolean { - return this.isWebm || this.isMp4 + return getMediaTypeFromFilename(this.filename) === 'video' } get isImageBySuffix(): boolean { - return this.isGif || this.isWebp + return getMediaTypeFromFilename(this.filename) === 'image' } get isMp3(): boolean { @@ -183,7 +178,7 @@ export class ResultItemImpl { } get isAudioBySuffix(): boolean { - return this.isMp3 || this.isWav || this.isOgg || this.isFlac + return getMediaTypeFromFilename(this.filename) === 'audio' } get isVideo(): boolean {