mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-02 20:22:08 +00:00
feat(cloud): add asset widget support for PrimitiveNode model selection (#8598)
Add cloud asset widget creation in `_createWidget()` using `isAssetBrowserEligible()` - Extract shared `createAssetWidget` factory to `src/platform/assets/utils/` - Refactor `useComboWidget.ts` to use the shared factory - Add `_finalizeWidget()` helper to DRY up widget sizing/callback setup - Pass target node's `comfyClass` and input name to Asset Browser for correct model filtering - Check `Comfy.Assets.UseAssetAPI` setting (matches `useComboWidget.ts` behavior) - Sync existing target widget value to asset widget - Add toast notifications for asset validation errors - Add i18n translations for invalidAsset and invalidFilename errors Supersedes #8461 (clean rebase, no merge commits) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8598-feat-cloud-add-asset-widget-support-for-PrimitiveNode-model-selection-2fd6d73d365081a8afa7c2e91762f11c) by [Unito](https://www.unito.io) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Introduced asset widget integration for cloud-based model selection, enabling users to browse and select assets through an improved interface. * Added comprehensive asset validation with enhanced error messages for invalid assets and filenames. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: Subagent 5 <subagent@example.com> Co-authored-by: GitHub Action <action@github.com> Co-authored-by: guill <jacob.e.segal@gmail.com> Co-authored-by: Jin Yi <jin12cc@gmail.com> Co-authored-by: Alexander Brown <drjkl@comfy.org> Co-authored-by: AustinMroz <austin@comfy.org> Co-authored-by: Comfy Org PR Bot <snomiao+comfy-pr@gmail.com> Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: Johnpaul Chiwetelu <49923152+Myestery@users.noreply.github.com> Co-authored-by: Rizumu Ayaka <rizumu@ayaka.moe> Co-authored-by: Kelly Yang <124ykl@gmail.com> Co-authored-by: sno <snomiao@gmail.com> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> Co-authored-by: Benjamin Lu <benjaminlu1107@gmail.com> Co-authored-by: Terry Jia <terryjia88@gmail.com> Co-authored-by: Luke Mino-Altherr <luke@comfy.org> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This commit is contained in:
111
src/platform/assets/utils/createAssetWidget.ts
Normal file
111
src/platform/assets/utils/createAssetWidget.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
import { t } from '@/i18n'
|
||||
import type { LGraphNode } from '@/lib/litegraph/src/litegraph'
|
||||
import type {
|
||||
IBaseWidget,
|
||||
IWidgetAssetOptions
|
||||
} from '@/lib/litegraph/src/types/widgets'
|
||||
import { useAssetBrowserDialog } from '@/platform/assets/composables/useAssetBrowserDialog'
|
||||
import {
|
||||
assetFilenameSchema,
|
||||
assetItemSchema
|
||||
} from '@/platform/assets/schemas/assetSchema'
|
||||
import { useToastStore } from '@/platform/updates/common/toastStore'
|
||||
import { getAssetFilename } from '@/platform/assets/utils/assetMetadataUtils'
|
||||
|
||||
interface CreateAssetWidgetParams {
|
||||
/** The node to add the widget to */
|
||||
node: LGraphNode
|
||||
/** The widget name */
|
||||
widgetName: string
|
||||
/** The node type to show in asset browser (may differ from node.comfyClass for PrimitiveNode) */
|
||||
nodeTypeForBrowser: string
|
||||
/** Input name for asset browser filtering (defaults to widgetName if not provided) */
|
||||
inputNameForBrowser?: string
|
||||
/** Default value for the widget */
|
||||
defaultValue?: string
|
||||
/** Callback when widget value changes */
|
||||
onValueChange?: (
|
||||
widget: IBaseWidget,
|
||||
newValue: string,
|
||||
oldValue: unknown
|
||||
) => void
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an asset widget that opens the Asset Browser dialog for model selection.
|
||||
* Used by both regular nodes (via useComboWidget) and PrimitiveNode.
|
||||
*
|
||||
* @param params - Configuration for the asset widget
|
||||
* @returns The created asset widget
|
||||
*/
|
||||
export function createAssetWidget(
|
||||
params: CreateAssetWidgetParams
|
||||
): IBaseWidget {
|
||||
const {
|
||||
node,
|
||||
widgetName,
|
||||
nodeTypeForBrowser,
|
||||
inputNameForBrowser,
|
||||
defaultValue,
|
||||
onValueChange
|
||||
} = params
|
||||
|
||||
const displayLabel = defaultValue ?? t('widgets.selectModel')
|
||||
const assetBrowserDialog = useAssetBrowserDialog()
|
||||
|
||||
async function openModal(widget: IBaseWidget) {
|
||||
const toastStore = useToastStore()
|
||||
|
||||
await assetBrowserDialog.show({
|
||||
nodeType: nodeTypeForBrowser,
|
||||
inputName: inputNameForBrowser ?? widgetName,
|
||||
currentValue: widget.value as string,
|
||||
onAssetSelected: (asset) => {
|
||||
const validatedAsset = assetItemSchema.safeParse(asset)
|
||||
|
||||
if (!validatedAsset.success) {
|
||||
console.error(
|
||||
'Invalid asset item:',
|
||||
validatedAsset.error.errors,
|
||||
'Received:',
|
||||
asset
|
||||
)
|
||||
toastStore.add({
|
||||
severity: 'error',
|
||||
summary: t('assetBrowser.invalidAsset'),
|
||||
detail: t('assetBrowser.invalidAssetDetail'),
|
||||
life: 5000
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const filename = getAssetFilename(validatedAsset.data)
|
||||
const validatedFilename = assetFilenameSchema.safeParse(filename)
|
||||
|
||||
if (!validatedFilename.success) {
|
||||
console.error(
|
||||
'Invalid asset filename:',
|
||||
validatedFilename.error.errors,
|
||||
'for asset:',
|
||||
validatedAsset.data.id
|
||||
)
|
||||
toastStore.add({
|
||||
severity: 'error',
|
||||
summary: t('assetBrowser.invalidFilename'),
|
||||
detail: t('assetBrowser.invalidFilenameDetail'),
|
||||
life: 5000
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const oldValue = widget.value
|
||||
widget.value = validatedFilename.data
|
||||
onValueChange?.(widget, validatedFilename.data, oldValue)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const options: IWidgetAssetOptions = { openModal }
|
||||
|
||||
return node.addWidget('asset', widgetName, displayLabel, () => {}, options)
|
||||
}
|
||||
Reference in New Issue
Block a user