import React, { useState, useEffect } from 'react'; import { Edit2, Trash2, Plus, Check, X, ExternalLink, Paperclip, Heart, Image as ImageIcon, LogOut, LogIn } from 'lucide-react'; import { initializeApp } from 'firebase/app'; import { getAuth, signInWithCustomToken, signInAnonymously, onAuthStateChanged, GoogleAuthProvider, signInWithPopup, signOut } from 'firebase/auth'; import { getFirestore, collection, onSnapshot, doc, setDoc, deleteDoc } from 'firebase/firestore'; // === Firebase 初始化設定 === const firebaseConfig = typeof __firebase_config !== 'undefined' ? 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'; // 定義可用的便利貼顏色 const NOTE_COLORS = [ 'bg-yellow-100', 'bg-pink-100', 'bg-blue-100', 'bg-green-100', 'bg-purple-100', 'bg-orange-100' ]; // 定義些微旋轉的角度,讓便利貼看起來更自然 const ROTATIONS = ['-rotate-2', '-rotate-1', 'rotate-0', 'rotate-1', 'rotate-2', 'rotate-3']; export default function App() { const [notes, setNotes] = useState([]); const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); // 注入手寫字體與自訂 CSS useEffect(() => { const link = document.createElement('link'); link.href = 'https://fonts.googleapis.com/css2?family=Klee+One:wght@400;600&display=swap'; link.rel = 'stylesheet'; document.head.appendChild(link); return () => document.head.removeChild(link); }, []); // 1. 處理身份驗證 (Auth) 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 (error) { console.error("Auth init error:", error); } }; initAuth(); const unsubscribe = onAuthStateChanged(auth, (currentUser) => { setUser(currentUser); }); return () => unsubscribe(); }, []); // 2. 處理資料庫同步 (Firestore) useEffect(() => { if (!user) return; setLoading(true); // 依據使用者 UID 建立專屬的資料路徑 const notesRef = collection(db, 'artifacts', appId, 'users', user.uid, 'notes'); const unsubscribe = onSnapshot(notesRef, (snapshot) => { const fetchedNotes = []; snapshot.forEach((doc) => { fetchedNotes.push({ id: doc.id, ...doc.data() }); }); // 依照建立時間排序 fetchedNotes.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0)); setNotes(fetchedNotes); setLoading(false); }, (error) => { console.error("Error fetching notes:", error); setLoading(false); } ); return () => unsubscribe(); }, [user]); // Google 登入 const handleGoogleLogin = async () => { const provider = new GoogleAuthProvider(); try { await signInWithPopup(auth, provider); } catch (error) { console.error("Google login failed", error); } }; // 登出 const handleLogout = async () => { try { await signOut(auth); await signInAnonymously(auth); // 登出後退回訪客狀態 } catch (error) { console.error("Logout failed", error); } }; // 新增便利貼 const addNote = async () => { if (!user) return; const randomColor = NOTE_COLORS[Math.floor(Math.random() * NOTE_COLORS.length)]; const randomRotate = ROTATIONS[Math.floor(Math.random() * ROTATIONS.length)]; const newId = Date.now().toString(); const newNote = { title: '新便利貼', content: '在這裡寫下描述...', link: '', color: randomColor, rotate: randomRotate, icon: '📌', iconType: 'emoji', // 'emoji' 或 'image' createdAt: Date.now() }; try { await setDoc(doc(db, 'artifacts', appId, 'users', user.uid, 'notes', newId), newNote); } catch (error) { console.error("Error adding note:", error); } }; // 更新便利貼 const updateNote = async (id, updatedData) => { if (!user) return; try { await setDoc(doc(db, 'artifacts', appId, 'users', user.uid, 'notes', id.toString()), updatedData, { merge: true }); } catch (error) { console.error("Error updating note:", error); } }; // 刪除便利貼 const deleteNote = async (id) => { if (!user) return; try { await deleteDoc(doc(db, 'artifacts', appId, 'users', user.uid, 'notes', id.toString())); } catch (error) { console.error("Error deleting note:", error); } }; return (
{note.content}