diff --git a/web/audio/achievement-unlocked.mp3 b/web/audio/achievement-unlocked.mp3 new file mode 100644 index 0000000..9940318 Binary files /dev/null and b/web/audio/achievement-unlocked.mp3 differ diff --git a/web/index.html b/web/index.html index 1ceb0e7..add0d6d 100644 --- a/web/index.html +++ b/web/index.html @@ -37,8 +37,14 @@ + + + @@ -54,6 +60,7 @@ + diff --git a/web/script.js b/web/script.js index f931f58..6e37fb1 100644 --- a/web/script.js +++ b/web/script.js @@ -8,10 +8,17 @@ const catImg = document.getElementById("cat"); const heartImg = document.getElementById("heart"); const volumeSlider = document.getElementById("volume-slider"); const currentVolumeLabel = document.getElementById("current-volume-label"); +const listenerCountLabel = document.getElementById("listener-count"); +const notificationContainer = document.getElementById("notification"); +const notificationTitle = document.getElementById("notification-title"); +const notificationBody = document.getElementById("notification-body"); + const clickAudio = document.getElementById("click-audio"); const clickReleaseAudio = document.getElementById("click-release-audio"); const meowAudio = document.getElementById("meow-audio"); -const listenerCountLabel = document.getElementById("listener-count"); +const achievementUnlockedAudio = document.getElementById( + "achievement-unlocked-audio", +); let isPlaying = false; let isFading = false; @@ -19,6 +26,7 @@ let currentAudio; let maxVolume = 100; let currentVolume = 0; let saveVolumeTimeout = null; +let meowCount = 0; let ws = connectToWebSocket(); function playAudio() { @@ -134,7 +142,9 @@ function enableSpaceBarControl() { } function connectToWebSocket() { - const ws = new WebSocket(`ws://${location.host}/ws`); + const ws = new WebSocket( + `${location.protocol === "https:" ? "wss:" : "ws:"}//${location.host}/ws`, + ); ws.onmessage = (event) => { console.log(event.data); @@ -189,6 +199,34 @@ function loadInitialVolume() { document.getElementById("volume-slider-container").style.display = "flex"; } +function loadMeowCount() { + const lastMeowCount = localStorage.getItem("meowCount"); + if (!lastMeowCount) { + meowCount = 0; + } else { + const n = Number.parseInt(lastMeowCount); + if (Number.isNaN(n)) { + meowCount = 0; + } else { + meowCount += n; + } + } +} + +function showNotification(title, content, duration) { + notificationTitle.innerText = title; + notificationBody.innerText = content; + notificationContainer.style.display = "block"; + notificationContainer.style.animation = "0.5s linear 0s notification-fade-in"; + setTimeout(() => { + notificationContainer.style.animation = + "0.5s linear 0s notification-fade-out"; + setTimeout(() => { + notificationContainer.style.display = "none"; + }, 450); + }, duration); +} + playBtn.onmousedown = () => { clickAudio.play(); document.addEventListener( @@ -231,8 +269,19 @@ meowAudio.onplay = () => { heartImg.style.display = "none"; heartImg.style.animation = ""; }, 900); + + meowCount += 1; + localStorage.setItem("meowCount", `${meowCount}`); + + if (meowCount === 100) { + showNotification("a little chatty", "make milo meow 100 times", 5000); + achievementUnlockedAudio.play(); + } }; +// don't wanna jumpscare ppl +achievementUnlockedAudio.volume = 0.05; + window.addEventListener("offline", () => { ws = null; }); @@ -241,6 +290,7 @@ window.addEventListener("online", () => { ws = connectToWebSocket(); }); +loadMeowCount(); loadInitialVolume(); animateCat(); enableSpaceBarControl(); diff --git a/web/style.css b/web/style.css index c9383c1..6698108 100644 --- a/web/style.css +++ b/web/style.css @@ -1,6 +1,7 @@ :root { font-family: monospace; --text: #4c4f69; + --surface0: #ccd0da; --surface1: #bcc0cc; --base: #eff1f5; --lavender: #7287fd; @@ -149,17 +150,6 @@ a { display: flex; } -#volume-slider-container { - display: none; - justify-content: start; - align-items: center; -} - -#volume-slider-container > output { - color: var(--text); - margin-right: 1rem; -} - @media screen and (-webkit-min-device-pixel-ratio: 0) { input[type="range"] { overflow: hidden; @@ -333,3 +323,55 @@ input[type="range"]::-ms-fill-upper { right: 50%; height: 15px; } + +#volume-slider-container { + display: none; + justify-content: start; + align-items: center; +} + +#volume-slider-container > output { + color: var(--text); + margin-right: 1rem; +} + +aside#notification { + display: none; + position: absolute; + top: 0; + right: 0; + background: var(--surface0); + padding: 1rem 2rem; + margin: 2rem; + border: 2px solid var(--text); +} + +aside#notification > p { + margin: 0; +} + +aside#notification > #notification-title { + font-weight: 700; + margin-bottom: 0.5rem; +} + +@keyframes notification-fade-in { + 0% { + display: block; + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +@keyframes notification-fade-out { + 0% { + opactiy: 1; + } + + 100% { + opacity: 0; + } +}