Update StoryEditorClient with new API key dependency
This commit is contained in:
@@ -67,6 +67,7 @@ export function StoryEditorClient() {
|
|||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const [apiKey, setApiKey] = useApiKey();
|
const [apiKey, setApiKey] = useApiKey();
|
||||||
|
|
||||||
|
|
||||||
const handleTitleUpdate = (newTitle: string) => {
|
const handleTitleUpdate = (newTitle: string) => {
|
||||||
setStory(prev => prev ? { ...prev, title: newTitle } : null);
|
setStory(prev => prev ? { ...prev, title: newTitle } : null);
|
||||||
};
|
};
|
||||||
@@ -166,12 +167,14 @@ export function StoryEditorClient() {
|
|||||||
|
|
||||||
window.addEventListener("keydown", handleKeyDown);
|
window.addEventListener("keydown", handleKeyDown);
|
||||||
return () => window.removeEventListener("keydown", handleKeyDown);
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
||||||
}, [pages.length]);
|
}, [pages.length, apiKey]);
|
||||||
|
|
||||||
|
|
||||||
const handleAddPage = () => {
|
const handleAddPage = () => {
|
||||||
if (!isLoaded || !isSignedIn) {
|
if (!isLoaded || !isSignedIn) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!apiKey && pages.length >= 1) {
|
if (!apiKey && pages.length >= 1) {
|
||||||
setShowApiModal(true);
|
setShowApiModal(true);
|
||||||
return;
|
return;
|
||||||
|
|||||||
+4
-58
@@ -1,65 +1,11 @@
|
|||||||
"use client";
|
"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] {
|
export function useApiKey(): [string | null, (key: string | null) => void] {
|
||||||
const [apiKey, setApiKeyState] = useState<string | null>(null);
|
const [apiKey, setApiKey] = useLocalStorageState<string | null>("together_api_key", { defaultValue: 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));
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return [apiKey, setApiKey];
|
return [apiKey, setApiKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -67,6 +67,7 @@
|
|||||||
"tailwind-merge": "^3.3.1",
|
"tailwind-merge": "^3.3.1",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"together-ai": "^0.33.0",
|
"together-ai": "^0.33.0",
|
||||||
|
"use-local-storage-state": "^19.5.0",
|
||||||
"vaul": "^1.1.2",
|
"vaul": "^1.1.2",
|
||||||
"zod": "4.2.1"
|
"zod": "4.2.1"
|
||||||
},
|
},
|
||||||
|
|||||||
Generated
+15
@@ -182,6 +182,9 @@ importers:
|
|||||||
together-ai:
|
together-ai:
|
||||||
specifier: ^0.33.0
|
specifier: ^0.33.0
|
||||||
version: 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:
|
vaul:
|
||||||
specifier: ^1.1.2
|
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)
|
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':
|
'@types/react':
|
||||||
optional: true
|
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:
|
use-sidecar@1.1.3:
|
||||||
resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==}
|
resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -5936,6 +5946,11 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 19.2.7
|
'@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):
|
use-sidecar@1.1.3(@types/react@19.2.7)(react@19.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
detect-node-es: 1.1.0
|
detect-node-es: 1.1.0
|
||||||
|
|||||||
Reference in New Issue
Block a user