import React, { useState, useEffect, useRef } from 'react'; import { initializeApp } from 'firebase/app'; import { getAuth, signInWithCustomToken, signInAnonymously, onAuthStateChanged } from 'firebase/auth'; import { getFirestore, doc, setDoc, onSnapshot, collection, query, orderBy, addDoc, serverTimestamp, updateDoc } from 'firebase/firestore'; import { Edit3, Send, User, ChevronRight, Check, X } from 'lucide-react'; const firebaseConfig = JSON.parse(__firebase_config); const app = initializeApp(firebaseConfig); const auth = getAuth(app); const db = getFirestore(app); const appId = typeof __app_id !== 'undefined' ? __app_id : 'xat-vibe-v2'; export default function App() { const [user, setUser] = useState(null); const [profile, setProfile] = useState(null); const [messages, setMessages] = useState([]); const [inputText, setInputText] = useState(''); const [isEditing, setIsEditing] = useState(false); const [newName, setNewName] = useState(''); const scrollRef = useRef(null); // 1. Auth Init useEffect(() => { const initAuth = async () => { if (typeof __initial_auth_token !== 'undefined' && __initial_auth_token) { await signInWithCustomToken(auth, __initial_auth_token); } else { await signInAnonymously(auth); } }; initAuth(); return onAuthStateChanged(auth, setUser); }, []); // 2. Profile and Data Sync useEffect(() => { if (!user) return; // Sync Profile const userDocRef = doc(db, 'artifacts', appId, 'users', user.uid, 'profile', 'info'); const unsubProfile = onSnapshot(userDocRef, (docSnap) => { if (docSnap.exists()) { const data = docSnap.data(); setProfile(data); setNewName(data.name || ''); } else { // Create default profile if not exists const defaultName = `Viber_${user.uid.substring(0, 4)}`; setDoc(userDocRef, { name: defaultName, uid: user.uid }); } }, (err) => console.error("Profile error:", err)); // Sync Messages const msgsCol = collection(db, 'artifacts', appId, 'public', 'data', 'messages'); const unsubMsgs = onSnapshot(msgsCol, (snap) => { const docs = snap.docs.map(d => ({ id: d.id, ...d.data() })); // In-memory sort because we can't use complex queries (Rule 2) const sorted = docs.sort((a, b) => (a.time?.seconds || 0) - (b.time?.seconds || 0)); setMessages(sorted); setTimeout(() => scrollRef.current?.scrollIntoView({ behavior: 'smooth' }), 100); }, (err) => console.error("Messages error:", err)); return () => { unsubProfile(); unsubMsgs(); }; }, [user]); const handleUpdateName = async () => { if (!newName.trim() || !user) return; const userDocRef = doc(db, 'artifacts', appId, 'users', user.uid, 'profile', 'info'); try { await updateDoc(userDocRef, { name: newName.trim() }); setIsEditing(false); } catch (e) { console.error(e); } }; const handleSendMessage = async (e) => { e.preventDefault(); if (!inputText.trim() || !user || !profile) return; const msg = inputText; setInputText(''); try { await addDoc(collection(db, 'artifacts', appId, 'public', 'data', 'messages'), { text: msg, sender: profile.name || 'Anonimo', uid: user.uid, time: serverTimestamp() }); } catch (e) { console.error(e); } }; if (!user) return
Connessione...
; return (
{/* Sidebar */} {/* Main Chat */}
Canale Generale
{messages.map((m) => (
{m.uid === user.uid ? 'Tu' : m.sender}
{m.text}
))}
setInputText(e.target.value)} className="w-full bg-zinc-900 border border-white/5 rounded-2xl py-4 pl-6 pr-16 text-sm focus:outline-none focus:border-indigo-500/50 transition-all placeholder:text-zinc-600" placeholder="Scrivi qualcosa di leggendario..." />