fix(street-level): re-check after every await; close the old photo; fresh panel views

Address samehkhamis's review on #1113:

- show_street_level checks the turn, the camera's owner (navigation stamp,
  re-taken where its own flight lands, or a press/wheel on the globe) and
  the hiding modes after the flight, the map switch, the layer switch-on and
  the lookup; a photo that opened after either is closed again. The hidden
  panel is also refused before the flight.
- An open photo closes before a new request arms or looks up, so a place
  with no imagery shows its own error.
- The panel posts every view with `fresh`; the inline app opens a billed
  photo only for a fresh one.
- A passed-through view's street_level point moves with a new camera
  position; revealPanel does nothing above 720px, scrolling included.
- Document that the app's own links do not carry `sl`.
This commit is contained in:
Said Turksever committed 2026-11-06 00:40:20 +00:00
1 parent 14f7326dbf
commit 30e6cd39c7
15 files changed
+486 -57

No files matched your search

+16 -4
View File
@@ -4569,8 +4569,9 @@ returns the radius's photos in no particular order and cuts them at the limit
first, so the distance sort and the imagery filter run over the spot's photos.
On a phone the panel sits in the Cameras tab sheet: a photo that opens, and a
link that arms, open that sheet and scroll the panel into view
(`revealPanel`); every photo the action opens reveals the panel again, also
one the user had collapsed. The layer exposes `requiredMapStack(id)` and
(`revealPanel`, which does nothing above 720px, scrolling included); every
photo the action opens reveals the panel again, also one the user had
collapsed. The layer exposes `requiredMapStack(id)` and
`providerStatus(id)` for callers that must decide before the panel lists a
source, and `coverageLines(id)` (the lines a provider draws now, current and
stale tiles, as `[lon, lat]` parts) for diagnostics and the browser gate,
@@ -4597,7 +4598,16 @@ the lookup that still owns the panel may change its spinner or error. Cancelling
a lookup clears its loading state even when an existing photo stays open;
internally retired lookups also release the caller's abort listener. A
passive link's photos stand down if anyone navigated (a gesture, a search,
the assistant) while the link waited behind its own marks. A plain
the assistant) while the link waited behind its own marks. The action itself
checks again after every await (flight, map switch, layer on, lookup): a
newer turn, a shell navigation stamp (`_navigationGeneration`, re-taken where
its own flight lands) or a press or wheel on the globe stops the remaining
stages (`superseded: true`), and cockpit, clean view, recording or scene
playback entered meanwhile ends it at the `view` stage; a photo that opened
after either is closed again. The hidden-panel check also runs before the
flight, so a recording's camera never moves for it. A photo already open
closes before the new request arms or looks up, so a place with no imagery
shows its own error, not the previous place's photo. A plain
link never loads a photo from a source that bills every load
(`billedPerImage` on the provider; Google): the action runs with
`autoOpen: false`, arms the lookup on the layer (`armNearest`: the link's
@@ -4610,7 +4620,9 @@ points at OPEN GOOGLE STREET VIEW. Only the panel page's own link (inline
embed) for a tool result issued in the last 5 minutes, and posted views, open
the photo: `show_in_gods_eye_view` stamps a street-level result `issued_at`,
and a host that mounts the panel again later hands back the old result, which
only arms; `?embed=1` on a published link only
only arms. The panel checks every result, not just the first: each `gev:view`
it posts carries `fresh`, and the inline app applies a view without it with
`autoOpen: false` (a framing page's posted views still open); `?embed=1` on a published link only
arms, without the panel nudge or toast (the rail is hidden in a frame). A link that follows an entity ignores `sl`.
The look-at default applies below 20 km, at a pitch steeper than -5° and
within 10 km ahead; otherwise the camera's own point is used. A view's
+10
View File
@@ -51,6 +51,16 @@ military aircraft or satellite. A selected vessel is not followed (the camera
stays where the user puts it), so a link made then is a place view; vessel
thing views open, but the app does not make them yet.
## Street-level photos (`sl`)
Views built by `show_in_gods_eye_view` or `src/view/index.js` can add
`sl=<source>,<lat>,<lon>` to the long form. Once the link has restored, the
app opens the nearest photo there, or, for a source that bills every load,
arms the panel so OPEN loads it (see `docs/TOOLS.md`). The app's own links do
not carry it: the address bar's long form drops `sl` when the camera next
moves, and the short form has no field for it. A reload or the app's Copy
Link keeps the lit source, the layer and the map, but not the photo request.
## Payload
The code is unpadded base64url (`A–Z a–z 0–9 - _`). The decoded bytes are:
+5 -2
View File
@@ -120,8 +120,11 @@ photo at once; none of them bills per image. A link that follows an entity ignor
Tools take a view as `VIEW_ARGUMENTS`: an `area` to frame from above, or a
`camera`, plus `layers`, `style`, `map`, `follow`, `annotations` and
`street_level`. A tilted camera over an area looks at its center from behind;
camera fields given with an area override its framing. `resolveViewArguments`
turns them into a view.
camera fields given with an area override its framing. A passed-through
view's `street_level` point moves with a new `area` or camera position (a
turned camera keeps it). `resolveViewArguments` turns them into a view. The
app's own links (the address bar, Copy Link, `/share/<code>`) do not carry
`sl`; see `docs/SHARE-LINK-FORMAT.md`.
### The God's Eye View panel