aboutsummaryrefslogtreecommitdiff
path: root/aero.js
diff options
context:
space:
mode:
Diffstat (limited to 'aero.js')
-rw-r--r--aero.js60
1 files changed, 56 insertions, 4 deletions
diff --git a/aero.js b/aero.js
index 98cb8ec..9429ccf 100644
--- a/aero.js
+++ b/aero.js
@@ -1,4 +1,4 @@
-// Shared Aero JS: bubbles, sparkle cursor, music toggle, drag windows, helpers.
+// Shared Aero JS: bubbles, sparkle cursor, music toggle, drag windows, theme switcher, helpers.
function spawnBubbles(host, count = 22) {
const f = document.createElement('div');
@@ -50,8 +50,14 @@ function sparkleCursor() {
s.className = 'sparkle';
s.style.left = e.clientX + 'px';
s.style.top = e.clientY + 'px';
- const hue = 30 + Math.random() * 200;
- s.style.background = `radial-gradient(circle, oklch(95% 0.12 ${hue}) 0%, oklch(85% 0.18 ${hue} / 0.6) 40%, transparent 70%)`;
+ const theme = document.body.dataset.theme;
+ // chrome: iridescent / holographic palette (cyan→magenta→pink)
+ // aero: warm-cool rainbow as before
+ const hue = theme === 'chrome'
+ ? 200 + Math.random() * 160
+ : 30 + Math.random() * 200;
+ const chroma = theme === 'chrome' ? 0.22 : 0.18;
+ s.style.background = `radial-gradient(circle, oklch(96% 0.10 ${hue}) 0%, oklch(82% ${chroma} ${hue} / 0.6) 40%, transparent 70%)`;
document.body.appendChild(s);
setTimeout(() => s.remove(), 900);
});
@@ -147,6 +153,45 @@ function bindMusicToggle(root) {
});
}
+// THEME SWITCHER — Aero (Frutiger) ↔ Chrome (Y2K)
+const THEME_KEY = 'tyler.theme';
+const THEMES = ['aero', 'chrome'];
+
+function getTheme() {
+ const t = localStorage.getItem(THEME_KEY);
+ return THEMES.includes(t) ? t : 'aero';
+}
+function setTheme(t) {
+ if (!THEMES.includes(t)) t = 'aero';
+ document.body.setAttribute('data-theme', t);
+ localStorage.setItem(THEME_KEY, t);
+ document.querySelectorAll('.theme-switcher button').forEach(b => {
+ b.classList.toggle('active', b.dataset.theme === t);
+ });
+ try { window.dispatchEvent(new CustomEvent('themechange', { detail: t })); } catch(_){}
+}
+function mountThemeSwitcher(host) {
+ host = host || document.body;
+ const wrap = document.createElement('div');
+ wrap.className = 'theme-switcher no-drag';
+ wrap.innerHTML = THEMES.map(t => `
+ <button data-theme="${t}" title="${t}" class="no-drag">
+ <span class="ts-dot ${t}"></span>${t}
+ </button>
+ `).join('');
+ host.appendChild(wrap);
+ wrap.querySelectorAll('button').forEach(b => {
+ b.addEventListener('click', () => setTheme(b.dataset.theme));
+ });
+ setTheme(getTheme());
+ return wrap;
+}
+function initTheme() {
+ document.body.setAttribute('data-theme', getTheme());
+}
+
+// REAL API INTEGRATIONS
+
async function fetchLastFm(user = 'trollshotlol', key = 'e4d5c973811037717f7603f616259cdf', limit = 4) {
const url = `https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=${user}&api_key=${key}&format=json&limit=${limit}`;
const r = await fetch(url);
@@ -182,4 +227,11 @@ async function fetchReelMouthFeed(limit = 6) {
return await r.json();
}
-window.Aero = { spawnBubbles, makeClouds, sparkleCursor, makeDraggable, counterHTML, nowPlayingHTML, animateEq, musicToggleHTML, bindMusicToggle, fetchLastFm, fetchFilms, fetchVisitorCount, fetchReelMouthFeed };
+window.Aero = {
+ spawnBubbles, makeClouds, sparkleCursor, makeDraggable,
+ counterHTML, nowPlayingHTML, animateEq, musicToggleHTML, bindMusicToggle,
+ // theme api
+ getTheme, setTheme, mountThemeSwitcher, initTheme, THEMES,
+ // real api integrations
+ fetchLastFm, fetchFilms, fetchVisitorCount, fetchReelMouthFeed,
+};