feat(canvas): enhance multi-image generation and user control over expanded states

This commit is contained in:
HouYunFei
2026-08-18 14:16:28 +08:00
parent b66936d891
commit e44c0c4b3e
3 changed files with 14 additions and 10 deletions
+11 -8
View File
@@ -235,7 +235,7 @@ function InfiniteCanvasPage() {
const [titleEditing, setTitleEditing] = useState(false);
const [titleDraft, setTitleDraft] = useState("");
const [historyState, setHistoryState] = useState({ canUndo: false, canRedo: false });
const [expandedImageNodeId, setExpandedImageNodeId] = useState<string | null>(null);
const [expandedImageNodeIds, setExpandedImageNodeIds] = useState<Set<string>>(new Set());
const [isNodeDragging, setIsNodeDragging] = useState(false);
const [isNodeResizing, setIsNodeResizing] = useState(false);
const [dropTargetGroupId, setDropTargetGroupId] = useState<string | null>(null);
@@ -719,6 +719,7 @@ function InfiniteCanvasPage() {
setAngleNodeId((current) => (current && allIds.has(current) ? null : current));
setPreviewNodeId((current) => (current && allIds.has(current) ? null : current));
setRunningNodeId((current) => (current && allIds.has(current) ? null : current));
setExpandedImageNodeIds((current) => new Set([...current].filter((nodeId) => !allIds.has(nodeId))));
setContextMenu((current) => (current?.type === "node" && allIds.has(current.nodeId) ? null : current));
cleanupCanvasFiles({ projectId, nodes: nodesRef.current.filter((node) => !allIds.has(node.id)), chatSessions });
},
@@ -733,7 +734,6 @@ function InfiniteCanvasPage() {
const deselectCanvas = useCallback(() => {
cancelPendingConnectionCreate();
setExpandedImageNodeId(null);
setSelectedNodeIds(new Set());
setSelectedConnectionId(null);
setContextMenu(null);
@@ -974,7 +974,6 @@ function InfiniteCanvasPage() {
(event: ReactPointerEvent<HTMLDivElement>) => {
setContextMenu(null);
setNodeCreatePosition(null);
setExpandedImageNodeId(null);
setHoveredNodeId(null);
setToolbarNodeId(null);
setDialogNodeId(null);
@@ -1427,7 +1426,6 @@ function InfiniteCanvasPage() {
const handleNodeResizeStart = useCallback(() => {
setIsNodeResizing(true);
setExpandedImageNodeId(null);
}, []);
const handleNodeResizeEnd = useCallback(() => setIsNodeResizing(false), []);
@@ -1453,7 +1451,12 @@ function InfiniteCanvasPage() {
}, []);
const toggleBatchExpanded = useCallback((nodeId: string) => {
setExpandedImageNodeId((current) => (current === nodeId ? null : nodeId));
setExpandedImageNodeIds((current) => {
const next = new Set(current);
if (next.has(nodeId)) next.delete(nodeId);
else next.add(nodeId);
return next;
});
}, []);
const setBatchPrimary = useCallback((nodeId: string, imageId: string) => {
@@ -2560,7 +2563,7 @@ function InfiniteCanvasPage() {
const deleteBatchImage = useCallback((nodeId: string, imageId: string) => {
const node = nodesRef.current.find((item) => item.id === nodeId);
if ((node?.metadata?.images?.length || 0) <= 2) setExpandedImageNodeId(null);
if ((node?.metadata?.images?.length || 0) <= 2) setExpandedImageNodeIds((current) => new Set([...current].filter((id) => id !== nodeId)));
setNodes((prev) =>
prev.map((item) => {
if (item.id !== nodeId) return item;
@@ -2838,7 +2841,7 @@ function InfiniteCanvasPage() {
showPanel={dialogNodeId === node.id && !selectionBox && !getNodeDefinition(node.type)?.hidePanel}
groupChildCount={groupChildCountById.get(node.id) || 0}
isGroupDropTarget={dropTargetGroupId === node.id}
batchExpanded={expandedImageNodeId === node.id}
batchExpanded={expandedImageNodeIds.has(node.id)}
showImageInfo={showImageInfo}
mentionReferences={mentionReferencesByNodeId.get(node.id) || EMPTY_REFERENCES}
pluginHost={pluginHost}
@@ -2895,7 +2898,7 @@ function InfiniteCanvasPage() {
</InfiniteCanvas>
<CanvasNodeHoverToolbar
node={isNodeDragging || isNodeResizing || nodeImageSettingsOpen || expandedImageNodeId ? null : toolbarNode}
node={isNodeDragging || isNodeResizing || nodeImageSettingsOpen || expandedImageNodeIds.has(toolbarNode?.id || "") ? null : toolbarNode}
viewport={viewport}
extraTools={toolbarNode ? buildNodeToolbarItems(toolbarNode) : undefined}
onKeep={keepNodeToolbar}