Installable as an app (PWA): manifests, offline-only service worker, icons
This commit is contained in:
parent
b26360e8f3
commit
44708d5f3c
16 changed files with 246 additions and 0 deletions
|
|
@ -3,6 +3,10 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#1b1e25">
|
||||
<link rel="manifest" href="/admin.webmanifest">
|
||||
<link rel="icon" href="/static/icon.svg" type="image/svg+xml">
|
||||
<link rel="apple-touch-icon" href="/static/apple-touch-icon.png">
|
||||
<title>Staff panel</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
|
|
|
|||
BIN
internal/web/assets/apple-touch-icon.png
Normal file
BIN
internal/web/assets/apple-touch-icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
|
|
@ -165,3 +165,6 @@ function toast(msg) {
|
|||
}
|
||||
|
||||
const steamProfile = (sid) => `https://steamcommunity.com/profiles/${encodeURIComponent(sid)}`;
|
||||
|
||||
// The service worker makes the site installable as an app (see sw.js).
|
||||
if ("serviceWorker" in navigator) navigator.serviceWorker.register("/sw.js").catch(() => {});
|
||||
|
|
|
|||
BIN
internal/web/assets/icon-192.png
Normal file
BIN
internal/web/assets/icon-192.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.8 KiB |
BIN
internal/web/assets/icon-512.png
Normal file
BIN
internal/web/assets/icon-512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
internal/web/assets/icon-maskable-512.png
Normal file
BIN
internal/web/assets/icon-maskable-512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.7 KiB |
7
internal/web/assets/icon-maskable.svg
Normal file
7
internal/web/assets/icon-maskable.svg
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<rect width="512" height="512" fill="#14161b"/>
|
||||
<g transform="translate(112 112) scale(9)">
|
||||
<path d="M16 2 28 7v9c0 7-5 12-12 14C9 28 4 23 4 16V7z" fill="none" stroke="#fe113d" stroke-width="2.5"/>
|
||||
<path d="M11 16h10M16 11v10" stroke="#e6e8ee" stroke-width="2.5" stroke-linecap="round"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 377 B |
7
internal/web/assets/icon.svg
Normal file
7
internal/web/assets/icon.svg
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<rect width="512" height="512" rx="112" fill="#14161b"/>
|
||||
<g transform="translate(64 64) scale(12)">
|
||||
<path d="M16 2 28 7v9c0 7-5 12-12 14C9 28 4 23 4 16V7z" fill="none" stroke="#fe113d" stroke-width="2.5"/>
|
||||
<path d="M11 16h10M16 11v10" stroke="#e6e8ee" stroke-width="2.5" stroke-linecap="round"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 385 B |
55
internal/web/assets/offline.html
Normal file
55
internal/web/assets/offline.html
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#1b1e25">
|
||||
<!-- Served in place of whatever page failed to load, so a refresh retries that page. -->
|
||||
<meta http-equiv="refresh" content="15">
|
||||
<title>Offline</title>
|
||||
<!-- Self-contained: nothing else is cached, so styles.css and the fonts can't load from here. -->
|
||||
<style>
|
||||
html, body { margin: 0; height: 100%; }
|
||||
body {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
padding: 16px;
|
||||
background: #14161b;
|
||||
color: #e6e8ee;
|
||||
font: 16px/1.5 system-ui, sans-serif;
|
||||
color-scheme: dark;
|
||||
}
|
||||
main {
|
||||
max-width: 360px;
|
||||
padding: 32px 24px;
|
||||
text-align: center;
|
||||
background: #1b1e25;
|
||||
border: 1px solid #2e333f;
|
||||
border-radius: 12px;
|
||||
}
|
||||
svg { width: 48px; height: 48px; }
|
||||
h1 { margin: 12px 0 4px; font-size: 22px; }
|
||||
p { margin: 0 0 20px; color: #8a91a0; }
|
||||
a {
|
||||
display: inline-block;
|
||||
padding: 8px 18px;
|
||||
background: #fe113d;
|
||||
color: #fff;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<svg viewBox="0 0 32 32" aria-hidden="true">
|
||||
<path d="M16 2 28 7v9c0 7-5 12-12 14C9 28 4 23 4 16V7z" fill="none" stroke="#fe113d" stroke-width="2.5"/>
|
||||
<path d="M11 16h10M16 11v10" stroke="#e6e8ee" stroke-width="2.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
<h1>Can't reach the panel</h1>
|
||||
<p>Check your connection. This page tries again by itself every few seconds.</p>
|
||||
<a href="">Try again</a>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -3,6 +3,10 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#1b1e25">
|
||||
<link rel="manifest" href="/manifest.webmanifest">
|
||||
<link rel="icon" href="/static/icon.svg" type="image/svg+xml">
|
||||
<link rel="apple-touch-icon" href="/static/apple-touch-icon.png">
|
||||
<title>Bans and staff</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,10 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#1b1e25">
|
||||
<link rel="manifest" href="/admin.webmanifest">
|
||||
<link rel="icon" href="/static/icon.svg" type="image/svg+xml">
|
||||
<link rel="apple-touch-icon" href="/static/apple-touch-icon.png">
|
||||
<title>Staff sign in</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
|
|
|
|||
23
internal/web/assets/sw.js
Normal file
23
internal/web/assets/sw.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// The service worker is what lets the site be installed as an app. It caches nothing but the
|
||||
// offline page: every request still goes to the network, so nobody sees stale bans or ranks.
|
||||
|
||||
const CACHE = "offline-v1";
|
||||
const OFFLINE = "/static/offline.html";
|
||||
|
||||
self.addEventListener("install", (e) => {
|
||||
e.waitUntil(caches.open(CACHE).then((c) => c.add(OFFLINE)).then(() => self.skipWaiting()));
|
||||
});
|
||||
|
||||
self.addEventListener("activate", (e) => {
|
||||
e.waitUntil(
|
||||
caches.keys()
|
||||
.then((keys) => Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k))))
|
||||
.then(() => self.clients.claim()),
|
||||
);
|
||||
});
|
||||
|
||||
// Only page loads get the offline page; API calls fail as they always have, and the pages say so.
|
||||
self.addEventListener("fetch", (e) => {
|
||||
if (e.request.mode !== "navigate") return;
|
||||
e.respondWith(fetch(e.request).catch(() => caches.match(OFFLINE)));
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue