Add progressive web app companion for cross-platform access

Vite + TypeScript PWA that mirrors the Android app's core features:
- Pre-processed shelter data (build-time UTM33N→WGS84 conversion)
- Leaflet map with shelter markers, user location, and offline tiles
- Canvas compass arrow (ported from DirectionArrowView.kt)
- IndexedDB shelter cache with 7-day staleness check
- Service worker with CacheFirst tiles and precached app shell
- i18n for en, nb, nn (ported from Android strings.xml)
- iOS/Android compass handling with low-pass filter
- Respects user map interaction (no auto-snap on pan/zoom)
- Build revision cache-breaker for reliable SW updates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ole-Morten Duesund 2026-03-08 17:41:38 +01:00
commit e8428de775
12051 changed files with 1799735 additions and 0 deletions

105
pwa/node_modules/workbox-build/build/generate-sw.js generated vendored Normal file
View file

@ -0,0 +1,105 @@
"use strict";
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateSW = void 0;
const upath_1 = __importDefault(require("upath"));
const get_file_manifest_entries_1 = require("./lib/get-file-manifest-entries");
const rebase_path_1 = require("./lib/rebase-path");
const validate_options_1 = require("./lib/validate-options");
const write_sw_using_default_template_1 = require("./lib/write-sw-using-default-template");
/**
* This method creates a list of URLs to precache, referred to as a "precache
* manifest", based on the options you provide.
*
* It also takes in additional options that configures the service worker's
* behavior, like any `runtimeCaching` rules it should use.
*
* Based on the precache manifest and the additional configuration, it writes
* a ready-to-use service worker file to disk at `swDest`.
*
* ```
* // The following lists some common options; see the rest of the documentation
* // for the full set of options and defaults.
* const {count, size, warnings} = await generateSW({
* dontCacheBustURLsMatching: [new RegExp('...')],
* globDirectory: '...',
* globPatterns: ['...', '...'],
* maximumFileSizeToCacheInBytes: ...,
* navigateFallback: '...',
* runtimeCaching: [{
* // Routing via a matchCallback function:
* urlPattern: ({request, url}) => ...,
* handler: '...',
* options: {
* cacheName: '...',
* expiration: {
* maxEntries: ...,
* },
* },
* }, {
* // Routing via a RegExp:
* urlPattern: new RegExp('...'),
* handler: '...',
* options: {
* cacheName: '...',
* plugins: [..., ...],
* },
* }],
* skipWaiting: ...,
* swDest: '...',
* });
* ```
*
* @memberof workbox-build
*/
async function generateSW(config) {
const options = (0, validate_options_1.validateGenerateSWOptions)(config);
let entriesResult;
if (options.globDirectory) {
// Make sure we leave swDest out of the precache manifest.
options.globIgnores.push((0, rebase_path_1.rebasePath)({
baseDirectory: options.globDirectory,
file: options.swDest,
}));
// If we create an extra external runtime file, ignore that, too.
// See https://rollupjs.org/guide/en/#outputchunkfilenames for naming.
if (!options.inlineWorkboxRuntime) {
const swDestDir = upath_1.default.dirname(options.swDest);
const workboxRuntimeFile = upath_1.default.join(swDestDir, 'workbox-*.js');
options.globIgnores.push((0, rebase_path_1.rebasePath)({
baseDirectory: options.globDirectory,
file: workboxRuntimeFile,
}));
}
// We've previously asserted that options.globDirectory is set, so this
// should be a safe cast.
entriesResult = await (0, get_file_manifest_entries_1.getFileManifestEntries)(options);
}
else {
entriesResult = {
count: 0,
manifestEntries: [],
size: 0,
warnings: [],
};
}
const filePaths = await (0, write_sw_using_default_template_1.writeSWUsingDefaultTemplate)(Object.assign({
manifestEntries: entriesResult.manifestEntries,
}, options));
return {
filePaths,
count: entriesResult.count,
size: entriesResult.size,
warnings: entriesResult.warnings,
};
}
exports.generateSW = generateSW;