import State from '../core/state.js'; import { Bus } from '../core/bus.js'; const WALLPAPERS = { graphite: { name: 'Graphite', gradient: 'radial-gradient(ellipse at center, #1e2126 0%, #0f1114 100%)' }, ember: { name: 'Ember', gradient: 'linear-gradient(135deg, #1a1d21 0%, #2a1f15 40%, #d4a24c33 100%)' }, tide: { name: 'Tide', gradient: 'linear-gradient(160deg, #0a1628 0%, #0f2847 40%, #14425a 70%, #1a5c6e 100%)' }, vellum: { name: 'Vellum', gradient: 'linear-gradient(145deg, #1e1c1a 0%, #2a2520 50%, #332e28 100%)' }, eclipse: { name: 'Eclipse', gradient: 'linear-gradient(160deg, #0a0a0f 0%, #150f20 50%, #1a1030 100%)' }, terminal: { name: 'Terminal', gradient: 'radial-gradient(ellipse at 20% 50%, #0a1a0a 0%, #0f1410 40%, #0a0f0a 100%)' } }; let currentWp = null; let applying = false; function applyWallpaper(id) { if (applying) return; const wp = WALLPAPERS[id]; if (!wp) return; const layer = document.getElementById('wallpaper-layer'); if (!layer) return; applying = true; // Crossfade const overlay = document.createElement('div'); overlay.style.position = 'absolute'; overlay.style.inset = '0'; overlay.style.background = wp.gradient; overlay.style.opacity = '0'; overlay.style.transition = 'opacity 250ms ease'; overlay.style.zIndex = '1'; layer.appendChild(overlay); requestAnimationFrame(() => { overlay.style.opacity = '1'; if (currentWp && currentWp !== overlay) { const old = currentWp; old.style.opacity = '0'; setTimeout(() => old.remove(), 300); } currentWp = overlay; }); if (State.get('wallpaper') !== id) { State.set('wallpaper', id); } applying = false; // Update picker swatches document.querySelectorAll('.wallpaper-swatch').forEach(s => { s.classList.toggle('active', s.dataset.id === id); }); } function initPicker() { const picker = document.getElementById('wallpaper-picker'); const grid = document.getElementById('wallpaper-picker-grid'); if (!picker || !grid) return; // Populate swatches for (const [id, wp] of Object.entries(WALLPAPERS)) { const swatch = document.createElement('div'); swatch.className = 'wallpaper-swatch'; swatch.dataset.id = id; swatch.setAttribute('role', 'button'); swatch.setAttribute('aria-label', `Select ${wp.name} wallpaper`); swatch.style.background = wp.gradient; swatch.innerHTML = `${wp.name}`; swatch.addEventListener('click', () => applyWallpaper(id)); grid.appendChild(swatch); } // Apply saved wallpaper const saved = State.get('wallpaper'); if (saved && WALLPAPERS[saved]) { applyWallpaper(saved); } // Toggle button in status bar const toggleBtn = document.getElementById('wallpaper-toggle'); if (toggleBtn) { toggleBtn.addEventListener('click', () => { picker.classList.toggle('hidden'); }); } // Close picker on backdrop click picker.addEventListener('click', (e) => { if (e.target === picker) { picker.classList.add('hidden'); } }); // Close on Escape document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && !picker.classList.contains('hidden')) { picker.classList.add('hidden'); } }); } function init() { // Listen for state changes to wallpaper (external triggers only; applying flag prevents recursion) State.subscribe('wallpaper', (id) => { if (id && WALLPAPERS[id]) { applyWallpaper(id); } }); // Apply saved or default const saved = State.get('wallpaper'); const wpId = (saved && WALLPAPERS[saved]) ? saved : 'graphite'; applyWallpaper(wpId); initPicker(); } init();