import { S } from '../state.js'; import { esc, toast } from '../utils.js'; import { api, fetchRomajiIndex, invalidateCoverCache, getRomajiOverrides, setRomajiOverride, removeRomajiOverride } from '../api.js'; import { THEMES, applyTheme, getCurrentThemeId } from '../themes.js'; // Circular — safe (only used inside function bodies) import { refreshDisplayMode, updateNpColorMode } from '../player/player.js'; import { startArtistSortFix } from './downloads.js'; // ─── SIDEBAR ─── export function openSidebar() { document.getElementById('sidebar').classList.add('mobile-open'); document.getElementById('mobile-overlay').classList.add('active'); } export function closeSidebar() { document.getElementById('sidebar').classList.remove('mobile-open'); document.getElementById('mobile-overlay').classList.remove('active'); } export function switchNavMode(mode) { const lib = document.getElementById('bnav-library'); const disc = document.getElementById('bnav-discover'); if(!lib || !disc) return; lib.style.display = mode==='library' ? 'flex' : 'none'; disc.style.display = mode==='discover' ? 'flex' : 'none'; document.getElementById('bnav-tab-library')?.classList.toggle('active', mode==='library'); document.getElementById('bnav-tab-discover')?.classList.toggle('active', mode==='discover'); } // ─── MOBILE SEARCH (legacy stubs — header search is now always visible) ─── export function toggleMobileSearch() { document.getElementById('header-search-input')?.focus(); } export function closeMobileSearch() { import('../views/views.js').then(m => m.closeHeaderSearch()); } // ─── SETUP ─── export function switchSetupTab(t) { document.querySelectorAll('.setup-tab').forEach((el,i) => el.classList.toggle('active', i===(t==='navidrome'?0:1))); document.querySelectorAll('.setup-pane').forEach((el,i) => el.classList.toggle('active', i===(t==='navidrome'?0:1))); } // ─── SETTINGS ─── export function openSettings() { import('../views/abs.js').then(m => m.absOpenSettings()); document.getElementById('s-url').value = S.cfg.url || ''; document.getElementById('s-user').value = S.cfg.user || ''; document.getElementById('s-pass').value = ''; document.getElementById('s-lastfm').value = S.cfg.lastfmKey || ''; document.getElementById('s-backend').value = S.cfg.backendUrl || ''; document.getElementById('s-show-playcount').classList.toggle('on', !!S.cfg.showPlayCount); document.getElementById('s-show-romaji').classList.toggle('on', !!S.cfg.showRomaji); document.getElementById('s-cover-color-bg').classList.toggle('on', !!S.cfg.coverColorBg); document.getElementById('s-scrobble-mode').value = S.cfg.scrobbleMode || '15s'; _renderThemePicker(); document.getElementById('settings-modal').classList.add('open'); checkBackend(); _loadApkInfo(); } // Show the "download the Android APK" button only if the backend actually has an APK staged. async function _loadApkInfo() { const section = document.getElementById('s-apk-section'); const btn = document.getElementById('s-apk-btn'); const meta = document.getElementById('s-apk-meta'); if (!section || !btn) return; section.style.display = 'none'; const base = S.cfg.backendUrl; if (!base) return; try { const info = await fetch(`${base}/api/apk/info`).then(r => r.json()); if (!info?.available) return; btn.href = `${base}/api/apk`; const mb = info.size ? (info.size / 1048576).toFixed(1) + ' MB' : ''; const date = info.updatedAt ? new Date(info.updatedAt).toLocaleDateString('de-DE') : ''; if (meta) meta.textContent = [info.version && `v${info.version}`, mb, date && `Stand ${date}`].filter(Boolean).join(' · '); section.style.display = ''; } catch {} } function _renderThemePicker() { const el = document.getElementById('theme-picker'); if (!el) return; const current = getCurrentThemeId(); el.innerHTML = THEMES.map(t => `