"use client"; import { useState, useRef, useEffect } from "react"; interface SpeakableProps { children: React.ReactNode; text: string; } let cachedProfileId: string | null = null; let profileChecked = false; export default function SpeakableText({ children, text }: SpeakableProps) { const [playing, setPlaying] = useState(false); const [loading, setLoading] = useState(false); const [hasProfile, setHasProfile] = useState(false); const audioRef = useRef(null); useEffect(() => { if (profileChecked) { setHasProfile(!!cachedProfileId); return; } try { const profiles = JSON.parse(localStorage.getItem("tts_profiles") || "[]"); if (profiles.length > 0) { cachedProfileId = profiles[0].id; setHasProfile(true); } profileChecked = true; } catch {} }, []); const handleSpeak = async (e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); if (playing) { audioRef.current?.pause(); setPlaying(false); return; } if (!cachedProfileId || text.length < 5) return; setLoading(true); try { const fd = new FormData(); fd.append("text", text); fd.append("profile_id", cachedProfileId); fd.append("language", "Korean"); const res = await fetch("/api/tts/speak", { method: "POST", body: fd }); if (!res.ok) { setLoading(false); return; } const blob = await res.blob(); if (blob.size < 200) { setLoading(false); return; } const url = URL.createObjectURL(blob); const audio = new Audio(url); audioRef.current = audio; audio.onended = () => setPlaying(false); setPlaying(true); setLoading(false); audio.play(); } catch { setLoading(false); } }; if (!hasProfile || text.length < 5) return <>{children}; return ( <> {children} ); }