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

@@ -180,14 +180,15 @@ export function createMapillaryProvider({ source }) {
loading: state.sequence.loading,
}),
/** Nearest image that passes the imagery filter, or null. */
async nearestImage({ lat, lon }) {
const images = await source.nearestImages({
lat,
lon,
radius: NEAREST_RADIUS_M,
limit: NEAREST_LIMIT,
});
/**
* Nearest image that passes the imagery filter, or null. The core
* aborts `signal` once a newer request overtakes the lookup.
*/
async nearestImage({ lat, lon }, { signal } = {}) {
const images = await source.nearestImages(
{ lat, lon, radius: NEAREST_RADIUS_M, limit: NEAREST_LIMIT },
{ signal },
);
// The API returns the images in the radius in no particular order.
const metres = (record) => {
const [lon2, lat2] = (record.computed_geometry || record.geometry)