139 lines
3.7 KiB
JavaScript
139 lines
3.7 KiB
JavaScript
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 = `<span class="wallpaper-swatch-label">${wp.name}</span>`;
|
|
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();
|