mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
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:
1 parent
061d2698f5
commit
a5e16e9470
11 files changed
+115
-6
No files matched your search
@@ -537,7 +537,7 @@ export function createCoverage({ state, source }) {
|
||||
let bbox = visibleBbox(viewer);
|
||||
if (kind === 'overview' && (!bbox || zoom <= 1))
|
||||
bbox = [-180, -85, 180, 85];
|
||||
if (!zoom || !bbox) {
|
||||
if (zoom == null || !bbox) {
|
||||
state.coverage.hint =
|
||||
'Point the camera at the globe for street-level coverage';
|
||||
clear();
|
||||
@@ -559,10 +559,14 @@ export function createCoverage({ state, source }) {
|
||||
if (!wanted.has(key)) removeTile(key);
|
||||
for (const [key, controller] of [...state.coverage.pending])
|
||||
if (!wanted.has(key)) {
|
||||
// The aborted request no longer owns its key, so its `finally` will
|
||||
// not settle the count: settle it here.
|
||||
controller.abort();
|
||||
state.coverage.pending.delete(key);
|
||||
state.coverage.loading = Math.max(0, state.coverage.loading - 1);
|
||||
}
|
||||
for (const tile of tiles) loadTile(tile, kind);
|
||||
if (!state.coverage.pending.size) purgeStale();
|
||||
// The camera moved: cells that were out of the sampler's range may not be.
|
||||
if (terrainMode())
|
||||
for (const entry of state.coverage.tiles.values())
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
@@ -69,6 +69,9 @@ export function createMapillaryViewer({ source, render } = {}) {
|
||||
viewer.getPosition(),
|
||||
viewer.getPointOfView(),
|
||||
]);
|
||||
// Closed (or never opened) while the pose was in flight: a late
|
||||
// `image` event must not bring the photo back.
|
||||
if (pendingOpen === null) return;
|
||||
if (image) current = describe(image);
|
||||
if (!current || !viewer) return;
|
||||
emit({
|
||||
|
||||
Reference in new issue
Block a user