//js/settings import { themeManager, lastFMStorage, nowPlayingSettings, lyricsSettings, backgroundSettings, trackListSettings, cardSettings, waveformSettings, } from "./storage.js"; import { db } from "./db.js"; import { authManager } from "./firebase/auth.js"; import { syncManager } from "./firebase/sync.js"; import { initializeFirebaseSettingsUI } from "./firebase/config.js"; export function initializeSettings(scrobbler, player, api, ui) { // Initialize Firebase UI & Settings authManager.updateUI(authManager.user); initializeFirebaseSettingsUI(); // Email Auth UI Logic const toggleEmailBtn = document.getElementById("toggle-email-auth-btn"); const cancelEmailBtn = document.getElementById("cancel-email-auth-btn"); const authContainer = document.getElementById("email-auth-container"); const authButtonsContainer = document.getElementById( "auth-buttons-container", ); const emailInput = document.getElementById("auth-email"); const passwordInput = document.getElementById("auth-password"); const signInBtn = document.getElementById("email-signin-btn"); const signUpBtn = document.getElementById("email-signup-btn"); if (toggleEmailBtn && authContainer && authButtonsContainer) { toggleEmailBtn.addEventListener("click", () => { authContainer.style.display = "flex"; authButtonsContainer.style.display = "none"; }); } if (cancelEmailBtn && authContainer && authButtonsContainer) { cancelEmailBtn.addEventListener("click", () => { authContainer.style.display = "none"; authButtonsContainer.style.display = "flex"; }); } if (signInBtn) { signInBtn.addEventListener("click", async () => { const email = emailInput.value; const password = passwordInput.value; if (!email || !password) { alert("Please enter both email and password."); return; } try { await authManager.signInWithEmail(email, password); authContainer.style.display = "none"; authButtonsContainer.style.display = "flex"; emailInput.value = ""; passwordInput.value = ""; } catch (e) { // Error handled in authManager } }); } if (signUpBtn) { signUpBtn.addEventListener("click", async () => { const email = emailInput.value; const password = passwordInput.value; if (!email || !password) { alert("Please enter both email and password."); return; } try { await authManager.signUpWithEmail(email, password); authContainer.style.display = "none"; authButtonsContainer.style.display = "flex"; emailInput.value = ""; passwordInput.value = ""; } catch (e) { // Error handled in authManager } }); } const lastfmConnectBtn = document.getElementById("lastfm-connect-btn"); const lastfmStatus = document.getElementById("lastfm-status"); const lastfmToggle = document.getElementById("lastfm-toggle"); const lastfmToggleSetting = document.getElementById("lastfm-toggle-setting"); const lastfmLoveToggle = document.getElementById("lastfm-love-toggle"); const lastfmLoveSetting = document.getElementById("lastfm-love-setting"); function updateLastFMUI() { if (scrobbler.isAuthenticated()) { lastfmStatus.textContent = `Connected as ${scrobbler.username}`; lastfmConnectBtn.textContent = "Disconnect"; lastfmConnectBtn.classList.add("danger"); lastfmToggleSetting.style.display = "flex"; lastfmLoveSetting.style.display = "flex"; lastfmToggle.checked = lastFMStorage.isEnabled(); lastfmLoveToggle.checked = lastFMStorage.shouldLoveOnLike(); } else { lastfmStatus.textContent = "Connect your Last.fm account to scrobble tracks"; lastfmConnectBtn.textContent = "Connect Last.fm"; lastfmConnectBtn.classList.remove("danger"); lastfmToggleSetting.style.display = "none"; lastfmLoveSetting.style.display = "none"; } } updateLastFMUI(); lastfmConnectBtn?.addEventListener("click", async () => { if (scrobbler.isAuthenticated()) { if (confirm("Disconnect from Last.fm?")) { scrobbler.disconnect(); updateLastFMUI(); } return; } const authWindow = window.open("", "_blank"); lastfmConnectBtn.disabled = true; lastfmConnectBtn.textContent = "Opening Last.fm..."; try { const { token, url } = await scrobbler.getAuthUrl(); if (authWindow) { authWindow.location.href = url; } else { alert("Popup blocked! Please allow popups."); lastfmConnectBtn.textContent = "Connect Last.fm"; lastfmConnectBtn.disabled = false; return; } lastfmConnectBtn.textContent = "Waiting for authorization..."; let attempts = 0; const maxAttempts = 30; const checkAuth = setInterval(async () => { attempts++; if (attempts > maxAttempts) { clearInterval(checkAuth); lastfmConnectBtn.textContent = "Connect Last.fm"; lastfmConnectBtn.disabled = false; if (authWindow && !authWindow.closed) authWindow.close(); alert("Authorization timed out. Please try again."); return; } try { const result = await scrobbler.completeAuthentication(token); if (result.success) { clearInterval(checkAuth); if (authWindow && !authWindow.closed) authWindow.close(); updateLastFMUI(); lastfmConnectBtn.disabled = false; lastFMStorage.setEnabled(true); lastfmToggle.checked = true; alert(`Successfully connected to Last.fm as ${result.username}!`); } } catch (e) { // Still waiting } }, 2000); } catch (error) { console.error("Last.fm connection failed:", error); alert("Failed to connect to Last.fm: " + error.message); lastfmConnectBtn.textContent = "Connect Last.fm"; lastfmConnectBtn.disabled = false; if (authWindow && !authWindow.closed) authWindow.close(); } }); lastfmToggle?.addEventListener("change", (e) => { lastFMStorage.setEnabled(e.target.checked); }); lastfmLoveToggle?.addEventListener("change", (e) => { lastFMStorage.setLoveOnLike(e.target.checked); }); // Theme picker const themePicker = document.getElementById("theme-picker"); const currentTheme = themeManager.getTheme(); themePicker.querySelectorAll(".theme-option").forEach((option) => { if (option.dataset.theme === currentTheme) { option.classList.add("active"); } option.addEventListener("click", () => { const theme = option.dataset.theme; themePicker .querySelectorAll(".theme-option") .forEach((opt) => opt.classList.remove("active")); option.classList.add("active"); if (theme === "custom") { document.getElementById("custom-theme-editor").classList.add("show"); renderCustomThemeEditor(); themeManager.setTheme('custom'); } else { document.getElementById("custom-theme-editor").classList.remove("show"); themeManager.setTheme(theme); } }); }); function renderCustomThemeEditor() { const grid = document.getElementById("theme-color-grid"); const customTheme = themeManager.getCustomTheme() || { background: "#000000", foreground: "#fafafa", primary: "#ffffff", secondary: "#27272a", muted: "#27272a", border: "#27272a", highlight: "#ffffff", }; grid.innerHTML = Object.entries(customTheme) .map( ([key, value]) => `
`, ) .join(""); } document .getElementById("apply-custom-theme") ?.addEventListener("click", () => { const colors = {}; document .querySelectorAll('#theme-color-grid input[type="color"]') .forEach((input) => { colors[input.dataset.color] = input.value; }); themeManager.setCustomTheme(colors); }); document .getElementById("reset-custom-theme") ?.addEventListener("click", () => { renderCustomThemeEditor(); }); // Quality setting const qualitySetting = document.getElementById("quality-setting"); if (qualitySetting) { const savedQuality = localStorage.getItem("playback-quality") || "LOSSLESS"; qualitySetting.value = savedQuality; player.setQuality(savedQuality); qualitySetting.addEventListener("change", (e) => { const newQuality = e.target.value; player.setQuality(newQuality); localStorage.setItem("playback-quality", newQuality); }); } // Now Playing Mode const nowPlayingMode = document.getElementById("now-playing-mode"); if (nowPlayingMode) { nowPlayingMode.value = nowPlayingSettings.getMode(); nowPlayingMode.addEventListener("change", (e) => { nowPlayingSettings.setMode(e.target.value); }); } // Track List Actions Mode const trackListActionsMode = document.getElementById( "track-list-actions-mode", ); if (trackListActionsMode) { trackListActionsMode.value = trackListSettings.getMode(); trackListActionsMode.addEventListener("change", (e) => { trackListSettings.setMode(e.target.value); }); } // Compact Artist Toggle const compactArtistToggle = document.getElementById("compact-artist-toggle"); if (compactArtistToggle) { compactArtistToggle.checked = cardSettings.isCompactArtist(); compactArtistToggle.addEventListener("change", (e) => { cardSettings.setCompactArtist(e.target.checked); }); } // Compact Album Toggle const compactAlbumToggle = document.getElementById("compact-album-toggle"); if (compactAlbumToggle) { compactAlbumToggle.checked = cardSettings.isCompactAlbum(); compactAlbumToggle.addEventListener("change", (e) => { cardSettings.setCompactAlbum(e.target.checked); }); } // Download Lyrics Toggle const downloadLyricsToggle = document.getElementById( "download-lyrics-toggle", ); if (downloadLyricsToggle) { downloadLyricsToggle.checked = lyricsSettings.shouldDownloadLyrics(); downloadLyricsToggle.addEventListener("change", (e) => { lyricsSettings.setDownloadLyrics(e.target.checked); }); } // Romaji Lyrics Toggle const romajiLyricsToggle = document.getElementById("romaji-lyrics-toggle"); if (romajiLyricsToggle) { romajiLyricsToggle.checked = localStorage.getItem("lyricsRomajiMode") === "true"; romajiLyricsToggle.addEventListener("change", (e) => { localStorage.setItem( "lyricsRomajiMode", e.target.checked ? "true" : "false", ); }); } // Album Background Toggle const albumBackgroundToggle = document.getElementById( "album-background-toggle", ); if (albumBackgroundToggle) { albumBackgroundToggle.checked = backgroundSettings.isEnabled(); albumBackgroundToggle.addEventListener("change", (e) => { backgroundSettings.setEnabled(e.target.checked); }); } // Waveform Toggle const waveformToggle = document.getElementById("waveform-toggle"); if (waveformToggle) { waveformToggle.checked = waveformSettings.isEnabled(); waveformToggle.addEventListener("change", (e) => { waveformSettings.setEnabled(e.target.checked); window.dispatchEvent(new CustomEvent("waveform-toggle", { detail: { enabled: e.target.checked } })); }); } // Filename template setting const filenameTemplate = document.getElementById("filename-template"); if (filenameTemplate) { filenameTemplate.value = localStorage.getItem("filename-template") || "{trackNumber} - {artist} - {title}"; filenameTemplate.addEventListener("change", (e) => { localStorage.setItem("filename-template", e.target.value); }); } // ZIP folder template const zipFolderTemplate = document.getElementById("zip-folder-template"); if (zipFolderTemplate) { zipFolderTemplate.value = localStorage.getItem("zip-folder-template") || "{albumTitle} - {albumArtist}"; zipFolderTemplate.addEventListener("change", (e) => { localStorage.setItem("zip-folder-template", e.target.value); }); } // API settings document .getElementById("refresh-speed-test-btn") ?.addEventListener("click", async () => { const btn = document.getElementById("refresh-speed-test-btn"); const originalText = btn.textContent; btn.textContent = "Testing..."; btn.disabled = true; try { await api.settings.refreshSpeedTests(); ui.renderApiSettings(); btn.textContent = "Done!"; setTimeout(() => { btn.textContent = originalText; btn.disabled = false; }, 1500); } catch (error) { console.error("Failed to refresh speed tests:", error); btn.textContent = "Error"; setTimeout(() => { btn.textContent = originalText; btn.disabled = false; }, 1500); } }); document .getElementById("api-instance-list") ?.addEventListener("click", async (e) => { const button = e.target.closest("button"); if (!button) return; const li = button.closest("li"); const index = parseInt(li.dataset.index, 10); const type = li.dataset.type || "api"; // Default to api if not present const instances = await api.settings.getInstances(type); if (button.classList.contains("move-up") && index > 0) { [instances[index], instances[index - 1]] = [ instances[index - 1], instances[index], ]; } else if ( button.classList.contains("move-down") && index < instances.length - 1 ) { [instances[index], instances[index + 1]] = [ instances[index + 1], instances[index], ]; } api.settings.saveInstances(instances, type); ui.renderApiSettings(); }); document .getElementById("clear-cache-btn") ?.addEventListener("click", async () => { const btn = document.getElementById("clear-cache-btn"); const originalText = btn.textContent; btn.textContent = "Clearing..."; btn.disabled = true; try { await api.clearCache(); btn.textContent = "Cleared!"; setTimeout(() => { btn.textContent = originalText; btn.disabled = false; if (window.location.hash.includes("settings")) { ui.renderApiSettings(); } }, 1500); } catch (error) { console.error("Failed to clear cache:", error); btn.textContent = "Error"; setTimeout(() => { btn.textContent = originalText; btn.disabled = false; }, 1500); } }); document .getElementById("firebase-clear-cloud-btn") ?.addEventListener("click", async () => { if ( confirm( "Are you sure you want to delete ALL your data from the cloud? This cannot be undone.", ) ) { try { await syncManager.clearCloudData(); alert("Cloud data cleared successfully."); authManager.signOut(); } catch (error) { console.error("Failed to clear cloud data:", error); alert("Failed to clear cloud data: " + error.message); } } }); // Backup & Restore document .getElementById("export-library-btn") ?.addEventListener("click", async () => { const data = await db.exportData(); const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json", }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = `monochrome-library-${new Date().toISOString().split("T")[0]}.json`; a.click(); URL.revokeObjectURL(url); }); const importInput = document.getElementById("import-library-input"); document .getElementById("import-library-btn") ?.addEventListener("click", () => { importInput.click(); }); importInput?.addEventListener("change", async (e) => { const file = e.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = async (event) => { try { const data = JSON.parse(event.target.result); await db.importData(data); alert("Library imported successfully!"); window.location.reload(); // Simple way to refresh all state } catch (err) { console.error("Import failed:", err); alert("Failed to import library. Please check the file format."); } }; reader.readAsText(file); }); }