tilfluktsrom/pwa/index.html
Ole-Morten Duesund c603e81b2a PWA: synleg del-ikon og ekte autoupdate utan å avbryte aktiv bruk
- Bytt del-knappen frå tekstpila ↪ til ein innebygd Material-stil
  SVG (20×20). Den førre Unicode-pila vart teikna mykje mindre enn
  ℹ og ↻ av dei fleste fontar — no har alle tre ikona same visuelle
  vekt på tvers av nettlesarar og operativsystem.
- Lagt til ein controllerchange-lyttar som utløyser ein omlasting
  *neste* gong appen vert lagt i bakgrunnen (visibilityState ===
  'hidden'), ikkje umiddelbart. Slik tek nye distribusjonar effekt
  utan brukarinngrep, men utan å rive vekk skjermen midt i ein
  tilfluktsromnavigering. registerType: 'autoUpdate' åleine sørgjer
  for at den nye SW-en skipWaiting + clientsClaim, men det reload-ar
  ikkje den allereie køyrande JavaScripten — denne lyttaren stettar
  det utan å bryte noregisseringsflyt.

Påverkar ikkje fråkopla bruk: omlasting skjer berre etter at ein ny
SW har vorte aktivert, og ein ny SW kan berre installerast medan
nettverket er tilgjengeleg. Sjølve omlastinga løyser alle ressursar
frå presjekken og fungerer fråkopla.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 16:28:31 +02:00

80 lines
3.9 KiB
HTML

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8" />
<!-- WCAG 1.4.4 Resize Text: do not pin maximum-scale or disable user-scalable.
Leaflet handles its own touch gestures on the map; the rest of the page
(status bar, bottom sheet, dialogs) must remain zoomable for low-vision users. -->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#1A1A2E" />
<meta name="description" content="Find the nearest public shelter in Norway" />
<!-- iOS home-screen/PWA integration: run in standalone mode, dark status bar, correct label. -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="apple-mobile-web-app-title" content="Tilfluktsrom" />
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://*.tile.openstreetmap.org; connect-src 'self' https://*.tile.openstreetmap.org; font-src 'self'; worker-src 'self'" />
<title>Tilfluktsrom</title>
<link rel="manifest" href="manifest.webmanifest" />
<link rel="icon" type="image/png" sizes="192x192" href="icons/icon-192.png" />
<link rel="apple-touch-icon" href="icons/icon-192.png" />
</head>
<body>
<div id="app">
<!-- Status bar -->
<header id="status-bar" role="banner">
<span id="status-text" aria-live="polite"></span>
<button id="about-btn" aria-label="About">&#x2139;</button>
<button id="share-btn" aria-label="Share shelter">
<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor" aria-hidden="true" focusable="false">
<path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92s2.92-1.31 2.92-2.92-1.31-2.92-2.92-2.92z"/>
</svg>
</button>
<button id="refresh-btn" aria-label="Refresh data">&#x21bb;</button>
</header>
<!-- Main content: map or compass -->
<main id="main-content">
<div id="map-container" role="application" aria-label="Map"></div>
<div id="compass-container" role="img" aria-label="Compass">
<span id="compass-address"></span>
<span id="compass-distance" aria-live="polite"></span>
</div>
<!-- Toggle map/compass FAB -->
<button id="toggle-fab" aria-label="Toggle map/compass view">&#x1F9ED;</button>
<!-- Reset view button -->
<button id="reset-view-btn" aria-label="Reset view">&#x2316;</button>
</main>
<!-- No-cache warning banner -->
<div id="no-cache-banner" role="alert">
<span id="no-cache-text"></span>
<button id="cache-retry-btn"></button>
</div>
<!-- Bottom sheet with shelter info -->
<aside id="bottom-sheet" aria-label="Shelter info">
<div id="selected-shelter" aria-live="polite">
<canvas id="mini-arrow" width="96" height="96" role="img" aria-label="Direction to shelter"></canvas>
<div id="selected-shelter-info">
<div id="selected-shelter-address"></div>
<div id="selected-shelter-details"></div>
</div>
</div>
<div id="shelter-list" role="list" aria-label="Nearest shelters"></div>
</aside>
</div>
<!-- Loading overlay -->
<div id="loading-overlay" role="dialog" aria-modal="true" aria-label="Loading">
<div id="loading-spinner" aria-hidden="true"></div>
<div id="loading-text" aria-live="assertive" tabindex="-1"></div>
<div id="loading-button-row">
<button id="loading-skip-btn"></button>
<button id="loading-ok-btn"></button>
</div>
</div>
<script type="module" src="src/main.ts"></script>
</body>
</html>