fix(street-level): point a key-gated layer at Street View; button beside the hint

Review of #966: with a Google Maps key but no Mapillary token, switching
Street Level on read KEY REQUIRED / "Needs MAPILLARY_CLIENT_TOKEN" with
nothing about Street View, which stayed off (billing), so the layer looked
broken.

- While the switched-on providers lack their keys, the layer reports the
  switched-off ones that would draw with a key already set
  (keyAlternatives: Street View on Google 3D with a Google key). The
  panel's KEY REQUIRED tooltip, its coverage line and the layer row's
  tooltip then read "Needs MAPILLARY_CLIENT_TOKEN — add it in Provider
  Settings, or light STREET VIEW to use your Google Maps key"
  (keySetupWithAlternatives). Off Google 3D the plain KEY REQUIRED stays.
  Street View stays off by default.
- OPEN STREET VIEW moves beside the coverage hint: at the default panel
  width the PROVIDERS row has no room for it, so it wrapped onto a line of
  its own.
- The panel gate's corner drag names what lay under the pointer when it
  fails.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Said TurkseverandClaude Opus 5.5 committed 2026-10-09 00:05:58 +01:00
1 parent f5c4f3fda3
commit e823e15025
15 files changed
+669 -138

No files matched your search

+28 -2
View File
@@ -1,4 +1,7 @@
import { keySetupRequirement } from '../keySetupCore.mjs';
import {
keySetupRequirement,
keySetupWithAlternatives,
} from '../keySetupCore.mjs';
// Street Level UI state to panel strings and flags. Pure, so it is testable.
@@ -54,13 +57,33 @@ function formatDate(ms, precision = 'day') {
}
}
/**
* What the key-gated layer needs: each switched-on provider's key, and the
* switched-off ones that would draw with a key already set.
*/
function keyGuidance(state) {
const needs = (state.providers || [])
.filter((p) => p.on && p.keyRequired && p.requiresKeyId)
.map((p) => keySetupRequirement(p.requiresKeyId))
.filter(Boolean);
return keySetupWithAlternatives(
[...new Set(needs)].join('; '),
state.keyAlternatives || [],
);
}
function presentStatus(state) {
const pressed = state.enabled === true;
const title = pressed ? 'Turn Street Level off' : 'Turn Street Level on';
if (state.keyRejected)
return { text: 'KEY REJECTED', tone: 'warn', pressed, title };
if (state.keyRequired)
return { text: 'KEY REQUIRED', tone: 'warn', pressed, title };
return {
text: 'KEY REQUIRED',
tone: 'warn',
pressed,
title: keyGuidance(state) || title,
};
if (state.coverage.loading)
return { text: 'LOADING', tone: 'busy', pressed, title };
return pressed
@@ -162,6 +185,9 @@ function presentNearest(state) {
function presentMeta(state) {
if (!state.enabled) return 'Switch a provider on to draw its coverage.';
// Key-gated with another source ready: say how to use it.
if (state.keyRequired && state.keyAlternatives?.length)
return keyGuidance(state);
if (state.sequence.selectedId)
return state.sequence.loading
? 'Loading this sequence…'