mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 18:34:02 +00:00
Select a box on the world and browse the last 30 days of open satellite imagery over it, keyless: NASA GIBS Harmonized Landsat Sentinel-2 (30 m) and the VIIRS daily overview (250 m), with a day strip, IMAGE / VS BASEMAP / A / B modes with a swipe divider, PNG export and share links. The before/after swipe from the Nepal scene moves into shared modules so both use it. Co-authored-by: manjunath22466 <[email protected]>
95 lines
3.1 KiB
JavaScript
95 lines
3.1 KiB
JavaScript
import { LayerPanel } from '../ui/layers.js';
|
|
import { governorRequestRender } from '../renderGovernor.js';
|
|
import { markDetectionSourcesChanged } from '../data/detection.js';
|
|
|
|
/** Own the layer panel and application reactions to lifecycle activity. */
|
|
export class LayerPresentation {
|
|
constructor(
|
|
manager,
|
|
{
|
|
weatherClock,
|
|
requestRender = governorRequestRender,
|
|
invalidateDetection = markDetectionSourcesChanged,
|
|
} = {},
|
|
) {
|
|
this.manager = manager;
|
|
this.weatherClock = weatherClock;
|
|
this._panel = null;
|
|
this.pendingVisible = false;
|
|
this._unsubscribe = manager.subscribeActivity((change) => {
|
|
if (change.type === 'status') this.refresh();
|
|
else if (change.type === 'destroy-all') this.destroy();
|
|
else {
|
|
const reason =
|
|
change.type === 'data-updated'
|
|
? `layer-tick:${change.layerId}`
|
|
: change.type === 'visibility-settled'
|
|
? 'layer-visibility'
|
|
: change.type === 'params-settled'
|
|
? `layer-params:${change.layerId}`
|
|
: null;
|
|
if (!reason) return;
|
|
requestRender(reason);
|
|
if (change.type !== 'params-settled') invalidateDetection(reason);
|
|
}
|
|
});
|
|
}
|
|
get panel() {
|
|
if (!this._panel)
|
|
this._panel = new LayerPanel({
|
|
weatherClock: this.weatherClock,
|
|
getLayers: () => this.manager.getAll(),
|
|
isEnabled: (id) => this.manager.isEnabled(id),
|
|
setEnabled: (id, enabled, options) =>
|
|
this.manager.setEnabled(id, enabled, options),
|
|
setLayerParams: (id, params, options) =>
|
|
this.manager.setLayerParams(id, params, options),
|
|
getRowControls: (id) => {
|
|
const module = this.manager.layers.get(id)?.module;
|
|
try {
|
|
return module?.getRowControls?.() || null;
|
|
} catch (error) {
|
|
console.warn(`[Data] ${id} getRowControls error:`, error);
|
|
return null;
|
|
}
|
|
},
|
|
hasRowControls: (id) =>
|
|
typeof this.manager.layers.get(id)?.module?.getRowControls ===
|
|
'function',
|
|
subscribeRowControls: (id, listener) => {
|
|
const module = this.manager.layers.get(id)?.module;
|
|
module?.setRowControlsListener?.(listener);
|
|
return () => module?.setRowControlsListener?.(null);
|
|
},
|
|
onHiddenRefresh: () => {
|
|
this.pendingVisible = true;
|
|
},
|
|
});
|
|
return this._panel;
|
|
}
|
|
mount(container) {
|
|
this.panel.mount(container);
|
|
}
|
|
/** Hand the Recent Imagery readout factory to the panel (see LayerPanel). */
|
|
attachRecentImagery(factory) {
|
|
// Detaching never builds a panel that teardown already released.
|
|
if (factory) this.panel.attachRecentImagery(factory);
|
|
else this._panel?.attachRecentImagery(null);
|
|
}
|
|
refresh() {
|
|
this._panel?._refreshTogglePanel();
|
|
}
|
|
flushVisible() {
|
|
if (!this.pendingVisible) return;
|
|
this.pendingVisible = false;
|
|
this.refresh();
|
|
}
|
|
destroy() {
|
|
this._panel?.destroy();
|
|
this._panel = null;
|
|
this.pendingVisible = false;
|
|
this._unsubscribe?.();
|
|
this._unsubscribe = null;
|
|
}
|
|
}
|