mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-23 16:24:06 +00:00
feat: support mask editor in comfyui cloud
- use response from /api/upload/mask to find mask layers - query for /api/files/mask-layers when making additional edits
This commit is contained in:
@@ -405,6 +405,63 @@ export class ComfyApp {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate old clipspace friendly filenames to hash-based filenames
|
||||
* This handles workflows saved before the hash-based filename fix
|
||||
*/
|
||||
migrateClipspaceFilenames(graph: LGraph) {
|
||||
// Iterate through all nodes in the graph
|
||||
for (const node of graph._nodes) {
|
||||
if (!node.widgets) continue
|
||||
|
||||
// Find image widgets
|
||||
for (const widget of node.widgets) {
|
||||
if (widget.name !== 'image' || typeof widget.value !== 'string')
|
||||
continue
|
||||
|
||||
// Check if widget has an old clipspace friendly filename
|
||||
const oldFilenamePattern =
|
||||
/clipspace\/clipspace-(painted-masked|painted|mask|paint)-\d+\.png(\s+\[input\])?/
|
||||
|
||||
if (oldFilenamePattern.test(widget.value)) {
|
||||
const oldValue = widget.value
|
||||
|
||||
// Try to migrate if clipspace has images
|
||||
if (
|
||||
ComfyApp.clipspace?.images &&
|
||||
ComfyApp.clipspace.images.length > 0
|
||||
) {
|
||||
const currentClipspaceImage =
|
||||
ComfyApp.clipspace.images[ComfyApp.clipspace.selectedIndex || 0]
|
||||
if (currentClipspaceImage?.filename) {
|
||||
// Check if this is a hash-based filename (64 chars hex)
|
||||
const isHashFilename = /^[0-9a-f]{64}\.png$/i.test(
|
||||
currentClipspaceImage.filename
|
||||
)
|
||||
if (isHashFilename) {
|
||||
// Construct the new hash-based value (filename only, no subfolder)
|
||||
const newValue =
|
||||
currentClipspaceImage.filename +
|
||||
(currentClipspaceImage.type
|
||||
? ` [${currentClipspaceImage.type}]`
|
||||
: '')
|
||||
|
||||
widget.value = newValue
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we can't migrate, clear the widget to prevent using old friendly name
|
||||
console.warn(
|
||||
`Cannot migrate clipspace filename "${oldValue}" for node ${node.id} - clipspace not available. Clearing widget to prevent asset not found error. Please re-paste from clipspace.`
|
||||
)
|
||||
widget.value = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static pasteFromClipspace(node: LGraphNode) {
|
||||
if (ComfyApp.clipspace) {
|
||||
// image paste
|
||||
@@ -483,10 +540,21 @@ export class ComfyApp {
|
||||
typeof node.widgets[index].value == 'string' &&
|
||||
clip_image.filename
|
||||
) {
|
||||
node.widgets[index].value =
|
||||
(clip_image.subfolder ? clip_image.subfolder + '/' : '') +
|
||||
// Widget value should be JUST the filename (no subfolder)
|
||||
const widgetValue =
|
||||
clip_image.filename +
|
||||
(clip_image.type ? ` [${clip_image.type}]` : '')
|
||||
node.widgets[index].value = widgetValue
|
||||
|
||||
// Also update the node's serialized properties
|
||||
// This ensures the value persists when the graph is serialized/configured
|
||||
if (node.properties) {
|
||||
node.properties['image'] = widgetValue
|
||||
}
|
||||
// Update widgets_values array if it exists (used during serialization)
|
||||
if (node.widgets_values) {
|
||||
node.widgets_values[index] = widgetValue
|
||||
}
|
||||
} else {
|
||||
node.widgets[index].value = clip_image
|
||||
}
|
||||
@@ -506,8 +574,9 @@ export class ComfyApp {
|
||||
value.filename
|
||||
) {
|
||||
const resultItem = value as ResultItem
|
||||
// For cloud storage, don't include subfolder prefix in widget value
|
||||
// The subfolder is handled internally by the backend
|
||||
prop.value =
|
||||
(resultItem.subfolder ? resultItem.subfolder + '/' : '') +
|
||||
resultItem.filename +
|
||||
(resultItem.type ? ` [${resultItem.type}]` : '')
|
||||
} else {
|
||||
@@ -748,6 +817,9 @@ export class ComfyApp {
|
||||
|
||||
const r = onConfigure?.apply(this, args)
|
||||
|
||||
// Migrate old clipspace friendly filenames to hash-based filenames
|
||||
app.migrateClipspaceFilenames(this)
|
||||
|
||||
// Fire after onConfigure, used by primitives to generate widget using input nodes config
|
||||
triggerCallbackOnAllNodes(this, 'onAfterGraphConfigured')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user