mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
Merge branch 'main' into pr/mapillary-layer
This commit is contained in:
201 files changed
+26665
-1973
No files matched your search
@@ -58,7 +58,7 @@ export const COCKPIT_BRIEF_PAGES = [
|
||||
id: 'local',
|
||||
kicker: 'LOCAL INFO',
|
||||
subtitle: 'PLACE / CONDITIONS / POSITION',
|
||||
source: 'OPENSTREETMAP · OPEN-METEO · UTC',
|
||||
source: 'NATURAL EARTH · OPEN-METEO · UTC',
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -115,6 +115,10 @@ export class LocationNavigation {
|
||||
placeSearch: this.placeSearch,
|
||||
...options,
|
||||
}),
|
||||
onResult: (destination) => {
|
||||
if (destination.outlineUnavailable)
|
||||
this._showToast('Detailed outline unavailable');
|
||||
},
|
||||
onError: (error) => console.error('[Search] Geocoding failed:', error),
|
||||
});
|
||||
this._locationLookupUnsubscribe = this._locationLookup.subscribe(
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { cancelCameraArrival } from '../data/cameraArrival.js';
|
||||
import { createStateChannel } from '../app/stateChannel.js';
|
||||
import * as Cesium from 'cesium';
|
||||
import {
|
||||
@@ -45,6 +46,7 @@ export class NavigationController {
|
||||
cancelPendingSelection = true,
|
||||
clearSearchedLocation = true,
|
||||
} = {}) {
|
||||
cancelCameraArrival(this.viewer);
|
||||
this.cancelOrientation();
|
||||
const { flightsLayer, militaryFlightsLayer, satellitesLayer } =
|
||||
this.tracking;
|
||||
@@ -257,6 +259,7 @@ export class NavigationController {
|
||||
return this._cameraHandoffs.subscribe(listener, { emitCurrent: false });
|
||||
}
|
||||
stop() {
|
||||
cancelCameraArrival(this.viewer);
|
||||
this._disposed = true;
|
||||
this._cameraHandoffs?.publish();
|
||||
this._cameraHandoffs?.destroy();
|
||||
|
||||
+20
-4
@@ -23,6 +23,8 @@ export class ShellFeedback {
|
||||
null;
|
||||
this._loadingVisibilityHandler = null;
|
||||
this._lastLoadingFeedbackUpdateAt = 0;
|
||||
this._lastTrafficChipUpdateAt = 0;
|
||||
this._lastTrafficGlobalUpdateAt = 0;
|
||||
this._globalLoadingStatus = document.getElementById(
|
||||
'global-loading-status',
|
||||
);
|
||||
@@ -74,7 +76,10 @@ export class ShellFeedback {
|
||||
// the flap keeps textContent equal to the settled label throughout, so
|
||||
// this stays a no-op on the repeat ticks exactly as it did before.
|
||||
if (presentation.label)
|
||||
setSplitFlapText(this._trafficSyncLabel, presentation.label);
|
||||
setSplitFlapText(this._trafficSyncLabel, presentation.label, {
|
||||
// Completion is a timing signal, not another animated loading stage.
|
||||
immediate: !presentation.busy,
|
||||
});
|
||||
// Written on every change INCLUDING the empty settled value — the reducer
|
||||
// clears the progress number once the sync lands, and a truthiness guard
|
||||
// here would strand the last "..." beside the settled label.
|
||||
@@ -142,9 +147,20 @@ export class ShellFeedback {
|
||||
if (this._trafficChipTicker) return;
|
||||
this._trafficChipTicker = setInterval(() => {
|
||||
if (document.hidden) return;
|
||||
this._updateTrafficSyncChip();
|
||||
this._updateGlobalLoadingFeedback();
|
||||
}, 500);
|
||||
const now = performance.now();
|
||||
// Poll busy traffic promptly; retain the idle/global 500 ms read budget.
|
||||
if (
|
||||
this._trafficSyncFeedbackState.busy ||
|
||||
now - this._lastTrafficChipUpdateAt >= 500
|
||||
) {
|
||||
this._lastTrafficChipUpdateAt = now;
|
||||
this._updateTrafficSyncChip(false, now);
|
||||
}
|
||||
if (now - this._lastTrafficGlobalUpdateAt >= 500) {
|
||||
this._lastTrafficGlobalUpdateAt = now;
|
||||
this._updateGlobalLoadingFeedback(now);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
_armLoadingFeedbackTicker() {
|
||||
|
||||
@@ -366,3 +366,41 @@ test('weather rail orders between CCTV and Context, resets positions, observes a
|
||||
f.restore();
|
||||
}
|
||||
});
|
||||
|
||||
test('busy traffic completion is polled promptly without accelerating idle or global reads', (t) => {
|
||||
const f = fixture();
|
||||
let now = 500;
|
||||
t.mock.method(performance, 'now', () => now);
|
||||
try {
|
||||
const owner = new ShellFeedback({ readLayers: () => [] });
|
||||
let traffic = 0,
|
||||
global = 0;
|
||||
owner._updateTrafficSyncChip = () => traffic++;
|
||||
owner._updateGlobalLoadingFeedback = () => global++;
|
||||
owner._startTrafficChipTicker();
|
||||
const tick = f.timers.get(owner._trafficChipTicker);
|
||||
tick();
|
||||
assert.equal(traffic, 1);
|
||||
assert.equal(global, 1);
|
||||
now = 600;
|
||||
tick();
|
||||
assert.equal(traffic, 1, 'idle polling remains bounded');
|
||||
owner._trafficSyncFeedbackState.busy = true;
|
||||
now = 700;
|
||||
tick();
|
||||
assert.equal(traffic, 2, 'busy completion is observed on a 100 ms tick');
|
||||
assert.equal(global, 1, 'other loading feedback keeps its prior budget');
|
||||
owner._trafficSyncFeedbackState.busy = false;
|
||||
now = 800;
|
||||
tick();
|
||||
assert.equal(traffic, 2);
|
||||
document.hidden = true;
|
||||
now = 1300;
|
||||
tick();
|
||||
assert.equal(traffic, 2, 'hidden pages do no polling');
|
||||
owner.destroy();
|
||||
assert.equal(f.timers.size, 0);
|
||||
} finally {
|
||||
f.restore();
|
||||
}
|
||||
});
|
||||
@@ -442,17 +442,17 @@
|
||||
letter-spacing: 0.035rem;
|
||||
}
|
||||
|
||||
/* The compact dock leaves both lower corners free for required attribution and telemetry. */
|
||||
/* Keep the complete inline attribution row above the command dock. */
|
||||
body:not(.ui-clean-view):not(.recording-mode) #cesium-credits,
|
||||
body:not(.ui-clean-view):not(.recording-mode):has(
|
||||
#intel-hud[data-variant='minimal'].active
|
||||
)
|
||||
#cesium-credits {
|
||||
right: auto;
|
||||
bottom: 0.75rem;
|
||||
bottom: calc(2vh + 5rem);
|
||||
left: 1.5rem;
|
||||
width: auto !important;
|
||||
max-width: calc(50vw - 15rem);
|
||||
max-width: calc(100vw - 3rem);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
|
||||
Vendored
-19
@@ -321,25 +321,6 @@ body.cockpit-mode #cockpit-cloud-effects.active {
|
||||
color: rgba(232, 234, 237, 0.7);
|
||||
}
|
||||
|
||||
/* Keep the ALPR source overflow reachable even after its brief on-map credit
|
||||
collapses. Wrap whole entries only while the optional layer is on. */
|
||||
body:has(.data-toggle-row[data-layer-id='alpr-cameras'] .data-toggle-btn.active)
|
||||
#cesium-credits {
|
||||
white-space: normal;
|
||||
}
|
||||
body:has(.data-toggle-row[data-layer-id='alpr-cameras'] .data-toggle-btn.active)
|
||||
#cesium-credits
|
||||
.cesium-credit-wrapper {
|
||||
display: inline-block !important;
|
||||
white-space: nowrap;
|
||||
}
|
||||
body:has(.data-toggle-row[data-layer-id='alpr-cameras'] .data-toggle-btn.active)
|
||||
#cesium-credits
|
||||
.cesium-credit-expand-link {
|
||||
/* Keep the complete link at the left edge, clear of the Power Up button. */
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
/* Cesium's stock attribution lightbox grows with every registered data source.
|
||||
Keep the title and close affordance fixed while the complete, unabridged
|
||||
credit list wraps and scrolls inside a compact panel. */
|
||||
|
||||
@@ -337,6 +337,15 @@
|
||||
#military-awareness-panel[hidden] {
|
||||
display: none;
|
||||
}
|
||||
.military-awareness-names {
|
||||
margin: 6px 0;
|
||||
color: var(--text-dim);
|
||||
}
|
||||
.military-awareness-names > div {
|
||||
max-height: 160px;
|
||||
overflow-y: auto;
|
||||
padding: 6px 0;
|
||||
}
|
||||
.military-awareness-subject {
|
||||
margin: 0 0 7px;
|
||||
color: #fff;
|
||||
|
||||
Reference in new issue
Block a user