import React, { useState, useRef, Suspense } from "react"; import { motion } from "framer-motion"; import { Canvas } from "@react-three/fiber"; import { OrbitControls } from '@react-three/drei'; import AssistantChat from "./components/AssistantChat"; import AvatarModel from "./components/AvatarModel"; import ErrorBoundary from "./components/ErrorBoundary"; import Sidebar from "./components/Sidebar"; import Header from "./components/Header"; export default function App() { const [error, setError] = useState(null); const [sidebarOpen, setSidebarOpen] = useState(false); const [activeTab, setActiveTab] = useState("chat"); const [audioUrl, setAudioUrl] = useState(null); // Audio partagé pour Avatar + Lipsync const audioRef = useRef(new Audio()); // --- Gestion audio stable --- const handleAudioGenerated = (url) => { setAudioUrl(url); if (!audioRef.current) return; // Pause et réinitialisation de l'audio actuel audioRef.current.pause(); audioRef.current.currentTime = 0; // Mettre à jour la source audioRef.current.src = url; audioRef.current.crossOrigin = "anonymous"; const playAudio = async () => { try { await audioRef.current.play(); } catch (err) { console.error("Erreur lecture audio:", err); } finally { audioRef.current.oncanplaythrough = null; } }; // Attendre que l'audio soit chargé audioRef.current.oncanplaythrough = playAudio; audioRef.current.onerror = () => { console.error("Erreur de chargement audio"); audioRef.current.oncanplaythrough = null; }; }; if (error) { return (

Erreur d'application

{error.message}

); } return (
setSidebarOpen(true)} />
setSidebarOpen(false)} activeTab={activeTab} setActiveTab={setActiveTab} />

Assistante Intelligent

); }