Browse Source

Remember image generate node settings

handoff-20260429-1057
Shrimbly 7 months ago
parent
commit
75a42f7340
  1. 18
      src/components/nodes/NanoBananaNode.tsx
  2. 44
      src/store/workflowStore.ts

18
src/components/nodes/NanoBananaNode.tsx

@ -3,7 +3,7 @@
import { useCallback } from "react"; import { useCallback } from "react";
import { Handle, Position, NodeProps, Node } from "@xyflow/react"; import { Handle, Position, NodeProps, Node } from "@xyflow/react";
import { BaseNode } from "./BaseNode"; import { BaseNode } from "./BaseNode";
import { useWorkflowStore } from "@/store/workflowStore"; import { useWorkflowStore, saveNanoBananaDefaults } from "@/store/workflowStore";
import { NanoBananaNodeData, AspectRatio, Resolution, ModelType } from "@/types"; import { NanoBananaNodeData, AspectRatio, Resolution, ModelType } from "@/types";
// All 10 aspect ratios supported by both models // All 10 aspect ratios supported by both models
@ -25,28 +25,36 @@ export function NanoBananaNode({ id, data, selected }: NodeProps<NanoBananaNodeT
const handleAspectRatioChange = useCallback( const handleAspectRatioChange = useCallback(
(e: React.ChangeEvent<HTMLSelectElement>) => { (e: React.ChangeEvent<HTMLSelectElement>) => {
updateNodeData(id, { aspectRatio: e.target.value as AspectRatio }); const aspectRatio = e.target.value as AspectRatio;
updateNodeData(id, { aspectRatio });
saveNanoBananaDefaults({ aspectRatio });
}, },
[id, updateNodeData] [id, updateNodeData]
); );
const handleResolutionChange = useCallback( const handleResolutionChange = useCallback(
(e: React.ChangeEvent<HTMLSelectElement>) => { (e: React.ChangeEvent<HTMLSelectElement>) => {
updateNodeData(id, { resolution: e.target.value as Resolution }); const resolution = e.target.value as Resolution;
updateNodeData(id, { resolution });
saveNanoBananaDefaults({ resolution });
}, },
[id, updateNodeData] [id, updateNodeData]
); );
const handleModelChange = useCallback( const handleModelChange = useCallback(
(e: React.ChangeEvent<HTMLSelectElement>) => { (e: React.ChangeEvent<HTMLSelectElement>) => {
updateNodeData(id, { model: e.target.value as ModelType }); const model = e.target.value as ModelType;
updateNodeData(id, { model });
saveNanoBananaDefaults({ model });
}, },
[id, updateNodeData] [id, updateNodeData]
); );
const handleGoogleSearchToggle = useCallback( const handleGoogleSearchToggle = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => { (e: React.ChangeEvent<HTMLInputElement>) => {
updateNodeData(id, { useGoogleSearch: e.target.checked }); const useGoogleSearch = e.target.checked;
updateNodeData(id, { useGoogleSearch });
saveNanoBananaDefaults({ useGoogleSearch });
}, },
[id, updateNodeData] [id, updateNodeData]
); );

44
src/store/workflowStore.ts

@ -145,18 +145,20 @@ const createDefaultNodeData = (type: NodeType): WorkflowNodeData => {
return { return {
prompt: "", prompt: "",
} as PromptNodeData; } as PromptNodeData;
case "nanoBanana": case "nanoBanana": {
const defaults = loadNanoBananaDefaults();
return { return {
inputImages: [], inputImages: [],
inputPrompt: null, inputPrompt: null,
outputImage: null, outputImage: null,
aspectRatio: "1:1", aspectRatio: defaults.aspectRatio,
resolution: "1K", resolution: defaults.resolution,
model: "nano-banana-pro", model: defaults.model,
useGoogleSearch: false, useGoogleSearch: defaults.useGoogleSearch,
status: "idle", status: "idle",
error: null, error: null,
} as NanoBananaNodeData; } as NanoBananaNodeData;
}
case "llmGenerate": case "llmGenerate":
return { return {
inputPrompt: null, inputPrompt: null,
@ -214,6 +216,38 @@ const GROUP_COLOR_ORDER: GroupColor[] = [
// localStorage helpers for auto-save configs // localStorage helpers for auto-save configs
const STORAGE_KEY = "node-banana-workflow-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<NanoBananaDefaults>) => {
if (typeof window === "undefined") return;
const current = loadNanoBananaDefaults();
const updated = { ...current, ...settings };
localStorage.setItem(NANO_BANANA_DEFAULTS_KEY, JSON.stringify(updated));
};
const generateWorkflowId = () => const generateWorkflowId = () =>
`wf_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; `wf_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;

Loading…
Cancel
Save