diff --git a/public/css/index.css b/public/css/index.css index 7a1a288..1d8ad00 100644 --- a/public/css/index.css +++ b/public/css/index.css @@ -40,6 +40,30 @@ body { align-items: center; } +.snowflake { + position: absolute; + background-color: white; + border-radius: 50%; + pointer-events: none; + z-index: 1; +} + +.raindrop { + position: absolute; + background-color: white; + border-radius: 50%; + pointer-events: none; + z-index: 1; +} + +.hidden { + display: none; +} + +.activity-header.hidden { + display: none; +} + .user-card { display: flex; flex-direction: column; diff --git a/public/js/index.js b/public/js/index.js index e6a9afe..22e2dc6 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -291,7 +291,6 @@ function updatePresence(data) { }; let status = "offline"; - console.log(data.activities.some((activity) => activity.type === 1)); if (data.activities.some((activity) => activity.type === 1)) { status = "streaming"; } else { @@ -339,11 +338,15 @@ function updatePresence(data) { }); const activityList = document.querySelector(".activities"); + const activitiesTitle = document.querySelector(".activity-header"); - if (activityList) { - activityList.innerHTML = ""; + if (activityList && activitiesTitle) { if (filtered?.length) { activityList.innerHTML = filtered.map(buildActivityHTML).join(""); + activitiesTitle.classList.remove("hidden"); + } else { + activityList.innerHTML = ""; + activitiesTitle.classList.add("hidden"); } updateElapsedAndProgress(); } diff --git a/public/js/rain.js b/public/js/rain.js new file mode 100644 index 0000000..27c0d8f --- /dev/null +++ b/public/js/rain.js @@ -0,0 +1,77 @@ +const rainContainer = document.createElement("div"); +rainContainer.style.position = "fixed"; +rainContainer.style.top = "0"; +rainContainer.style.left = "0"; +rainContainer.style.width = "100vw"; +rainContainer.style.height = "100vh"; +rainContainer.style.pointerEvents = "none"; +document.body.appendChild(rainContainer); + +const maxRaindrops = 100; +const raindrops = []; +const mouse = { x: -100, y: -100 }; + +document.addEventListener("mousemove", (e) => { + mouse.x = e.clientX; + mouse.y = e.clientY; +}); + +const getRaindropColor = () => { + const htmlTag = document.documentElement; + return htmlTag.getAttribute("data-theme") === "dark" + ? "rgba(173, 216, 230, 0.8)" + : "rgba(70, 130, 180, 0.8)"; +}; + +const createRaindrop = () => { + if (raindrops.length >= maxRaindrops) { + const oldestRaindrop = raindrops.shift(); + rainContainer.removeChild(oldestRaindrop); + } + + const raindrop = document.createElement("div"); + raindrop.classList.add("raindrop"); + raindrop.style.position = "absolute"; + raindrop.style.width = "2px"; + raindrop.style.height = `${Math.random() * 10 + 10}px`; + raindrop.style.background = getRaindropColor(); + raindrop.style.borderRadius = "1px"; + raindrop.style.left = `${Math.random() * window.innerWidth}px`; + raindrop.style.top = `-${raindrop.style.height}`; + raindrop.style.opacity = Math.random() * 0.5 + 0.3; + raindrop.speed = Math.random() * 6 + 4; + raindrop.directionX = (Math.random() - 0.5) * 0.2; + raindrop.directionY = Math.random() * 0.5 + 0.8; + + raindrops.push(raindrop); + rainContainer.appendChild(raindrop); +}; + +setInterval(createRaindrop, 50); + +function updateRaindrops() { + raindrops.forEach((raindrop, index) => { + const rect = raindrop.getBoundingClientRect(); + + raindrop.style.left = `${rect.left + raindrop.directionX * raindrop.speed}px`; + raindrop.style.top = `${rect.top + raindrop.directionY * raindrop.speed}px`; + + if (rect.top + rect.height >= window.innerHeight) { + rainContainer.removeChild(raindrop); + raindrops.splice(index, 1); + } + + if ( + rect.left > window.innerWidth || + rect.top > window.innerHeight || + rect.left < 0 + ) { + raindrop.style.left = `${Math.random() * window.innerWidth}px`; + raindrop.style.top = `-${raindrop.style.height}`; + } + }); + + requestAnimationFrame(updateRaindrops); +} + +updateRaindrops(); diff --git a/public/js/snow.js b/public/js/snow.js new file mode 100644 index 0000000..05048a8 --- /dev/null +++ b/public/js/snow.js @@ -0,0 +1,84 @@ +document.addEventListener("DOMContentLoaded", () => { + const snowContainer = document.createElement("div"); + snowContainer.style.position = "fixed"; + snowContainer.style.top = "0"; + snowContainer.style.left = "0"; + snowContainer.style.width = "100vw"; + snowContainer.style.height = "100vh"; + snowContainer.style.pointerEvents = "none"; + document.body.appendChild(snowContainer); + + const maxSnowflakes = 60; + const snowflakes = []; + const mouse = { x: -100, y: -100 }; + + document.addEventListener("mousemove", (e) => { + mouse.x = e.clientX; + mouse.y = e.clientY; + }); + + const createSnowflake = () => { + if (snowflakes.length >= maxSnowflakes) { + const oldestSnowflake = snowflakes.shift(); + snowContainer.removeChild(oldestSnowflake); + } + + const snowflake = document.createElement("div"); + snowflake.classList.add("snowflake"); + snowflake.style.position = "absolute"; + snowflake.style.width = `${Math.random() * 3 + 2}px`; + snowflake.style.height = snowflake.style.width; + snowflake.style.background = "white"; + snowflake.style.borderRadius = "50%"; + snowflake.style.opacity = Math.random(); + snowflake.style.left = `${Math.random() * window.innerWidth}px`; + snowflake.style.top = `-${snowflake.style.height}`; + snowflake.speed = Math.random() * 3 + 2; + snowflake.directionX = (Math.random() - 0.5) * 0.5; + snowflake.directionY = Math.random() * 0.5 + 0.5; + + snowflakes.push(snowflake); + snowContainer.appendChild(snowflake); + }; + + setInterval(createSnowflake, 80); + + function updateSnowflakes() { + snowflakes.forEach((snowflake, index) => { + const rect = snowflake.getBoundingClientRect(); + + const dx = rect.left + rect.width / 2 - mouse.x; + const dy = rect.top + rect.height / 2 - mouse.y; + const distance = Math.sqrt(dx * dx + dy * dy); + + if (distance < 30) { + snowflake.directionX += (dx / distance) * 0.02; + snowflake.directionY += (dy / distance) * 0.02; + } else { + snowflake.directionX += (Math.random() - 0.5) * 0.01; + snowflake.directionY += (Math.random() - 0.5) * 0.01; + } + + snowflake.style.left = `${rect.left + snowflake.directionX * snowflake.speed}px`; + snowflake.style.top = `${rect.top + snowflake.directionY * snowflake.speed}px`; + + if (rect.top + rect.height >= window.innerHeight) { + snowContainer.removeChild(snowflake); + snowflakes.splice(index, 1); + } + + if ( + rect.left > window.innerWidth || + rect.top > window.innerHeight || + rect.left < 0 + ) { + snowflake.style.left = `${Math.random() * window.innerWidth}px`; + snowflake.style.top = `-${snowflake.style.height}`; + } + }); + + requestAnimationFrame(updateSnowflakes); + } + + updateSnowflakes(); +}); diff --git a/src/routes/[id].ts b/src/routes/[id].ts index bdfc975..16ea3c0 100644 --- a/src/routes/[id].ts +++ b/src/routes/[id].ts @@ -52,6 +52,8 @@ async function handler(request: ExtendedRequest): Promise { }, instance, readme, + allowSnow: presence.kv.snow || false, + allowRain: presence.kv.rain || false, }; return await renderEjsTemplate("index", ejsTemplateData); diff --git a/src/routes/index.ts b/src/routes/index.ts index 829d105..7f12f0a 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -51,6 +51,8 @@ async function handler(): Promise { }, instance, readme, + allowSnow: presence.kv.snow || false, + allowRain: presence.kv.rain || false, }; return await renderEjsTemplate("index", ejsTemplateData); diff --git a/src/views/index.ejs b/src/views/index.ejs index 0611579..d4f2be3 100644 --- a/src/views/index.ejs +++ b/src/views/index.ejs @@ -13,6 +13,13 @@ + <% if (allowSnow) { %> + + <% } %> + <% if(allowRain) { %> + + <% } %> + @@ -59,152 +66,139 @@ let filtered = activities .filter(a => a.type !== 4) .sort((a, b) => { - const priority = { 2: 0, 1: 1, 3: 2 }; // Listening, Streaming, Watching ? should i keep this + const priority = { 2: 0, 1: 1, 3: 2 }; const aPriority = priority[a.type] ?? 99; const bPriority = priority[b.type] ?? 99; return aPriority - bPriority; }); %> - <% if (filtered.length > 0) { %> -

Activities

- <% if (readme) { %>