Add Cancel animation

This commit is contained in:
Christian Semmler 2026-01-04 14:40:33 -07:00
parent 67a6548bba
commit 57a8cb17d9
No known key found for this signature in database
GPG Key ID: 086DAA1360BEEE5C
4 changed files with 100 additions and 9 deletions

60
app.js
View File

@ -602,6 +602,66 @@ document.addEventListener('DOMContentLoaded', function () {
}); });
} }
// Goodbye popup elements
const goodbyePopup = document.getElementById('goodbye-popup');
const goodbyeCancelBtn = document.getElementById('goodbye-cancel-btn');
const goodbyeProgressBar = document.querySelector('.goodbye-progress-bar');
const cancelBtn = document.getElementById('cancel-btn');
let goodbyeTimeout = null;
let goodbyeInterval = null;
function showGoodbyePopup() {
if (goodbyePopup && goodbyePopup.style.display !== 'flex') {
goodbyePopup.style.display = 'flex';
if (goodbyeProgressBar) {
goodbyeProgressBar.style.width = '0%';
}
startGoodbyeCountdown();
}
}
function hideGoodbyePopup() {
if (goodbyePopup) {
goodbyePopup.style.display = 'none';
}
if (goodbyeTimeout) {
clearTimeout(goodbyeTimeout);
goodbyeTimeout = null;
}
if (goodbyeInterval) {
clearInterval(goodbyeInterval);
goodbyeInterval = null;
}
}
function startGoodbyeCountdown() {
const duration = 4000;
const startTime = Date.now();
goodbyeInterval = setInterval(() => {
const elapsed = Date.now() - startTime;
const progress = Math.min(elapsed / duration, 1);
if (goodbyeProgressBar) {
goodbyeProgressBar.style.width = (progress * 100) + '%';
}
if (progress >= 1) {
clearInterval(goodbyeInterval);
}
}, 50);
goodbyeTimeout = setTimeout(() => {
window.location.href = 'https://legoisland.org';
}, duration);
}
if (cancelBtn) {
cancelBtn.addEventListener('click', showGoodbyePopup);
}
if (goodbyeCancelBtn) {
goodbyeCancelBtn.addEventListener('click', hideGoodbyePopup);
}
if ('serviceWorker' in navigator) { if ('serviceWorker' in navigator) {
Promise.all([ Promise.all([
configManager.init(), configManager.init(),

View File

@ -40,8 +40,21 @@
</head> </head>
<body> <body>
<div id="update-popup" class="update-popup" style="display: none;"> <div id="goodbye-popup" class="notification-popup" style="display: none;">
<div class="update-popup-content"> <div class="notification-popup-content">
<button id="goodbye-cancel-btn" class="update-dismiss-btn" aria-label="Cancel">×</button>
<div class="update-speech-bubble">
<p class="update-message">See you later, Brickulator!</p>
<div class="goodbye-progress">
<div class="goodbye-progress-bar"></div>
</div>
</div>
</div>
<img src="later.webp" alt="Goodbye" class="update-character" width="150" height="187">
</div>
<div id="update-popup" class="notification-popup" style="display: none;">
<div class="notification-popup-content">
<button id="update-dismiss-btn" class="update-dismiss-btn" aria-label="Dismiss">×</button> <button id="update-dismiss-btn" class="update-dismiss-btn" aria-label="Dismiss">×</button>
<div class="update-speech-bubble"> <div class="update-speech-bubble">
<p class="update-message">A new version just arrived!</p> <p class="update-message">A new version just arrived!</p>
@ -75,7 +88,7 @@
<img class="control-img" width="134" height="149" id="read-me-btn" src="read_me_off.webp" alt="Read Me" <img class="control-img" width="134" height="149" id="read-me-btn" src="read_me_off.webp" alt="Read Me"
data-off="read_me_off.webp" data-on="read_me_on.webp" data-target="#read-me-page"> data-off="read_me_off.webp" data-on="read_me_on.webp" data-target="#read-me-page">
<img class="control-img" width="93" height="145" id="cancel-btn" src="cancel_off.webp" alt="Cancel" <img class="control-img" width="93" height="145" id="cancel-btn" src="cancel_off.webp" alt="Cancel"
data-off="cancel_off.webp" data-on="cancel_on.webp" onclick="location.href = 'https://legoisland.org';"> data-off="cancel_off.webp" data-on="cancel_on.webp">
</div> </div>
<div id="read-me-page" class="page-content"> <div id="read-me-page" class="page-content">
@ -885,7 +898,7 @@
</div> </div>
<div class="app-footer"> <div class="app-footer">
<p>Last updated: <span id="app-version">2026-01-04 21:23:56 UTC</span></p> <p>Last updated: <span id="app-version">2026-01-04 21:38:40 UTC</span></p>
</div> </div>
</div> </div>

View File

@ -1357,8 +1357,8 @@ select {
} }
} }
/* Update notification popup */ /* Notification popup (shared by update and goodbye popups) */
.update-popup { .notification-popup {
position: fixed; position: fixed;
bottom: 20px; bottom: 20px;
right: 20px; right: 20px;
@ -1380,7 +1380,7 @@ select {
} }
} }
.update-popup-content { .notification-popup-content {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -1495,7 +1495,7 @@ select {
} }
@media (max-width: 480px) { @media (max-width: 480px) {
.update-popup { .notification-popup {
bottom: 10px; bottom: 10px;
right: 10px; right: 10px;
} }
@ -1518,3 +1518,21 @@ select {
padding: 8px 12px; padding: 8px 12px;
} }
} }
/* Goodbye popup progress bar */
.goodbye-progress {
width: 100%;
height: 4px;
background: #333;
border-radius: 2px;
margin-top: 10px;
overflow: hidden;
}
.goodbye-progress-bar {
height: 100%;
width: 0%;
background: #FFD700;
border-radius: 2px;
transition: width 0.1s linear;
}

2
sw.js
View File

@ -10,7 +10,7 @@ const { Strategy } = workbox.strategies;
const { CacheableResponsePlugin } = workbox.cacheableResponse; const { CacheableResponsePlugin } = workbox.cacheableResponse;
const { RangeRequestsPlugin } = workbox.rangeRequests; const { RangeRequestsPlugin } = workbox.rangeRequests;
precacheAndRoute([{"revision":"b5ab2932f88a0fd7872d344d011cb692","url":"index.html"},{"revision":"013ceb7d67293d532e979dde0347f3af","url":"cancel_off.webp"},{"revision":"bfc1563be018d82685716c6130529129","url":"cancel_on.webp"},{"revision":"d282c260fd35522036936bb6faf8ad21","url":"cdspin.gif"},{"revision":"3d820bf72b19bd4e437a61e75f317b83","url":"configure_off.webp"},{"revision":"e2c0c5e6aa1f7703c385a433a2d2a519","url":"configure_on.webp"},{"revision":"88e1e81c930d8e6c24dfdc7af274e812","url":"favicon.png"},{"revision":"d16b293eca457e2fb1e7ef2caca8c904","url":"favicon.svg"},{"revision":"d2b9c2e128ef1e5e4265c603b0bc3305","url":"free_stuff_off.webp"},{"revision":"cbc6a6779897f932c3a3c8dceb329804","url":"free_stuff_on.webp"},{"revision":"05fba4ef1884cbbd6afe09ea3325efc0","url":"install_off.webp"},{"revision":"11247e92082ba3d978a2e3785b0acf51","url":"install_on.webp"},{"revision":"d23ea8243c18eb217ef08fe607097824","url":"island.webp"},{"revision":"c97d78e159b8bff44d41e56d0aa20220","url":"isle.js"},{"revision":"5f174d45de1e3c5e0abdbccfd64567b6","url":"isle.wasm"},{"revision":"6d4248f1a08c218943e582673179b7be","url":"poster.pdf"},{"revision":"a6fcac24a24996545c039a1755af33ea","url":"read_me_off.webp"},{"revision":"aae783d064996b4322e23b092d97ea4a","url":"read_me_on.webp"},{"revision":"766a9e6e6d890f24cef252e81753b29d","url":"run_game_off.webp"},{"revision":"70208e00e9ea641e4c98699f74100db3","url":"run_game_on.webp"},{"revision":"0a65c71d9983c9bb1bc6a5f405fd6fd9","url":"shark.webp"},{"revision":"88c1fd032e6fc16814690712a26c1ede","url":"uninstall_off.webp"},{"revision":"0118a4aca04c5fb0a525bf00b001844e","url":"uninstall_on.webp"},{"revision":"5c265d887349dca70d05a7a698cbc904","url":"app.js"},{"revision":"855cf24b370f61c75532d8c2d5ed0bbd","url":"style.css"},{"revision":"060210979e13e305510de6285e085db1","url":"manifest.json"},{"revision":"4f0172bc7007d34cebf681cc233ab57f","url":"install.webp"},{"revision":"6a70d35dadf51d2ec6e38a6202d7fb0b","url":"install.mp3"},{"revision":"eac041a0b8835bfea706d997b0b7b224","url":"downloader.js"},{"revision":"6899f72755d4e84c707b93ac54a8fb06","url":"debug.js"},{"revision":"7817b36ddda9f07797c05a0ff6cacb21","url":"debug.html"},{"revision":"4ea2aac9446188b8a588811bc593919e","url":"ogel.webp"},{"revision":"c57d24598537443c5b8276c8dd5dbdc9","url":"bonus.webp"},{"revision":"d11c8c893d5525c8842555dc2861c393","url":"callfail.webp"},{"revision":"be9a89fb567b632cf8d4661cbf8afd9e","url":"getinfo.webp"},{"revision":"fe986681f41e96631f39f3288b23e538","url":"sysinfo.webp"},{"revision":"4ec902e0b0ce60ffd9dd565c9ddf40a1","url":"send.webp"},{"revision":"81f3c8fc38b876dc2fcfeefaadad1d1b","url":"congrats.webp"},{"revision":"f906318cb87e09a819e5916676caab2e","url":"register.webp"},{"revision":"d149d5709ac00fd5e2967ab4f3d74886","url":"comic.pdf"}]); precacheAndRoute([{"revision":"483fcf29a509ff4578512ce6fd42194d","url":"index.html"},{"revision":"013ceb7d67293d532e979dde0347f3af","url":"cancel_off.webp"},{"revision":"bfc1563be018d82685716c6130529129","url":"cancel_on.webp"},{"revision":"d282c260fd35522036936bb6faf8ad21","url":"cdspin.gif"},{"revision":"3d820bf72b19bd4e437a61e75f317b83","url":"configure_off.webp"},{"revision":"e2c0c5e6aa1f7703c385a433a2d2a519","url":"configure_on.webp"},{"revision":"88e1e81c930d8e6c24dfdc7af274e812","url":"favicon.png"},{"revision":"d16b293eca457e2fb1e7ef2caca8c904","url":"favicon.svg"},{"revision":"d2b9c2e128ef1e5e4265c603b0bc3305","url":"free_stuff_off.webp"},{"revision":"cbc6a6779897f932c3a3c8dceb329804","url":"free_stuff_on.webp"},{"revision":"05fba4ef1884cbbd6afe09ea3325efc0","url":"install_off.webp"},{"revision":"11247e92082ba3d978a2e3785b0acf51","url":"install_on.webp"},{"revision":"d23ea8243c18eb217ef08fe607097824","url":"island.webp"},{"revision":"c97d78e159b8bff44d41e56d0aa20220","url":"isle.js"},{"revision":"5f174d45de1e3c5e0abdbccfd64567b6","url":"isle.wasm"},{"revision":"6d4248f1a08c218943e582673179b7be","url":"poster.pdf"},{"revision":"a6fcac24a24996545c039a1755af33ea","url":"read_me_off.webp"},{"revision":"aae783d064996b4322e23b092d97ea4a","url":"read_me_on.webp"},{"revision":"766a9e6e6d890f24cef252e81753b29d","url":"run_game_off.webp"},{"revision":"70208e00e9ea641e4c98699f74100db3","url":"run_game_on.webp"},{"revision":"0a65c71d9983c9bb1bc6a5f405fd6fd9","url":"shark.webp"},{"revision":"88c1fd032e6fc16814690712a26c1ede","url":"uninstall_off.webp"},{"revision":"0118a4aca04c5fb0a525bf00b001844e","url":"uninstall_on.webp"},{"revision":"008f544b125d0d595af8fffc2d86103d","url":"app.js"},{"revision":"8f37e9eaff5601153c160f0c8a9ab00e","url":"style.css"},{"revision":"060210979e13e305510de6285e085db1","url":"manifest.json"},{"revision":"4f0172bc7007d34cebf681cc233ab57f","url":"install.webp"},{"revision":"6a70d35dadf51d2ec6e38a6202d7fb0b","url":"install.mp3"},{"revision":"eac041a0b8835bfea706d997b0b7b224","url":"downloader.js"},{"revision":"6899f72755d4e84c707b93ac54a8fb06","url":"debug.js"},{"revision":"7817b36ddda9f07797c05a0ff6cacb21","url":"debug.html"},{"revision":"4ea2aac9446188b8a588811bc593919e","url":"ogel.webp"},{"revision":"c57d24598537443c5b8276c8dd5dbdc9","url":"bonus.webp"},{"revision":"d11c8c893d5525c8842555dc2861c393","url":"callfail.webp"},{"revision":"be9a89fb567b632cf8d4661cbf8afd9e","url":"getinfo.webp"},{"revision":"fe986681f41e96631f39f3288b23e538","url":"sysinfo.webp"},{"revision":"4ec902e0b0ce60ffd9dd565c9ddf40a1","url":"send.webp"},{"revision":"81f3c8fc38b876dc2fcfeefaadad1d1b","url":"congrats.webp"},{"revision":"f906318cb87e09a819e5916676caab2e","url":"register.webp"},{"revision":"c633a7500e6f30162bf1cf4ec4e95a6d","url":"later.webp"},{"revision":"d149d5709ac00fd5e2967ab4f3d74886","url":"comic.pdf"}]);
const gameFiles = [ const gameFiles = [
"/LEGO/Scripts/CREDITS.SI", "/LEGO/Scripts/INTRO.SI", "/LEGO/Scripts/NOCD.SI", "/LEGO/Scripts/SNDANIM.SI", "/LEGO/Scripts/CREDITS.SI", "/LEGO/Scripts/INTRO.SI", "/LEGO/Scripts/NOCD.SI", "/LEGO/Scripts/SNDANIM.SI",