Street Level: a landed link, a replaced photo and a retired lookup keep their state

- A link's photo step compares with the navigation token its own restore
  flight owned, so a navigation after the flight landed (while the layers
  still load) keeps the camera.
- A request that switches the source keeps the open photo up until it is
  replaced (holdViewer), so EXPAND stays across sources.
- A lookup given up while it looked leaves the open photo and the panel as
  they were, also when it found nothing or failed.
- A failed replacement shows its error inside the expanded viewer.
- A replacing lookup stops a playing Mapillary sequence before the found
  photo opens.
- The action refuses coordinates outside the globe, keeps a name given with
  coordinates as its label, and fly: false keeps the camera only for
  coordinates (its test-only entity and query branches are gone).
- Numbered entities carry their label; a view's street-level point is a pair.
- Mapillary's nearest search always asks for 50 m and 100 images.
- Tests: the lifecycle reproductions, PLAY on replacement, out-of-range
  coordinates, half a point, and the named label; three layer tests share
  enabledLayer; the second payload digest is gone.
- Docs: the tool count, the panel freshness rule, armed: false, the photo
  replacement, the browser-gate comment and a shorter changelog fragment.
This commit is contained in:
German Khokhlov committed 2026-11-10 23:48:57 +04:00
1 parent 9c73939425
commit f3996da0af
26 files changed
+470 -327

No files matched your search

+8 -2
View File
@@ -341,10 +341,16 @@ export function installViews({
// A restore whose camera never landed (the recipient dragged, searched or
// opened another place during its flight) leaves the camera with them.
const cameraLanded = (outcome) => outcome?.share?.camera === 'applied';
// The generation the restore's own flight owned: a navigation after it
// landed, while the layers still loaded, has moved on from it.
const restoreGeneration = (outcome) =>
Number.isInteger(outcome?.navigationToken)
? outcome.navigationToken
: shell._navigationGeneration;
let generationAtRestore = null;
let startSuperseded = false;
let queue = ready.then((outcome) => {
generationAtRestore = shell._navigationGeneration;
generationAtRestore = restoreGeneration(outcome);
startSuperseded =
outcome?.status === 'superseded' ||
(Boolean(outcome?.share) && !cameraLanded(outcome));
@@ -414,7 +420,7 @@ export function installViews({
new URLSearchParams(String(location?.hash || '').replace(/^#/, '')),
);
if (!streetLevel) return;
const generation = shell._navigationGeneration;
const generation = restoreGeneration(event.detail);
queue = linkStep(() => openLinkedStreetLevel(streetLevel, { generation }));
};
windowRef?.addEventListener?.(