diff --git a/src/components/nodes/BaseNode.tsx b/src/components/nodes/BaseNode.tsx index e9312819..f50d0b90 100644 --- a/src/components/nodes/BaseNode.tsx +++ b/src/components/nodes/BaseNode.tsx @@ -22,6 +22,7 @@ interface BaseNodeProps { minWidth?: number; minHeight?: number; headerAction?: ReactNode; + titlePrefix?: ReactNode; } export function BaseNode({ @@ -41,6 +42,7 @@ export function BaseNode({ minWidth = 180, minHeight = 100, headerAction, + titlePrefix, }: BaseNodeProps) { const currentNodeId = useWorkflowStore((state) => state.currentNodeId); const groups = useWorkflowStore((state) => state.groups); @@ -201,6 +203,7 @@ export function BaseNode({
{/* Title Section */}
+ {titlePrefix} {isEditingTitle ? ( - {provider === "replicate" ? ( - + + {provider === "gemini" ? ( + + + + ) : provider === "replicate" ? ( + ) : ( - + )} @@ -367,47 +371,38 @@ export function GenerateImageNode({ id, data, selected }: NodeProps { - if (isGeminiOnly) { - // Gemini-only mode: just "Generate", model shown in inline dropdown - return "Generate"; - } else if (nodeData.selectedModel?.displayName && nodeData.selectedModel.modelId) { - // External provider with model selected: append model name - return `Generate - ${nodeData.selectedModel.displayName}`; + if (nodeData.selectedModel?.displayName && nodeData.selectedModel.modelId) { + return nodeData.selectedModel.displayName; + } + // Fallback for legacy data or no model selected + if (nodeData.model) { + return GEMINI_IMAGE_MODELS.find(m => m.value === nodeData.model)?.label || nodeData.model; } - return "Generate"; - }, [isGeminiOnly, nodeData.selectedModel?.displayName, nodeData.selectedModel?.modelId]); + return "Select model..."; + }, [nodeData.selectedModel?.displayName, nodeData.selectedModel?.modelId, nodeData.model]); + + // Provider badge as title prefix + const titlePrefix = useMemo(() => ( + + ), [currentProvider]); // Header action element based on provider mode const headerAction = useMemo(() => { - if (isGeminiOnly) { - // Gemini-only: inline dropdown for 2 models + if (!isGeminiOnly) { + // External providers: browse button return ( - - ); - } else { - // External providers: badge + browse button - return ( - <> - - - + Browse + ); } - }, [isGeminiOnly, nodeData.model, handleModelChange, currentProvider]); + return null; + }, [isGeminiOnly]); const isNanoBananaPro = isGeminiProvider && nodeData.model === "nano-banana-pro"; const hasCarouselImages = (nodeData.imageHistory || []).length > 1; @@ -465,6 +460,7 @@ export function GenerateImageNode({ id, data, selected }: NodeProps {/* Dynamic input handles based on model schema (external providers only) */} {!isGeminiProvider && nodeData.inputSchema && nodeData.inputSchema.length > 0 ? ( diff --git a/src/components/nodes/GenerateVideoNode.tsx b/src/components/nodes/GenerateVideoNode.tsx index 6b37ffea..f9c2a982 100644 --- a/src/components/nodes/GenerateVideoNode.tsx +++ b/src/components/nodes/GenerateVideoNode.tsx @@ -11,18 +11,24 @@ import { ModelSearchDialog } from "@/components/modals/ModelSearchDialog"; import { useToast } from "@/components/Toast"; import { getVideoDimensions, calculateNodeSize } from "@/utils/nodeDimensions"; -// Provider badge component - shows small provider icon for external providers +// Provider badge component - shows provider icon for all providers function ProviderBadge({ provider }: { provider: ProviderType }) { + const providerName = provider === "gemini" ? "Gemini" : provider === "replicate" ? "Replicate" : "fal.ai"; + return ( - - {provider === "replicate" ? ( - + + {provider === "gemini" ? ( + + + + ) : provider === "replicate" ? ( + ) : ( - + )} @@ -264,27 +270,29 @@ export function GenerateVideoNode({ id, data, selected }: NodeProps { if (nodeData.selectedModel?.displayName && nodeData.selectedModel.modelId) { - return `Video - ${nodeData.selectedModel.displayName}`; + return nodeData.selectedModel.displayName; } - return "Generate Video"; + return "Select model..."; }, [nodeData.selectedModel?.displayName, nodeData.selectedModel?.modelId]); - // Header action element - badge + browse button - const headerAction = useMemo(() => ( - <> - - - + // Provider badge as title prefix + const titlePrefix = useMemo(() => ( + ), [currentProvider]); + // Header action element - browse button + const headerAction = useMemo(() => ( + + ), []); + const hasCarouselVideos = (nodeData.videoHistory || []).length > 1; // Track previous status to detect error transitions @@ -341,6 +349,7 @@ export function GenerateVideoNode({ id, data, selected }: NodeProps {/* Dynamic input handles based on model schema */} {nodeData.inputSchema && nodeData.inputSchema.length > 0 ? (