fix(street-level): settle loading on pan, keep zoom 0, drop late poses

Fixes from gekh's re-review of 061d269, each with a regression test that
fails on the old code:

- A pan that drops a tile still loading now settles the loading count
  (the aborted request no longer owns its key, so its `finally` never
  did), and purges the previous zoom's tiles once nothing is pending.
  LOADING no longer sticks on the status pill and chip.
- Zoom 0 (above 15,000 km) is a zoom: `zoom == null` instead of `!zoom`.
- A pose that arrives after a photo was closed is dropped, in the
  MapillaryJS adapter and in the viewer host, so the marker and sequence
  selection do not come back.
- Ground casting passes the tile's signal to the terrain request, so a
  cancelled tile stops its height batch instead of holding the queue.
- The server's in-memory tile cache honours the 24 h TTL like the disk.
- The viewer's one-time resize runs for every photo, not just the first.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Said TurkseverandClaude Opus 5.5 committed 2026-10-05 12:44:27 +01:00
1 parent 061d2698f5
commit a5e16e9470
11 files changed
+115 -6

No files matched your search

@@ -241,3 +241,39 @@ test('a tile whose lines cannot be cast is not rebuilt for nothing', async () =>
assert.equal(viewer.scene.primitives.items.size, 0);
coverage.clear();
});
test('panning off a tile that is still loading settles the loading count', async () => {
const { viewer, source, state, coverage } = setup();
coverage.refresh();
assert.equal(state.coverage.loading, 1);
// Same zoom, two tiles east: the first request is dropped, a new one starts.
viewer.view.lon += 0.05;
coverage.refresh();
assert.equal(source.calls.length, 2);
assert.equal(source.calls[0].signal.aborted, true);
assert.equal(state.coverage.pending.size, 1);
assert.equal(
state.coverage.loading,
1,
'only the live request counts as loading',
);
source.calls[0].reject(new DOMException('aborted', 'AbortError'));
source.calls[1].resolve(new Uint8Array());
await settle();
assert.equal(state.coverage.pending.size, 0);
assert.equal(state.coverage.loading, 0, 'LOADING clears');
coverage.clear();
});
test('zoom 0 is a zoom: the whole-earth view still shows coverage', () => {
const { viewer, source, state, coverage } = setup();
viewer.view.height = 20_000_000;
coverage.refresh();
assert.equal(state.coverage.zoom, 0);
assert.equal(state.coverage.hint, '');
assert.deepEqual(
source.calls.map((call) => call.key),
['0/0/0'],
);
coverage.clear();
});