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

View file

@ -0,0 +1,64 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.buildScopeIIFE = buildScopeIIFE;
exports.collectShadowedParamsNames = collectShadowedParamsNames;
exports.iifeVisitor = void 0;
var _core = require("@babel/core");
const iifeVisitor = exports.iifeVisitor = {
"ReferencedIdentifier|BindingIdentifier"(path, state) {
const {
scope,
node
} = path;
const {
name
} = node;
if (name === "eval" || scope.getBinding(name) === state.scope.parent.getBinding(name) && state.scope.hasOwnBinding(name)) {
state.needsOuterBinding = true;
path.stop();
}
},
"TypeAnnotation|TSTypeAnnotation|TypeParameterDeclaration|TSTypeParameterDeclaration": path => path.skip()
};
function collectShadowedParamsNames(param, functionScope, shadowedParams) {
for (const name of Object.keys(param.getBindingIdentifiers())) {
var _functionScope$bindin;
const constantViolations = (_functionScope$bindin = functionScope.bindings[name]) == null ? void 0 : _functionScope$bindin.constantViolations;
if (constantViolations) {
for (const redeclarator of constantViolations) {
const node = redeclarator.node;
switch (node.type) {
case "VariableDeclarator":
{
if (node.init === null) {
const declaration = redeclarator.parentPath;
if (!declaration.parentPath.isFor() || declaration.parentPath.get("body") === declaration) {
redeclarator.remove();
break;
}
}
shadowedParams.add(name);
break;
}
case "FunctionDeclaration":
shadowedParams.add(name);
break;
}
}
}
}
}
function buildScopeIIFE(shadowedParams, body) {
const args = [];
const params = [];
for (const name of shadowedParams) {
args.push(_core.types.identifier(name));
params.push(_core.types.identifier(name));
}
return _core.types.returnStatement(_core.types.callExpression(_core.types.arrowFunctionExpression(params, body), args));
}
//# sourceMappingURL=shadow-utils.js.map