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

51
pwa/node_modules/@vitest/mocker/dist/browser.d.ts generated vendored Normal file
View file

@ -0,0 +1,51 @@
import { M as ModuleMockerInterceptor } from './mocker-pQgp1HFr.js';
export { C as CompilerHintsOptions, b as ModuleMocker, a as ModuleMockerCompilerHints, d as ModuleMockerConfig, e as ModuleMockerRPC, R as ResolveIdResult, f as ResolveMockResul, c as createCompilerHints } from './mocker-pQgp1HFr.js';
import { StartOptions, SetupWorker } from 'msw/browser';
import { c as MockerRegistry, g as MockedModule } from './types-DZOqTgiN.js';
import '@vitest/spy';
interface ModuleMockerMSWInterceptorOptions {
/**
* The identifier to access the globalThis object in the worker.
* This will be injected into the script as is, so make sure it's a valid JS expression.
* @example
* ```js
* // globalThisAccessor: '__my_variable__' produces:
* globalThis[__my_variable__]
* // globalThisAccessor: 'Symbol.for('secret:mocks')' produces:
* globalThis[Symbol.for('secret:mocks')]
* // globalThisAccessor: '"__vitest_mocker__"' (notice quotes) produces:
* globalThis["__vitest_mocker__"]
* ```
* @default `"__vitest_mocker__"`
*/
globalThisAccessor?: string;
/**
* Options passed down to `msw.setupWorker().start(options)`
*/
mswOptions?: StartOptions;
/**
* A pre-configured `msw.setupWorker` instance.
*/
mswWorker?: SetupWorker;
}
declare class ModuleMockerMSWInterceptor implements ModuleMockerInterceptor {
private readonly options;
protected readonly mocks: MockerRegistry;
private startPromise;
private worker;
constructor(options?: ModuleMockerMSWInterceptorOptions);
register(module: MockedModule): Promise<void>;
delete(url: string): Promise<void>;
invalidate(): void;
private resolveManualMock;
protected init(): Promise<SetupWorker>;
}
declare class ModuleMockerServerInterceptor implements ModuleMockerInterceptor {
register(module: MockedModule): Promise<void>;
delete(id: string): Promise<void>;
invalidate(): void;
}
export { ModuleMockerInterceptor, ModuleMockerMSWInterceptor, type ModuleMockerMSWInterceptorOptions, ModuleMockerServerInterceptor };