document.addEventListener("DOMContentLoaded", () => { // DOM Elements - Navigation const btnSimulator = document.getElementById("btn-simulator"); const btnDeveloper = document.getElementById("btn-developer"); const btnHistory = document.getElementById("btn-history"); const sectionSimulator = document.getElementById("section-simulator-view"); const sectionDeveloper = document.getElementById("section-developer-view"); const sectionHistory = document.getElementById("section-history-view"); const pageTitle = document.getElementById("page-title"); const pageDesc = document.getElementById("page-desc"); // DOM Elements - Chat Simulator const chatInput = document.getElementById("chat-input"); const btnSendMessage = document.getElementById("btn-send-message"); const chatMessagesContainer = document.getElementById("chat-messages-container"); // DOM Elements - Inspector Panel (Phase 1) const previewEmptyState = document.getElementById("preview-empty-state"); const previewLoadingState = document.getElementById("preview-loading-state"); const previewImage = document.getElementById("preview-image"); const previewMetadataPanel = document.getElementById("preview-metadata-panel"); const loadingStepText = document.getElementById("loading-step-text"); const loadingFunnyQuote = document.getElementById("loading-funny-quote"); const metaQuery = document.getElementById("meta-query"); const metaGreeting = document.getElementById("meta-greeting"); const metaPrompt = document.getElementById("meta-prompt"); const btnDownload = document.getElementById("btn-download"); const btnShowApiDetails = document.getElementById("btn-show-api-details"); // DOM Elements - Settings Modal const settingsModal = document.getElementById("settings-modal"); const btnOpenSettings = document.getElementById("btn-open-settings"); const btnCloseSettings = document.getElementById("btn-close-settings"); const btnSaveSettings = document.getElementById("btn-save-settings"); const btnResetSettings = document.getElementById("btn-reset-settings"); const inputApiKey = document.getElementById("input-api-key"); const inputCustomGreeting = document.getElementById("input-custom-greeting"); const selectHeaderPreset = document.getElementById("select-header-preset"); // DOM Elements - Developer Hub const urlLatest = document.getElementById("url-latest"); const urlGenerate = document.getElementById("url-generate"); const btnCopies = document.querySelectorAll(".btn-copy"); const tabBtns = document.querySelectorAll(".tab-btn"); const tabContents = document.querySelectorAll(".tab-content"); // DOM Elements - History const historyGridContainer = document.getElementById("history-grid-container"); const historyCountText = document.getElementById("history-count-text"); // Configuration / Local State let config = { apiKey: localStorage.getItem("GOOGLE_API_KEY") || "", customGreeting: localStorage.getItem("CUSTOM_GREETING") || "", headerPreset: localStorage.getItem("HEADER_PRESET") || "random" }; // Initialize Settings Inputs inputApiKey.value = config.apiKey; inputCustomGreeting.value = config.customGreeting; selectHeaderPreset.value = config.headerPreset; // Set Dynamic host URLs based on window.location const host = window.location.origin; urlLatest.value = `${host}/api/latest`; urlGenerate.value = `${host}/api/generate`; // Funny quotes to rotate during loading const loadingQuotes = [ "「正在池塘裡培育第一朵金蓮花...」", "「正在將太陽緩緩拉出地平線...」", "「正在調配紅、橙、黃、綠、藍、靛、紫飽和度...」", "「正在使用 90 年代頂級繪圖軟體套用漸層濾鏡...」", "「正在祈求大慈大悲觀世音菩薩加持...」", "「正在用微軟正黑體與標楷體在畫布邊緣雕琢...」", "「正在呼叫隊友串接的通訊軟體 API Webhook...」", "「健康就是福,請稍候,認同請分享...」" ]; let loadingInterval = null; // Navigation Click Handlers btnSimulator.addEventListener("click", () => { switchTab(btnSimulator, sectionSimulator, "聊天指令模擬器", "在這裡模擬通訊軟體的對話,即時檢視生成的「早安圖」效果。"); }); btnDeveloper.addEventListener("click", () => { switchTab(btnDeveloper, sectionDeveloper, "FastAPI 串接中心", "隊友 (成員 A) 可以直接呼叫以下 FastAPI 端點,將同一張早安圖回傳至通訊軟體群組。"); }); btnHistory.addEventListener("click", () => { switchTab(btnHistory, sectionHistory, "歷史生成紀錄", "瀏覽過去所有生成且包含文字浮水印的早安長輩圖。"); fetchHistory(); }); function switchTab(activeBtn, activeSection, title, description) { // Toggle Nav Buttons [btnSimulator, btnDeveloper, btnHistory].forEach(btn => btn.classList.remove("active")); activeBtn.classList.add("active"); // Toggle Sections [sectionSimulator, sectionDeveloper, sectionHistory].forEach(sec => sec.classList.add("hidden")); activeSection.classList.remove("hidden"); // Update Title & Desc pageTitle.textContent = title; pageDesc.textContent = description; } // Modal Operations btnOpenSettings.addEventListener("click", () => settingsModal.classList.remove("hidden")); btnCloseSettings.addEventListener("click", () => settingsModal.classList.add("hidden")); settingsModal.addEventListener("click", (e) => { if (e.target === settingsModal) settingsModal.classList.add("hidden"); }); btnSaveSettings.addEventListener("click", () => { config.apiKey = inputApiKey.value.trim(); config.customGreeting = inputCustomGreeting.value.trim(); config.headerPreset = selectHeaderPreset.value; localStorage.setItem("GOOGLE_API_KEY", config.apiKey); localStorage.setItem("CUSTOM_GREETING", config.customGreeting); localStorage.setItem("HEADER_PRESET", config.headerPreset); settingsModal.classList.add("hidden"); showToast("🌸 設定已成功儲存!"); }); btnResetSettings.addEventListener("click", () => { inputApiKey.value = ""; inputCustomGreeting.value = ""; selectHeaderPreset.value = "random"; }); // Copy to clipboard helper btnCopies.forEach(btn => { btn.addEventListener("click", () => { const targetId = btn.getAttribute("data-target"); const targetInput = document.getElementById(targetId); targetInput.select(); document.execCommand("copy"); btn.classList.add("copied"); btn.innerHTML = ` 已複製`; setTimeout(() => { btn.classList.remove("copied"); btn.innerHTML = ` 複製`; }, 2000); }); }); // Developer Code Tabs tabBtns.forEach(btn => { btn.addEventListener("click", () => { tabBtns.forEach(b => b.classList.remove("active")); btn.classList.add("active"); const tabId = btn.getAttribute("data-tab"); tabContents.forEach(c => { if (c.id === tabId) { c.classList.remove("hidden"); } else { c.classList.add("hidden"); } }); }); }); // Send Message / Simulate command btnSendMessage.addEventListener("click", sendSimulatedMessage); chatInput.addEventListener("keydown", (e) => { if (e.key === "Enter") sendSimulatedMessage(); }); btnShowApiDetails.addEventListener("click", () => { btnDeveloper.click(); }); function getFormattedTime() { const now = new Date(); return now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); } function addMessageToChat(avatar, text, isUser = false, imageUrl = null) { const msgDiv = document.createElement("div"); msgDiv.className = `message ${isUser ? 'user-message' : 'bot-message'}`; let content = `
${text}
`; if (imageUrl) { content += `正在吸收指令能量,著手繪製早安圖...
${getFormattedTime()}載入生成紀錄中...
尚無歷史生成紀錄
載入失敗: ${err.message}