diff --git a/src/components/nodes/NanoBananaNode.tsx b/src/components/nodes/NanoBananaNode.tsx index 412fe485..7129f88e 100644 --- a/src/components/nodes/NanoBananaNode.tsx +++ b/src/components/nodes/NanoBananaNode.tsx @@ -3,7 +3,7 @@ import { useCallback } from "react"; import { Handle, Position, NodeProps, Node } from "@xyflow/react"; import { BaseNode } from "./BaseNode"; -import { useWorkflowStore } from "@/store/workflowStore"; +import { useWorkflowStore, saveNanoBananaDefaults } from "@/store/workflowStore"; import { NanoBananaNodeData, AspectRatio, Resolution, ModelType } from "@/types"; // All 10 aspect ratios supported by both models @@ -25,28 +25,36 @@ export function NanoBananaNode({ id, data, selected }: NodeProps) => { - updateNodeData(id, { aspectRatio: e.target.value as AspectRatio }); + const aspectRatio = e.target.value as AspectRatio; + updateNodeData(id, { aspectRatio }); + saveNanoBananaDefaults({ aspectRatio }); }, [id, updateNodeData] ); const handleResolutionChange = useCallback( (e: React.ChangeEvent) => { - updateNodeData(id, { resolution: e.target.value as Resolution }); + const resolution = e.target.value as Resolution; + updateNodeData(id, { resolution }); + saveNanoBananaDefaults({ resolution }); }, [id, updateNodeData] ); const handleModelChange = useCallback( (e: React.ChangeEvent) => { - updateNodeData(id, { model: e.target.value as ModelType }); + const model = e.target.value as ModelType; + updateNodeData(id, { model }); + saveNanoBananaDefaults({ model }); }, [id, updateNodeData] ); const handleGoogleSearchToggle = useCallback( (e: React.ChangeEvent) => { - updateNodeData(id, { useGoogleSearch: e.target.checked }); + const useGoogleSearch = e.target.checked; + updateNodeData(id, { useGoogleSearch }); + saveNanoBananaDefaults({ useGoogleSearch }); }, [id, updateNodeData] ); diff --git a/src/store/workflowStore.ts b/src/store/workflowStore.ts index 4082a98d..32d3f9fe 100644 --- a/src/store/workflowStore.ts +++ b/src/store/workflowStore.ts @@ -145,18 +145,20 @@ const createDefaultNodeData = (type: NodeType): WorkflowNodeData => { return { prompt: "", } as PromptNodeData; - case "nanoBanana": + case "nanoBanana": { + const defaults = loadNanoBananaDefaults(); return { inputImages: [], inputPrompt: null, outputImage: null, - aspectRatio: "1:1", - resolution: "1K", - model: "nano-banana-pro", - useGoogleSearch: false, + aspectRatio: defaults.aspectRatio, + resolution: defaults.resolution, + model: defaults.model, + useGoogleSearch: defaults.useGoogleSearch, status: "idle", error: null, } as NanoBananaNodeData; + } case "llmGenerate": return { inputPrompt: null, @@ -214,6 +216,38 @@ const GROUP_COLOR_ORDER: GroupColor[] = [ // localStorage helpers for auto-save configs const STORAGE_KEY = "node-banana-workflow-configs"; +// localStorage helpers for NanoBanana sticky settings +const NANO_BANANA_DEFAULTS_KEY = "node-banana-nanoBanana-defaults"; + +interface NanoBananaDefaults { + aspectRatio: string; + resolution: string; + model: string; + useGoogleSearch: boolean; +} + +const loadNanoBananaDefaults = (): NanoBananaDefaults => { + if (typeof window === "undefined") { + return { aspectRatio: "1:1", resolution: "1K", model: "nano-banana-pro", useGoogleSearch: false }; + } + const stored = localStorage.getItem(NANO_BANANA_DEFAULTS_KEY); + if (stored) { + try { + return JSON.parse(stored); + } catch { + return { aspectRatio: "1:1", resolution: "1K", model: "nano-banana-pro", useGoogleSearch: false }; + } + } + return { aspectRatio: "1:1", resolution: "1K", model: "nano-banana-pro", useGoogleSearch: false }; +}; + +export const saveNanoBananaDefaults = (settings: Partial) => { + if (typeof window === "undefined") return; + const current = loadNanoBananaDefaults(); + const updated = { ...current, ...settings }; + localStorage.setItem(NANO_BANANA_DEFAULTS_KEY, JSON.stringify(updated)); +}; + const generateWorkflowId = () => `wf_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;