feat(canvas): 图片转换插件 - 合并 PR #446 本地媒体转换节点与运行时
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
commit
99f50f85eb
51 files changed
+3286
-46
No files matched your search
@@ -72,7 +72,7 @@ import { CanvasLocalAgentPanel } from "@/components/canvas/canvas-local-agent-pa
|
||||
import { useFocusMode } from "@/hooks/use-focus-mode";
|
||||
import { useCanvasAgentStore } from "@/stores/canvas/use-canvas-agent-store";
|
||||
import { applyCanvasConnectionPromptSync, getContextResourceNodes, normalizeCanvasNodeMentionTokens, type CanvasResourceReference } from "@/lib/canvas/canvas-resource-references";
|
||||
import { CanvasConnectionCreateMenu, CanvasNodePanelOverlay } from "@/components/canvas/canvas-workspace-overlays";
|
||||
import { CanvasConnectionCreateMenu, CanvasNodePanelOverlay, type PendingConnectionCreate } from "@/components/canvas/canvas-workspace-overlays";
|
||||
import { CanvasOverlayLayerContainer, CanvasOverlayLayerProvider } from "@/components/canvas/canvas-overlay-layer";
|
||||
import { CanvasLeaferGraphicsLayer } from "@/components/canvas/canvas-leafer-graphics-layer";
|
||||
import { CanvasFreeformEmptyState, CanvasLinkedProjectEmptyState, CanvasShortDramaEmptyState, CanvasShortDramaGuide, CanvasStoryInputNodeContent, CanvasStylePlaceholderNodeContent } from "@/components/canvas/canvas-short-drama-entry";
|
||||
@@ -1018,6 +1018,20 @@ function InfiniteCanvasPage() {
|
||||
.filter((node) => selectedNodeIds.has(node.id) && !batchSourceRestriction(node))
|
||||
.map((node) => node.id), [nodes, selectedNodeIds]);
|
||||
|
||||
const createConversionFromSource = useCallback((source: CanvasNodeData) => {
|
||||
if (source.type !== CanvasNodeType.Image && source.type !== CanvasNodeType.Video) return;
|
||||
const spec = getNodeSpec(CanvasNodeType.MediaConversion);
|
||||
const pending: PendingConnectionCreate = {
|
||||
connection: { nodeId: source.id, handleType: "source", anchorRatio: 0.5 },
|
||||
position: {
|
||||
x: source.position.x + source.width + 96 + spec.width / 2,
|
||||
y: source.position.y + source.height / 2,
|
||||
},
|
||||
quick: true,
|
||||
};
|
||||
void createConnectedNode(CanvasNodeType.MediaConversion, pending);
|
||||
}, [createConnectedNode]);
|
||||
|
||||
const handleCanvasSelectionStart = useCallback(() => {
|
||||
setContextMenu(null);
|
||||
}, []);
|
||||
@@ -1048,6 +1062,8 @@ function InfiniteCanvasPage() {
|
||||
} else if (node.type === ART_CRITIQUE_NODE_TYPE) {
|
||||
setDialogNodeId(null);
|
||||
setArtCritiqueNodeId(node.id);
|
||||
} else if (node.type === CanvasNodeType.MediaConversion) {
|
||||
setDialogNodeId(null);
|
||||
} else {
|
||||
// 选择参考媒体时保留当前工作流配置面板,避免点击图片后配置“返回/消失”。
|
||||
// 没有工作流配置面板时,媒体节点仍按原逻辑打开自己的面板。
|
||||
@@ -1065,7 +1081,7 @@ function InfiniteCanvasPage() {
|
||||
|
||||
const handleNodeDragEnd = useCallback((nodeId: string) => {
|
||||
const node = nodesRef.current.find((item) => item.id === nodeId);
|
||||
if (!node || node.type === CanvasNodeType.Script || node.type === CanvasNodeType.Drawing || node.type === PORTRAIT_CLEARANCE_NODE_TYPE || node.type === ART_CRITIQUE_NODE_TYPE) {
|
||||
if (!node || node.type === CanvasNodeType.Script || node.type === CanvasNodeType.Drawing || node.type === CanvasNodeType.MediaConversion || node.type === PORTRAIT_CLEARANCE_NODE_TYPE || node.type === ART_CRITIQUE_NODE_TYPE) {
|
||||
setDialogNodeId(null);
|
||||
return;
|
||||
}
|
||||
@@ -1895,7 +1911,7 @@ function InfiniteCanvasPage() {
|
||||
|
||||
const renderCanvasNodePanel = useCallback(
|
||||
(panelNode: CanvasNodeData) => {
|
||||
if (panelNode.type === CanvasNodeType.Script || panelNode.type === CanvasNodeType.Drawing) return null;
|
||||
if (panelNode.type === CanvasNodeType.Script || panelNode.type === CanvasNodeType.Drawing || panelNode.type === CanvasNodeType.MediaConversion) return null;
|
||||
return panelNode.type === CanvasNodeType.Config ? (
|
||||
<CanvasConfigComposer
|
||||
value={panelNode.metadata?.composerContent ?? panelNode.metadata?.prompt ?? ""}
|
||||
@@ -2572,6 +2588,7 @@ function InfiniteCanvasPage() {
|
||||
onUpload={(node) => handleUploadRequest(node.id)}
|
||||
onDownload={downloadNodeImage}
|
||||
onSaveAsset={(node) => void saveNodeAsset(node)}
|
||||
onCreateConversion={createConversionFromSource}
|
||||
onAnnotate={(node) => setAnnotationNodeId(node.id)}
|
||||
onMaskEdit={(node) => setMaskEditNodeId(node.id)}
|
||||
onEmotion={(node) => {
|
||||
|
||||
Reference in new issue
Block a user