diff --git a/app/story/[storySlug]/story-editor-client.tsx b/app/story/[storySlug]/story-editor-client.tsx index 582e796..f6f1c27 100644 --- a/app/story/[storySlug]/story-editor-client.tsx +++ b/app/story/[storySlug]/story-editor-client.tsx @@ -67,6 +67,7 @@ export function StoryEditorClient() { const { toast } = useToast(); const [apiKey, setApiKey] = useApiKey(); + const handleTitleUpdate = (newTitle: string) => { setStory(prev => prev ? { ...prev, title: newTitle } : null); }; @@ -166,12 +167,14 @@ export function StoryEditorClient() { window.addEventListener("keydown", handleKeyDown); return () => window.removeEventListener("keydown", handleKeyDown); - }, [pages.length]); + }, [pages.length, apiKey]); + const handleAddPage = () => { if (!isLoaded || !isSignedIn) { return; } + if (!apiKey && pages.length >= 1) { setShowApiModal(true); return; diff --git a/hooks/use-api-key.ts b/hooks/use-api-key.ts index 1018f20..28ffa9b 100644 --- a/hooks/use-api-key.ts +++ b/hooks/use-api-key.ts @@ -1,65 +1,11 @@ "use client"; -import { useState, useEffect, useCallback } from "react"; +import useLocalStorageState from "use-local-storage-state"; -const STORAGE_KEY = "together_api_key"; -const STORAGE_EVENT = "apiKeyChanged"; - -/** - * Reactive hook for managing the Together API key in localStorage. - * Automatically syncs across components and tabs when the key changes. - * - * @returns {[string | null, (key: string | null) => void]} Tuple of [apiKey, setApiKey] - */ export function useApiKey(): [string | null, (key: string | null) => void] { - const [apiKey, setApiKeyState] = useState(null); - - // Initialize from localStorage on mount - useEffect(() => { - const readFromStorage = () => { - if (typeof window !== "undefined") { - const stored = localStorage.getItem(STORAGE_KEY); - setApiKeyState(stored); - } - }; - - readFromStorage(); - - // Listen for storage events (cross-tab updates) - const handleStorageChange = (e: StorageEvent) => { - if (e.key === STORAGE_KEY) { - setApiKeyState(e.newValue); - } - }; - - // Listen for custom events (same-tab updates) - const handleCustomStorageChange = () => { - readFromStorage(); - }; - - window.addEventListener("storage", handleStorageChange); - window.addEventListener(STORAGE_EVENT, handleCustomStorageChange); - - return () => { - window.removeEventListener("storage", handleStorageChange); - window.removeEventListener(STORAGE_EVENT, handleCustomStorageChange); - }; - }, []); - - // Setter function that updates both localStorage and state, and dispatches event - const setApiKey = useCallback((key: string | null) => { - if (typeof window !== "undefined") { - if (key === null) { - localStorage.removeItem(STORAGE_KEY); - } else { - localStorage.setItem(STORAGE_KEY, key); - } - setApiKeyState(key); - // Dispatch custom event for same-tab reactivity - window.dispatchEvent(new CustomEvent(STORAGE_EVENT)); - } - }, []); - + const [apiKey, setApiKey] = useLocalStorageState("together_api_key", { defaultValue: null }); return [apiKey, setApiKey]; } + + diff --git a/package.json b/package.json index 0da4a16..8fa32b6 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "tailwind-merge": "^3.3.1", "tailwindcss-animate": "^1.0.7", "together-ai": "^0.33.0", + "use-local-storage-state": "^19.5.0", "vaul": "^1.1.2", "zod": "4.2.1" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2fdf3ec..ea307b1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -182,6 +182,9 @@ importers: together-ai: specifier: ^0.33.0 version: 0.33.0 + use-local-storage-state: + specifier: ^19.5.0 + version: 19.5.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) vaul: specifier: ^1.1.2 version: 1.1.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -2856,6 +2859,13 @@ packages: '@types/react': optional: true + use-local-storage-state@19.5.0: + resolution: {integrity: sha512-sUJAyFvsmqMpBhdwaRr7GTKkkoxb6PWeNVvpBDrLuwQF1PpbJRKIbOYeLLeqJI7B3wdfFlLLCBbmOdopiSTBOw==} + engines: {node: '>=14'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + use-sidecar@1.1.3: resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} engines: {node: '>=10'} @@ -5936,6 +5946,11 @@ snapshots: optionalDependencies: '@types/react': 19.2.7 + use-local-storage-state@19.5.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0): + dependencies: + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + use-sidecar@1.1.3(@types/react@19.2.7)(react@19.2.0): dependencies: detect-node-es: 1.1.0