import React, { useState, useEffect, useRef } from 'react'; import { initializeApp } from 'firebase/app'; import { getAuth, signInAnonymously, onAuthStateChanged, updateProfile, signInWithCustomToken } from 'firebase/auth'; import { getFirestore, collection, addDoc, query, onSnapshot, orderBy, serverTimestamp, doc, setDoc, getDoc, deleteDoc } from 'firebase/firestore'; import { MessageSquare, Plus, LogOut, User, Search, Send, ArrowLeft, Users, Trash2, Smile } from 'lucide-react'; // --- Firebase Initialization --- 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 : 'default-app-id'; // --- Constants & Helpers --- const AVATAR_COLORS = ['#EF4444', '#F59E0B', '#10B981', '#3B82F6', '#6366F1', '#8B5CF6', '#EC4899']; const getRandomColor = () => AVATAR_COLORS[Math.floor(Math.random() * AVATAR_COLORS.length)]; // --- Main Component --- export default function App() { const [user, setUser] = useState(null); // Auth user const [userProfile, setUserProfile] = useState(null); // Firestore profile const [view, setView] = useState('loading'); // loading, auth, home, chat const [currentRoom, setCurrentRoom] = useState(null); const [rooms, setRooms] = useState([]); const [loading, setLoading] = useState(true); // 1. Auth & Initial Load useEffect(() => { const initAuth = async () => { try { if (typeof __initial_auth_token !== 'undefined' && __initial_auth_token) { await signInWithCustomToken(auth, __initial_auth_token); } else { await signInAnonymously(auth); } } catch (err) { console.error("Auth error:", err); } }; initAuth(); const unsubscribe = onAuthStateChanged(auth, async (firebaseUser) => { if (firebaseUser) { setUser(firebaseUser); // Check for existing profile in Firestore const userRef = doc(db, 'artifacts', appId, 'users', firebaseUser.uid, 'profile', 'data'); const userSnap = await getDoc(userRef); if (userSnap.exists()) { setUserProfile(userSnap.data()); setView('home'); } else { setView('auth'); // Need to register } } else { setUser(null); setView('loading'); } setLoading(false); }); return () => unsubscribe(); }, []); // 2. Fetch Rooms (Only when logged in) useEffect(() => { if (!user) return; const roomsRef = collection(db, 'artifacts', appId, 'public', 'data', 'rooms'); // Note: Simple query to avoid index requirements const q = query(roomsRef); const unsubscribe = onSnapshot(q, (snapshot) => { const roomData = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })); // Client-side sort by createdAt (desc) roomData.sort((a, b) => (b.createdAt?.seconds || 0) - (a.createdAt?.seconds || 0)); setRooms(roomData); }, (err) => console.error("Room fetch error:", err)); return () => unsubscribe(); }, [user]); // --- Actions --- const handleRegister = async (username) => { if (!user) return; const color = getRandomColor(); const profileData = { uid: user.uid, username: username, color: color, createdAt: serverTimestamp() }; // Save public profile await setDoc(doc(db, 'artifacts', appId, 'users', user.uid, 'profile', 'data'), profileData); setUserProfile(profileData); setView('home'); }; const handleCreateRoom = async (name, desc) => { if (!user) return; await addDoc(collection(db, 'artifacts', appId, 'public', 'data', 'rooms'), { name, description: desc, createdBy: user.uid, creatorName: userProfile.username, createdAt: serverTimestamp(), memberCount: 0 }); }; const handleLogout = async () => { // In this demo environment, we just reload to reset anonymous session effectively window.location.reload(); }; // --- Rendering Views --- if (loading) { return (
Connecting to BloxChat Server...
Create an identity to start chatting.
No rooms found. Be the first to create one!
{room.description}
Live Chat
Welcome to the start of {room.name}!
Remember to be kind and respectful.