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:
parent
46365b713b
commit
e8428de775
12051 changed files with 1799735 additions and 0 deletions
136
pwa/node_modules/leaflet.offline/test/TileLayerTest.ts
generated
vendored
Normal file
136
pwa/node_modules/leaflet.offline/test/TileLayerTest.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
import { Bounds, Point } from 'leaflet';
|
||||
import { assert } from 'chai';
|
||||
import { TileLayerOffline } from '../src/TileLayerOffline';
|
||||
|
||||
describe('TileLayer.Offline', () => {
|
||||
it('createTile', () => {
|
||||
const url = 'http://a.tile.openstreetmap.org/{z}/{x}/{y}.png';
|
||||
const layer = new TileLayerOffline(url);
|
||||
// @ts-ignore
|
||||
const tile = layer.createTile({ x: 123456, y: 456789, z: 16 }, () => {});
|
||||
assert.instanceOf(tile, HTMLElement);
|
||||
});
|
||||
it('get storagekey openstreetmap', () => {
|
||||
const layer = new TileLayerOffline(
|
||||
'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
);
|
||||
const key = layer._getStorageKey({ z: 16, x: 123456, y: 456789 });
|
||||
assert.equal(key, 'http://a.tile.openstreetmap.org/16/123456/456789.png');
|
||||
});
|
||||
it('get storagekey cartodb', () => {
|
||||
const layer = new TileLayerOffline(
|
||||
'https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png',
|
||||
);
|
||||
const key = layer._getStorageKey({ z: 16, x: 123456, y: 456789 });
|
||||
assert.equal(
|
||||
key,
|
||||
'https://cartodb-basemaps-a.global.ssl.fastly.net/light_all/16/123456/456789.png',
|
||||
);
|
||||
});
|
||||
it('get storagekey mapbox with accessToken', () => {
|
||||
const layer = new TileLayerOffline(
|
||||
'https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}',
|
||||
{
|
||||
id: 'mapbox.streets',
|
||||
accessToken: 'xyz',
|
||||
},
|
||||
);
|
||||
const key = layer._getStorageKey({ z: 16, x: 123456, y: 456789 });
|
||||
assert.equal(
|
||||
key,
|
||||
'https://api.tiles.mapbox.com/v4/mapbox.streets/16/123456/456789.png?access_token=xyz',
|
||||
);
|
||||
});
|
||||
it('calculates tiles at level 16', () => {
|
||||
const layer = new TileLayerOffline(
|
||||
'http://a.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
);
|
||||
const bounds = new Bounds(
|
||||
new Point(8621975, 5543267.999999999),
|
||||
new Point(8621275, 5542538),
|
||||
);
|
||||
const tiles = layer.getTileUrls(bounds, 16);
|
||||
assert.lengthOf(tiles, 16);
|
||||
const urls = tiles.map((t) => t.url);
|
||||
assert.include(urls, 'http://a.tile.openstreetmap.org/16/33677/21651.png');
|
||||
const keys = tiles.map((t) => t.key);
|
||||
assert.include(keys, 'http://a.tile.openstreetmap.org/16/33677/21651.png');
|
||||
});
|
||||
|
||||
it('calculates tile urls,keys at level 16 with subdomains', () => {
|
||||
const layer = new TileLayerOffline(
|
||||
'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
);
|
||||
const bounds = new Bounds(
|
||||
new Point(8621975, 5543267.999999999),
|
||||
new Point(8621275, 5542538),
|
||||
);
|
||||
const tiles = layer.getTileUrls(bounds, 16);
|
||||
assert.lengthOf(tiles, 16);
|
||||
const urls = tiles.map((t) => t.url.replace(/[abc]\./, ''));
|
||||
assert.include(urls, 'http://tile.openstreetmap.org/16/33677/21651.png');
|
||||
const keys = tiles.map((t) => t.key);
|
||||
assert.include(keys, 'http://a.tile.openstreetmap.org/16/33677/21651.png');
|
||||
});
|
||||
|
||||
it('uses subdomains for url and not for key', () => {
|
||||
const layer = new TileLayerOffline(
|
||||
'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
);
|
||||
const bounds = new Bounds(
|
||||
new Point(8621975, 5543267.999999999),
|
||||
new Point(8621275, 5542538),
|
||||
);
|
||||
const tiles = layer.getTileUrls(bounds, 16);
|
||||
const subs = tiles.map((t) => t.url.match(/([abc])\./)?.[1]);
|
||||
assert.include(subs, 'a');
|
||||
assert.include(subs, 'b');
|
||||
assert.include(subs, 'c');
|
||||
const subskeys = tiles.map((t) => t.key.match(/([abc])\./)?.[1]);
|
||||
assert.include(subskeys, 'a');
|
||||
assert.notInclude(subskeys, 'b');
|
||||
assert.notInclude(subskeys, 'c');
|
||||
});
|
||||
|
||||
it('calculates openstreetmap tiles at level 16', () => {
|
||||
const layer = new TileLayerOffline(
|
||||
'http://a.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
);
|
||||
const bounds = new Bounds(
|
||||
new Point(8621975, 5543267.999999999),
|
||||
new Point(8621275, 5542538),
|
||||
);
|
||||
const tiles = layer.getTileUrls(bounds, 16);
|
||||
assert.lengthOf(tiles, 16);
|
||||
const urls = tiles.map((t) => t.url);
|
||||
assert.include(urls, 'http://a.tile.openstreetmap.org/16/33677/21651.png');
|
||||
const keys = tiles.map((t) => t.key);
|
||||
assert.include(keys, 'http://a.tile.openstreetmap.org/16/33677/21651.png');
|
||||
});
|
||||
|
||||
it('calculates mobox tiles at level 16', () => {
|
||||
const layer = new TileLayerOffline(
|
||||
'https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}',
|
||||
{
|
||||
id: 'mapbox.streets',
|
||||
accessToken: 'xyz',
|
||||
},
|
||||
);
|
||||
const bounds = new Bounds(
|
||||
new Point(8621975, 5543267.999999999),
|
||||
new Point(8621275, 5542538),
|
||||
);
|
||||
const tiles = layer.getTileUrls(bounds, 16);
|
||||
assert.lengthOf(tiles, 16);
|
||||
const urls = tiles.map((t) => t.url);
|
||||
assert.include(
|
||||
urls,
|
||||
'https://api.tiles.mapbox.com/v4/mapbox.streets/16/33677/21651.png?access_token=xyz',
|
||||
);
|
||||
const keys = tiles.map((t) => t.key);
|
||||
assert.include(
|
||||
keys,
|
||||
'https://api.tiles.mapbox.com/v4/mapbox.streets/16/33677/21651.png?access_token=xyz',
|
||||
);
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue