fix(street-level): own the framing flight and the nearest-photo lookup

From the IC8 review of #768, each with tests that fail before:

- P1: closing a photo, switching the layer off or destroying it stops the
  1.6 s framing flight toward that photo. The flight is claimed with a
  token before flyToBoundingSphere and released by its complete/cancel
  callbacks, so cancelFraming() calls camera.cancelFlight() only while
  the flight is still Street Level's: a newer navigation flight (a search
  result, a scene) is never cancelled. Turning FOLLOW on also stops it, so
  the tween cannot overwrite the follow view.
- P2: an older nearest-photo lookup can no longer replace a newer choice.
  The core owns one AbortController per lookup, aborted by a newer lookup,
  a direct open or cone click, closing the viewer, disable and destroy;
  the signal reaches source.nearestImages through the provider, and an
  aborted lookup never surfaces as an error.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Said TurkseverandClaude Opus 5.5 committed 2026-10-06 15:16:57 +01:00
1 parent c2f1b54d00
commit 09fc10756c
8 files changed
+371 -27

No files matched your search

+21 -2
View File
@@ -39,11 +39,16 @@ function harness(adapter) {
};
const def = { id: 'mapillary', name: 'Mapillary', label: 'MAPILLARY' };
state.providers.set('mapillary', { def, instance: { viewer: adapter } });
const framing = { started: 0, cancelled: 0 };
const parts = {
marker: { set() {}, clear() {} },
follow: { followCamera() {}, lookAtPosition() {} },
follow: {
followCamera() {},
lookAtPosition: () => framing.started++,
cancelFraming: () => framing.cancelled++,
},
};
return { state, host: createViewerHost({ state, parts }) };
return { state, framing, host: createViewerHost({ state, parts }) };
}
/**
@@ -318,3 +323,17 @@ test('closing the photo stops sequence playback in the hidden viewer (review P2-
assert.equal(viewer.playback.stops, 1, 'playback stopped with the photo');
assert.equal(viewers.live, 1, 'the viewer itself stays warm');
});
test('closing the photo or switching the layer off stops its framing flight (review IC8 P1)', async () => {
const adapter = fakeAdapter();
const { framing, host } = harness(adapter);
await host.open('mapillary', 'a');
assert.equal(framing.started, 1, 'the open framed the photo');
host.close();
assert.equal(framing.cancelled, 1, 'closed: the globe stops flying to it');
await host.open('mapillary', 'b');
host.unmount('panoramax');
assert.equal(framing.cancelled, 1, 'another provider leaves it alone');
host.unmount();
assert.equal(framing.cancelled, 2, 'layer off: likewise');
});