Merge upstream/main (KartaView #1121 merged) into pr/panoramax

KartaView's later viewer changes are carried into the shared
photoViewer.js: the camera bearing (`bearingOf`), redrawing the same
photo after a GPU reset through `onReopen`, no pose while a lost context
recovers, the 2,560 px flat version only once the viewer outgrows
1,280 px, `refreshPose`, and one sharper-panorama load at a time with a
second look once it lands. Its tile cache's `keyOf` and `clear` move to
the shared tileCache.js. KartaView gets `onEscape` beside `onReopen`.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Said TurkseverandClaude Opus 5.5 committed 2026-10-14 15:52:21 +01:00
commit da0d370fa3
43 files changed
+3299 -178

No files matched your search

+28
View File
@@ -106,6 +106,34 @@ test('bike share joins station information with live status inside the area', as
assert.equal(result.data.rows[1].capacity, 10);
});
test('bike share returns localized names without losing stations with malformed names', async () => {
const informationUrl = 'https://gbfs.example/austin/station_information.json';
const information = structuredClone(documents[informationUrl]);
information.version = '3.0';
information.data.stations[0].name = [
{ language: 'hu', text: 'Magyar név' },
{ language: 'en', text: 'Congress & 2nd' },
];
information.data.stations[2].name = [null, { language: 42, text: [] }];
const source = bikeshare([system('austin', 'Austin, TX', 30.27, -97.74)]);
const catalog = composeCatalog({
tools: coreTools,
services: {
bikeshare: {
...source,
getStations: (url) =>
url === informationUrl ? information : source.getStations(url),
},
},
});
const result = await catalog.call('get_bike_share', { area: downtown });
assert.equal(result.data.total, 2);
assert.equal(result.data.rows[0].name, 'Congress & 2nd');
assert.equal(result.data.rows[0].bikes_available, 4);
assert.equal(result.data.rows[1].name, null);
assert.doesNotMatch(result.summary, /unavailable/);
});
test('bike share reports uncovered areas and failed systems honestly', async () => {
const none = composeCatalog({
tools: coreTools,