|
|
|
@ -33,8 +33,7 @@ import { logger } from "@/utils/logger"; |
|
|
|
import { EditOperation, applyEditOperations as executeEditOps } from "@/lib/chat/editOperations"; |
|
|
|
import { findNearestFreePosition } from "@/utils/spatialLayout"; |
|
|
|
import { assertCanCreateNodeType } from "@/utils/nodeCreationTypes"; |
|
|
|
import { resolveInitialNodeSize, type NodeCreationSize } from "@/utils/nodeSizing"; |
|
|
|
import { calculateMediaNodeSizeByShortSide } from "@/utils/nodeDimensions"; |
|
|
|
import { resolveInitialNodeSize, resolveNodeAutoSize, type NodeCreationSize } from "@/utils/nodeSizing"; |
|
|
|
import { |
|
|
|
loadWorkflowCostData, |
|
|
|
saveWorkflowCostData, |
|
|
|
@ -1191,15 +1190,6 @@ function getRunningGroupIdsFromTasks(tasks: Record<string, RunningTaskEntry>): S |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
function getMediaNodeCanvasSize( |
|
|
|
dimensions: { width: number; height: number } | null | undefined |
|
|
|
): { width: number; height: number } | null { |
|
|
|
if (!dimensions) return null; |
|
|
|
const { width, height } = dimensions; |
|
|
|
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return null; |
|
|
|
return calculateMediaNodeSizeByShortSide(width / height); |
|
|
|
} |
|
|
|
|
|
|
|
function applyWorkflowNodeStyleSize( |
|
|
|
node: WorkflowNode, |
|
|
|
size: { width: number; height: number } | null |
|
|
|
@ -1223,6 +1213,26 @@ function applyWorkflowNodeStyleSize( |
|
|
|
} as WorkflowNode; |
|
|
|
} |
|
|
|
|
|
|
|
function hasNodeSizingInputChange(data: Partial<WorkflowNodeData>): boolean { |
|
|
|
const sizingKeys = [ |
|
|
|
"dimensions", |
|
|
|
"image", |
|
|
|
"outputImage", |
|
|
|
"previewImage", |
|
|
|
"previewImg", |
|
|
|
"video", |
|
|
|
"outputVideo", |
|
|
|
"outputVideoRemoteUrl", |
|
|
|
"previewVideoPoster", |
|
|
|
"outputVideoCover", |
|
|
|
"aspectRatio", |
|
|
|
"parameters", |
|
|
|
"config", |
|
|
|
]; |
|
|
|
|
|
|
|
return sizingKeys.some((key) => Object.prototype.hasOwnProperty.call(data, key)); |
|
|
|
} |
|
|
|
|
|
|
|
function syncRunningStateFromTasks(tasks: Record<string, RunningTaskEntry>) { |
|
|
|
const runningNodeIds = getRunningNodeIdsFromTasks(tasks); |
|
|
|
return { |
|
|
|
@ -1249,7 +1259,8 @@ function isDimensionValueEffective( |
|
|
|
): boolean { |
|
|
|
if (value === undefined) return false; |
|
|
|
|
|
|
|
if (!numbersMatch(node.measured?.[axis], value)) { |
|
|
|
const styleValue = typeof node.style?.[axis] === "number" ? node.style[axis] : undefined; |
|
|
|
if (!numbersMatch(styleValue, value)) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
@ -1257,7 +1268,7 @@ function isDimensionValueEffective( |
|
|
|
setAttributes === true || |
|
|
|
setAttributes === axis |
|
|
|
) { |
|
|
|
return !numbersMatch(node[axis], value); |
|
|
|
return !numbersMatch(styleValue, value); |
|
|
|
} |
|
|
|
|
|
|
|
return false; |
|
|
|
@ -1287,6 +1298,7 @@ function isNodeChangeEffective( |
|
|
|
case "dimensions": { |
|
|
|
const node = nodeById.get(change.id); |
|
|
|
if (!node) return false; |
|
|
|
if (node.type !== "group") return false; |
|
|
|
const widthChanged = isDimensionValueEffective(node, "width", change.dimensions?.width, change.setAttributes); |
|
|
|
const heightChanged = isDimensionValueEffective(node, "height", change.dimensions?.height, change.setAttributes); |
|
|
|
const resizing = (node as WorkflowNode & { resizing?: boolean }).resizing; |
|
|
|
@ -1568,9 +1580,6 @@ const workflowStoreImpl: StateCreator<WorkflowStore> = (set, get) => ({ |
|
|
|
...node, |
|
|
|
type, |
|
|
|
data: managedNodeData, |
|
|
|
width, |
|
|
|
height, |
|
|
|
measured: undefined, |
|
|
|
style: { ...node.style, width, height }, |
|
|
|
} |
|
|
|
: node |
|
|
|
@ -1601,7 +1610,13 @@ const workflowStoreImpl: StateCreator<WorkflowStore> = (set, get) => ({ |
|
|
|
const hasDataChange = Object.entries(managedData).some( |
|
|
|
([key, value]) => !Object.is((node.data as Record<string, unknown>)[key], value) |
|
|
|
); |
|
|
|
if (!hasDataChange) { |
|
|
|
const nextData = { ...node.data, ...managedData } as WorkflowNodeData; |
|
|
|
const canvasSize = hasNodeSizingInputChange(managedData) |
|
|
|
? resolveNodeAutoSize(node.type, nextData) |
|
|
|
: null; |
|
|
|
const resizedNode = applyWorkflowNodeStyleSize(node, canvasSize); |
|
|
|
const hasSizeChange = resizedNode !== node; |
|
|
|
if (!hasDataChange && !hasSizeChange) { |
|
|
|
if (nodeId === "smartImage-7") { |
|
|
|
logSmartImage7Snapshot("updateNodeData:no-change", node, { |
|
|
|
patch: data, |
|
|
|
@ -1633,7 +1648,10 @@ const workflowStoreImpl: StateCreator<WorkflowStore> = (set, get) => ({ |
|
|
|
set((state) => ({ |
|
|
|
nodes: state.nodes.map((node) => |
|
|
|
node.id === nodeId |
|
|
|
? { ...node, data: { ...node.data, ...managedData } as WorkflowNodeData } |
|
|
|
? applyWorkflowNodeStyleSize({ |
|
|
|
...node, |
|
|
|
data: { ...node.data, ...managedData } as WorkflowNodeData, |
|
|
|
} as WorkflowNode, canvasSize) |
|
|
|
: node |
|
|
|
) as WorkflowNode[], |
|
|
|
hasUnsavedChanges: true, |
|
|
|
@ -1727,7 +1745,8 @@ const workflowStoreImpl: StateCreator<WorkflowStore> = (set, get) => ({ |
|
|
|
if (!node) return; |
|
|
|
|
|
|
|
const managedData = buildStoreManagedGenerationData(node, data, get); |
|
|
|
const canvasSize = getMediaNodeCanvasSize(dimensions); |
|
|
|
const nextData = { ...node.data, ...managedData } as WorkflowNodeData; |
|
|
|
const canvasSize = resolveNodeAutoSize(node.type, nextData, { dimensions }); |
|
|
|
const hasDataChange = Object.entries(managedData).some( |
|
|
|
([key, value]) => !Object.is((node.data as Record<string, unknown>)[key], value) |
|
|
|
); |
|
|
|
@ -2262,9 +2281,6 @@ const workflowStoreImpl: StateCreator<WorkflowStore> = (set, get) => ({ |
|
|
|
// Reset height to defaults so BaseNode's ResizeObserver
|
|
|
|
// can correctly add settings panel height from the right baseline
|
|
|
|
style: { width: node.style?.width ?? defaults.width, height: defaults.height }, |
|
|
|
width: undefined, |
|
|
|
height: undefined, |
|
|
|
measured: undefined, |
|
|
|
data: clonePreservingStrings(node.data), |
|
|
|
}; |
|
|
|
}); |
|
|
|
|