fix: use WidgetSelectDropdown for models (#6607)

## Summary

As the commit says, the model loaders were broken in cloud if you
enabled Vue Nodes (not a thing I think user does yet).

This fixes it by configuring the `WidgetSelectDropdown` to load so the
user load models like they would load a input or output asset.

## Review Focus

Probably `useAssetWidgetData` to make sure it's idomatic.

This part of
[assetsStore](https://github.com/Comfy-Org/ComfyUI_frontend/pull/6607/files#diff-18a5914c9f12c16d9c9c3a9f6d0e203a9c00598414d3d1c8637da9ca77339d83R158-R234)
as well.

## Screenshots

<img width="1196" height="1005" alt="Screenshot 2025-11-05 at 5 34
22 PM"
src="https://github.com/user-attachments/assets/804cd3c4-3370-4667-b606-bed52fcd6278"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6607-fix-use-WidgetSelectDropdown-for-models-2a36d73d36508143b185d06d736e4af9)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
Arjan Singh
2025-11-05 19:34:17 -08:00
committed by GitHub
parent 63cb271509
commit 8849d54e20
13 changed files with 986 additions and 37 deletions

View File

@@ -0,0 +1,99 @@
import { computed, toValue, watch } from 'vue'
import type { MaybeRefOrGetter } from 'vue'
import { isCloud } from '@/platform/distribution/types'
import type { AssetItem } from '@/platform/assets/schemas/assetSchema'
import type { DropdownItem } from '@/renderer/extensions/vueNodes/widgets/components/form/dropdown/types'
import { useAssetsStore } from '@/stores/assetsStore'
import { useModelToNodeStore } from '@/stores/modelToNodeStore'
/**
* Composable for fetching and transforming asset data for Vue node widgets.
* Provides reactive asset data based on node type with automatic category detection.
* Uses store-based caching to avoid duplicate fetches across multiple instances.
*
* Cloud-only composable - returns empty data when not in cloud environment.
*
* @param nodeType - ComfyUI node type (ref, getter, or plain value). Can be undefined.
* Accepts: ref('CheckpointLoaderSimple'), () => 'CheckpointLoaderSimple', or 'CheckpointLoaderSimple'
* @returns Reactive data including category, assets, dropdown items, loading state, and errors
*/
export function useAssetWidgetData(
nodeType: MaybeRefOrGetter<string | undefined>
) {
if (isCloud) {
const assetsStore = useAssetsStore()
const modelToNodeStore = useModelToNodeStore()
const category = computed(() => {
const resolvedType = toValue(nodeType)
return resolvedType
? modelToNodeStore.getCategoryForNodeType(resolvedType)
: undefined
})
const assets = computed<AssetItem[]>(() => {
const resolvedType = toValue(nodeType)
return resolvedType
? (assetsStore.modelAssetsByNodeType.get(resolvedType) ?? [])
: []
})
const isLoading = computed(() => {
const resolvedType = toValue(nodeType)
return resolvedType
? (assetsStore.modelLoadingByNodeType.get(resolvedType) ?? false)
: false
})
const error = computed<Error | null>(() => {
const resolvedType = toValue(nodeType)
return resolvedType
? (assetsStore.modelErrorByNodeType.get(resolvedType) ?? null)
: null
})
const dropdownItems = computed<DropdownItem[]>(() => {
return assets.value.map((asset) => ({
id: asset.id,
name:
(asset.user_metadata?.filename as string | undefined) ?? asset.name,
label: asset.name,
mediaSrc: asset.preview_url ?? '',
metadata: ''
}))
})
watch(
() => toValue(nodeType),
async (currentNodeType) => {
if (!currentNodeType) {
return
}
const hasData = assetsStore.modelAssetsByNodeType.has(currentNodeType)
if (!hasData) {
await assetsStore.updateModelsForNodeType(currentNodeType)
}
},
{ immediate: true }
)
return {
category,
assets,
dropdownItems,
isLoading,
error
}
}
return {
category: computed(() => undefined),
assets: computed(() => []),
dropdownItems: computed(() => []),
isLoading: computed(() => false),
error: computed(() => null)
}
}