diff --git a/CHANGELOG.md b/CHANGELOG.md index 20b6fccdb..02a869424 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +- Street Level with no providers uses the shared unavailable state and refuses + activation before initialization, while keeping its layer identity visible. + - Application source configuration accepts replacements and explicit removal. Missing catalog feeds leave their layers unavailable without blocking startup or making fallback requests; malformed supplied feeds remain configuration errors. diff --git a/docs/CURRENT-STATE.md b/docs/CURRENT-STATE.md index d0cfa5c1b..dc460fb3d 100644 --- a/docs/CURRENT-STATE.md +++ b/docs/CURRENT-STATE.md @@ -7,7 +7,8 @@ visibility lifecycle before initialization. Invalid supplied methods still fail construction. `createStandaloneApplication` and `createStandaloneCatalog` accept `sources` overrides; unspecified entries retain standalone defaults, and null entries explicitly remove a source. Street Level -continues to accept an explicit provider list. Directions and Recent Imagery +continues to accept an explicit provider list. An empty Street Level provider +list uses the same unavailable lifecycle and disabled layer toggle. Directions and Recent Imagery acquisition are still selected by their application constructors. Application catalog composition accepts an optional `streetLevelProviders` list. diff --git a/src/app/sourceComposition.test.mjs b/src/app/sourceComposition.test.mjs index 9d6823e40..beafa5c51 100644 --- a/src/app/sourceComposition.test.mjs +++ b/src/app/sourceComposition.test.mjs @@ -82,3 +82,20 @@ test('standalone defaults allow exact replacements and explicit removal, and rej /Unknown source/, ); }); + +test('empty Street Level uses the shared unavailable lifecycle without initialization', async (t) => { + const actual = catalog({}, t); + const manager = new LayerLifecycle({}); + manager.register(actual.get('street-level')); + assert.equal(await manager.setEnabled('street-level', true), false); + assert.equal(manager.layers.get('street-level').initialized, false); + const row = manager.getAll()[0]; + assert.equal(row.stats.status, 'unavailable'); + assert.equal(row.stats.error, 'No street-level imagery providers configured'); + assert.equal(await manager.setEnabled('street-level', false), true); + const configured = catalog(createStandaloneLayerSources(), t); + assert.equal( + configured.get('street-level').getSourceAvailability().available, + true, + ); +}); diff --git a/src/layers/streetLevel/index.js b/src/layers/streetLevel/index.js index dd4478c58..60a31691e 100644 --- a/src/layers/streetLevel/index.js +++ b/src/layers/streetLevel/index.js @@ -333,6 +333,16 @@ export function createStreetLevelLayer({ requiresKeyId: requiresKeyIdFor(definitionsFrozen), /** Registered providers, in chip order. */ providerIds: definitionsFrozen.map((def) => def.id), + getSourceAvailability() { + const available = definitionsFrozen.length > 0; + return { + available, + source: STREET_LEVEL_LAYER_ID, + reason: available + ? null + : 'No street-level imagery providers configured', + }; + }, init(viewer) { if (state.initialized)