Compare commits

..

3 Commits

Author SHA1 Message Date
Ettore
70691dcd4a Add install banner 2026-05-06 18:35:29 +02:00
Ettore
a7ccada0b5 Update manifest 2026-05-06 18:35:19 +02:00
Ettore
7617af10a9 Update icons 2026-05-06 18:34:42 +02:00
7 changed files with 118 additions and 6 deletions

View File

@@ -187,3 +187,34 @@ document.getElementById("logout-btn").addEventListener("click", () => {
if ("serviceWorker" in navigator) { if ("serviceWorker" in navigator) {
navigator.serviceWorker.register("/sw.js").catch(() => {}); navigator.serviceWorker.register("/sw.js").catch(() => {});
} }
// ── PWA install banner ────────────────────────────────────────────────────────
const INSTALL_DISMISSED_KEY = "lg_install_dismissed";
let _deferredInstallPrompt = null;
window.addEventListener("beforeinstallprompt", (e) => {
e.preventDefault();
if (sessionStorage.getItem(INSTALL_DISMISSED_KEY)) return;
_deferredInstallPrompt = e;
document.getElementById("install-banner").classList.remove("hidden");
});
document.getElementById("install-btn").addEventListener("click", async () => {
const banner = document.getElementById("install-banner");
banner.classList.add("hidden");
if (!_deferredInstallPrompt) return;
_deferredInstallPrompt.prompt();
await _deferredInstallPrompt.userChoice;
_deferredInstallPrompt = null;
});
document.getElementById("install-dismiss").addEventListener("click", () => {
document.getElementById("install-banner").classList.add("hidden");
sessionStorage.setItem(INSTALL_DISMISSED_KEY, "1");
_deferredInstallPrompt = null;
});
window.addEventListener("appinstalled", () => {
document.getElementById("install-banner").classList.add("hidden");
_deferredInstallPrompt = null;
});

View File

@@ -9,7 +9,7 @@
<title>Lagomare Gates</title> <title>Lagomare Gates</title>
<link rel="manifest" href="/manifest.json" /> <link rel="manifest" href="/manifest.json" />
<link rel="icon" type="image/svg+xml" href="/static/logo.svg" /> <link rel="icon" type="image/svg+xml" href="/static/logo.svg" />
<link rel="apple-touch-icon" href="/static/logo.svg" /> <link rel="apple-touch-icon" href="/static/mobile_icon.png" />
<link rel="stylesheet" href="/static/style.css" /> <link rel="stylesheet" href="/static/style.css" />
<style> <style>
@@ -143,6 +143,21 @@
</div> </div>
</div> </div>
<!-- ── PWA install banner ──────────────────────────────────────────────── -->
<div id="install-banner" class="install-banner hidden" role="banner" aria-label="Install app">
<div class="install-banner-body">
<img src="/static/logo.svg" alt="" class="install-banner-icon" />
<div class="install-banner-text">
<strong>Add to Home Screen</strong>
<span>Install Lagomare Gates for quick access</span>
</div>
</div>
<div class="install-banner-actions">
<button id="install-dismiss" class="btn btn-ghost" style="font-size:.8rem;padding:.45rem .9rem">Later</button>
<button id="install-btn" class="btn btn-primary" style="font-size:.8rem;padding:.45rem .9rem">Install</button>
</div>
</div>
<script src="/static/app.js"></script> <script src="/static/app.js"></script>
</body> </body>
</html> </html>

View File

@@ -3,6 +3,7 @@
"short_name": "Lagomare Gates", "short_name": "Lagomare Gates",
"description": "Gates control panel for Lagomare residential complex", "description": "Gates control panel for Lagomare residential complex",
"start_url": "/", "start_url": "/",
"scope": "/",
"display": "standalone", "display": "standalone",
"orientation": "portrait", "orientation": "portrait",
"background_color": "#00541eff", "background_color": "#00541eff",
@@ -10,9 +11,10 @@
"icons": [ "icons": [
{ {
"src": "/static/mobile_icon.png", "src": "/static/mobile_icon.png",
"sizes": "any", "sizes": "512x512",
"type": "image/png", "type": "image/png",
"purpose": "any maskable" "purpose": "any maskable"
} }
] ],
"lang": "en"
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -31,7 +31,7 @@
inkscape:cy="507.14579" inkscape:cy="507.14579"
inkscape:window-width="1912" inkscape:window-width="1912"
inkscape:window-height="1012" inkscape:window-height="1012"
inkscape:window-x="4" inkscape:window-x="1924"
inkscape:window-y="64" inkscape:window-y="64"
inkscape:window-maximized="1" inkscape:window-maximized="1"
inkscape:current-layer="g17635" inkscape:current-layer="g17635"
@@ -55,7 +55,7 @@
style="fill:#ffffff;fill-opacity:1;stroke-width:0.255884" style="fill:#ffffff;fill-opacity:1;stroke-width:0.255884"
d="M 105.30402,43.804442 A 100.90167,103.06385 0 0 0 4.40222,146.86825 100.90167,103.06385 0 0 0 11.912894,185.88737 L 197.0311,189.80848 A 100.90167,103.06385 0 0 0 206.20581,146.86825 100.90167,103.06385 0 0 0 105.30402,43.804442 Z" /><path d="M 105.30402,43.804442 A 100.90167,103.06385 0 0 0 4.40222,146.86825 100.90167,103.06385 0 0 0 11.912894,185.88737 L 197.0311,189.80848 A 100.90167,103.06385 0 0 0 206.20581,146.86825 100.90167,103.06385 0 0 0 105.30402,43.804442 Z" /><path
style="fill:#0076be;stroke-width:0.880051" style="fill:#0076be;stroke-width:0.880051"
d="m 107.60824,253.29064 c -14.88064,-1.2116 -27.606893,-4.7687 -39.442915,-11.02465 -4.643166,-2.45415 -4.720225,-2.23564 0.846124,-2.3993 11.377634,-0.33453 24.626748,-2.61947 45.446491,-7.83772 25.66298,-6.43216 42.79573,-7.85659 60.01309,-4.9895 5.56456,0.92663 5.59998,0.1768 -0.23855,5.04966 -4.16646,3.47733 -18.47145,13.55865 -35.35369,18.07963 -9.63076,2.57909 -22.34618,3.84852 -31.27055,3.12188 z M 54.394081,235.2651 c -7.413545,-0.32531 -16.487447,-1.76309 -23.392436,-3.70655 -3.285719,-0.92479 -10.211659,-3.21649 -9.779565,-3.23592 0.128066,-0.006 1.647391,0.14443 3.376279,0.33374 20.054478,2.19601 48.412809,-0.93296 79.289971,-8.74859 33.67408,-8.52359 48.89413,-9.4867 75.20387,-4.75882 2.82523,0.5077 9.4911,1.86628 10.28297,2.09578 0.14881,0.0431 -0.26578,0.71591 -0.9861,1.43247 -1.54261,1.53457 -2.24211,2.10968 -3.36599,3.23152 -1.30825,1.32685 -1.59883,1.51542 -2.20532,1.43118 -0.3842,-0.0533 -2.27026,-0.37033 -4.19125,-0.70435 -11.5675,-2.01137 -24.59896,-2.50704 -35.15986,-1.33737 -12.35708,1.3686 -17.45465,2.32178 -33.06425,6.18264 -22.349546,5.52789 -32.001312,7.2194 -44.473737,7.79422 -5.537099,0.25519 -5.491485,0.25523 -11.534582,-0.01 z" d="m 101.2582,253.29064 c -14.880604,-1.2116 -27.606857,-4.7687 -39.442879,-11.02465 -4.643166,-2.45415 -4.720225,-2.23564 0.846124,-2.3993 11.377634,-0.33453 24.626748,-2.61947 45.446455,-7.83772 25.66298,-6.43216 42.79573,-7.85659 60.01309,-4.9895 5.56456,0.92663 5.59998,0.1768 -0.23855,5.04966 -4.16646,3.47733 -18.47145,13.55865 -35.35369,18.07963 -9.63076,2.57909 -22.34618,3.84852 -31.27055,3.12188 z M 48.044077,235.2651 c -7.413545,-0.32531 -16.487447,-1.76309 -23.392436,-3.70655 -3.285719,-0.92479 -10.211659,-3.21649 -9.779565,-3.23592 0.128066,-0.006 1.647391,0.14443 3.376279,0.33374 20.054478,2.19601 48.412809,-0.93296 79.28995,-8.74859 33.674065,-8.52359 48.894115,-9.4867 75.203855,-4.75882 2.82523,0.5077 9.4911,1.86628 10.28297,2.09578 0.14881,0.0431 -0.26578,0.71591 -0.9861,1.43247 -1.54261,1.53457 -2.24211,2.10968 -3.36599,3.23152 -1.30825,1.32685 -1.59883,1.51542 -2.20532,1.43118 -0.3842,-0.0533 -2.27026,-0.37033 -4.19125,-0.70435 -11.5675,-2.01137 -24.59896,-2.50704 -35.15986,-1.33737 -12.35708,1.3686 -17.45465,2.32178 -33.06425,6.18264 -22.34951,5.52789 -32.001276,7.2194 -44.473701,7.79422 -5.537099,0.25519 -5.491485,0.25523 -11.534582,-0.01 z"
id="path17636" id="path17636"
sodipodi:nodetypes="sssssssssscsssssssssssss" /><path sodipodi:nodetypes="sssssssssscsssssssssssss" /><path
style="fill:#018133;stroke:#018133;stroke-width:0.880051;stroke-opacity:1" style="fill:#018133;stroke:#018133;stroke-width:0.880051;stroke-opacity:1"

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@@ -189,3 +189,67 @@ tr:last-child td { border-bottom: none; }
/* ── Error text ────────────────────────────────────────────────────────────── */ /* ── Error text ────────────────────────────────────────────────────────────── */
.error-msg { color: var(--red); font-size: .85rem; margin-top: .5rem; } .error-msg { color: var(--red); font-size: .85rem; margin-top: .5rem; }
/* ── PWA install banner ────────────────────────────────────────────────────── */
.install-banner {
position: fixed;
bottom: 1rem;
left: 50%;
transform: translateX(-50%);
width: calc(100% - 2rem);
max-width: 480px;
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
box-shadow: var(--shadow);
padding: .9rem 1rem;
display: flex;
align-items: center;
justify-content: space-between;
gap: .75rem;
z-index: 9000;
animation: banner-in .3s ease;
}
.install-banner.hidden { display: none !important; }
.install-banner-body {
display: flex;
align-items: center;
gap: .75rem;
flex: 1;
min-width: 0;
}
.install-banner-icon {
width: 36px;
height: 36px;
object-fit: contain;
flex-shrink: 0;
}
.install-banner-text {
display: flex;
flex-direction: column;
gap: .1rem;
min-width: 0;
}
.install-banner-text strong {
font-size: .9rem;
font-weight: 700;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.install-banner-text span {
font-size: .78rem;
color: var(--text-muted);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.install-banner-actions {
display: flex;
gap: .5rem;
flex-shrink: 0;
}
@keyframes banner-in {
from { opacity: 0; transform: translateX(-50%) translateY(1rem); }
to { opacity: 1; transform: translateX(-50%) translateY(0); }
}

View File

@@ -1,6 +1,6 @@
/* Service worker - Lagomare Gates */ /* Service worker - Lagomare Gates */
const CACHE = "lagomare-gates-v1"; const CACHE = "lagomare-gates-v1";
const PRECACHE = ["/", "/static/style.css", "/static/app.js", "/static/logo.svg", "/static/mobile_icon.svg", "/static/mobile_icon.png", "/manifest.json"]; const PRECACHE = ["/", "/static/style.css", "/static/app.js", "/static/logo.svg", "/static/mobile_icon.png", "/manifest.json"];
self.addEventListener("install", event => { self.addEventListener("install", event => {
event.waitUntil( event.waitUntil(