mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 19:34:01 +00:00
fix(ui): the "kept in the link" notice is readable on Navara
On Navara the engine's persistent notice came up right after the share restore's NOT ON THIS ENGINE notice and replaced it at once, so the names of the linked layers this engine lacks were never seen (and a later finite notice would in turn have wiped the engine notice for good). - ShellFeedback keeps a persistent notice that a finite one covers and brings it back when the finite one ends; a persistent notice that arrives under a live finite one waits for it. - Notices take a dwellMs; "Kept in the link: …" stays 15 s. - scripts/qa-engine-notice.mjs (headless): a Cesium share link with a layer Navara lacks, opened with ?engine=navara: notice shown with the layer name, still up 14 s later, then the engine notice is back. 4/4 (before the fix the notice never appeared). T8-T9 review item 2.
This commit is contained in:
1 parent
c493a8303b
commit
9f1a0611fa
5 files changed
+103
-5
No files matched your search
@@ -1109,5 +1109,6 @@
|
|||||||
"src/app/layers/qaSources.test.mjs",
|
"src/app/layers/qaSources.test.mjs",
|
||||||
"scripts/qa-w1-layers.mjs",
|
"scripts/qa-w1-layers.mjs",
|
||||||
"src/bench/w1Feeds.js",
|
"src/bench/w1Feeds.js",
|
||||||
"scripts/qa-map-switch.mjs"
|
"scripts/qa-map-switch.mjs",
|
||||||
|
"scripts/qa-engine-notice.mjs"
|
||||||
]
|
]
|
||||||
@@ -130,7 +130,7 @@ export function createLoadingFeedbackState() {
|
|||||||
export function createGlobalStatusNotice(
|
export function createGlobalStatusNotice(
|
||||||
message,
|
message,
|
||||||
nowMs = 0,
|
nowMs = 0,
|
||||||
{ state = 'error', detail = '', persistent = false } = {},
|
{ state = 'error', detail = '', persistent = false, dwellMs } = {},
|
||||||
) {
|
) {
|
||||||
const label = String(message || '').trim();
|
const label = String(message || '').trim();
|
||||||
if (!label) return null;
|
if (!label) return null;
|
||||||
@@ -139,7 +139,11 @@ export function createGlobalStatusNotice(
|
|||||||
label,
|
label,
|
||||||
detail: String(detail || '').trim(),
|
detail: String(detail || '').trim(),
|
||||||
persistent: !!persistent,
|
persistent: !!persistent,
|
||||||
dwellMs: persistent ? null : LOADING_FAILURE_DWELL_MS,
|
dwellMs: persistent
|
||||||
|
? null
|
||||||
|
: Number.isFinite(dwellMs) && dwellMs > 0
|
||||||
|
? dwellMs
|
||||||
|
: LOADING_FAILURE_DWELL_MS,
|
||||||
// A finite notice starts its dwell only when it first wins presentation.
|
// A finite notice starts its dwell only when it first wins presentation.
|
||||||
// Otherwise a higher-priority manager failure could consume the whole
|
// Otherwise a higher-priority manager failure could consume the whole
|
||||||
// deadline while this notice remained queued and invisible.
|
// deadline while this notice remained queued and invisible.
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import { LayerStateCoordinator } from '../data/layerStateCoordinator.js';
|
import { LayerStateCoordinator } from '../data/layerStateCoordinator.js';
|
||||||
import { APPLICATION_LAYER_DIRECTORY } from '../app/layers/directory.js';
|
import { APPLICATION_LAYER_DIRECTORY } from '../app/layers/directory.js';
|
||||||
|
|
||||||
|
/** How long the "kept in the link" notice stays up (ms). */
|
||||||
|
export const NOT_ON_THIS_ENGINE_DWELL_MS = 15_000;
|
||||||
|
|
||||||
/** Names of the layers a link turned on that this engine does not have. */
|
/** Names of the layers a link turned on that this engine does not have. */
|
||||||
export function layersNotOnThisEngine(results) {
|
export function layersNotOnThisEngine(results) {
|
||||||
return results
|
return results
|
||||||
@@ -189,6 +192,9 @@ export class ShareRestoration {
|
|||||||
this.showStatus('NOT ON THIS ENGINE', {
|
this.showStatus('NOT ON THIS ENGINE', {
|
||||||
state: 'retry',
|
state: 'retry',
|
||||||
detail: `Kept in the link: ${names.join(', ')}`,
|
detail: `Kept in the link: ${names.join(', ')}`,
|
||||||
|
// Long enough to read a list of layer names; the engine's own
|
||||||
|
// persistent notice comes back afterwards (ShellFeedback).
|
||||||
|
dwellMs: NOT_ON_THIS_ENGINE_DWELL_MS,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
cancelSelection() {
|
cancelSelection() {
|
||||||
|
|||||||
+20
-2
@@ -17,6 +17,9 @@ export class ShellFeedback {
|
|||||||
this._trafficSyncFeedbackState = createTrafficSyncFeedbackState();
|
this._trafficSyncFeedbackState = createTrafficSyncFeedbackState();
|
||||||
this._loadingFeedbackEvent = null;
|
this._loadingFeedbackEvent = null;
|
||||||
this._globalStatusNotice = null;
|
this._globalStatusNotice = null;
|
||||||
|
// A persistent notice (the Navara engine notice) that a finite one
|
||||||
|
// covers for its dwell; it comes back when the finite one ends.
|
||||||
|
this._coveredPersistentNotice = null;
|
||||||
this._loadingFeedbackTicker =
|
this._loadingFeedbackTicker =
|
||||||
this._trafficChipTicker =
|
this._trafficChipTicker =
|
||||||
this._toastTimer =
|
this._toastTimer =
|
||||||
@@ -111,7 +114,8 @@ export class ShellFeedback {
|
|||||||
Number.isFinite(this._globalStatusNotice?.hideAt) &&
|
Number.isFinite(this._globalStatusNotice?.hideAt) &&
|
||||||
now >= this._globalStatusNotice.hideAt
|
now >= this._globalStatusNotice.hideAt
|
||||||
) {
|
) {
|
||||||
this._globalStatusNotice = null;
|
this._globalStatusNotice = this._coveredPersistentNotice;
|
||||||
|
this._coveredPersistentNotice = null;
|
||||||
}
|
}
|
||||||
// Loading phases and universal notices both have time-driven transitions.
|
// Loading phases and universal notices both have time-driven transitions.
|
||||||
// Compute this after arbitration: a queued finite notice starts its dwell
|
// Compute this after arbitration: a queued finite notice starts its dwell
|
||||||
@@ -138,7 +142,21 @@ export class ShellFeedback {
|
|||||||
_showGlobalStatusNotice(message, options = {}) {
|
_showGlobalStatusNotice(message, options = {}) {
|
||||||
if (this.destroyed) return;
|
if (this.destroyed) return;
|
||||||
const now = performance.now();
|
const now = performance.now();
|
||||||
this._globalStatusNotice = createGlobalStatusNotice(message, now, options);
|
const next = createGlobalStatusNotice(message, now, options);
|
||||||
|
const current = this._globalStatusNotice;
|
||||||
|
if (next?.persistent && current && !current.persistent) {
|
||||||
|
// A persistent notice arriving under a live finite one (the engine
|
||||||
|
// notice after a share link's "kept in the link") waits for it.
|
||||||
|
this._coveredPersistentNotice = next;
|
||||||
|
this._updateGlobalLoadingFeedback(now);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (next && !next.persistent) {
|
||||||
|
if (current?.persistent) this._coveredPersistentNotice = current;
|
||||||
|
} else {
|
||||||
|
this._coveredPersistentNotice = null;
|
||||||
|
}
|
||||||
|
this._globalStatusNotice = next;
|
||||||
this._updateGlobalLoadingFeedback(now);
|
this._updateGlobalLoadingFeedback(now);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -404,3 +404,72 @@ test('busy traffic completion is polled promptly without accelerating idle or gl
|
|||||||
f.restore();
|
f.restore();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('a finite notice covers the persistent engine notice only for its dwell', () => {
|
||||||
|
const f = fixture();
|
||||||
|
const realNow = performance.now;
|
||||||
|
let now = 1_000;
|
||||||
|
performance.now = () => now;
|
||||||
|
try {
|
||||||
|
const owner = new ShellFeedback({ readLayers: () => [] });
|
||||||
|
const detail = () => f.nodes.get('global-loading-detail').textContent;
|
||||||
|
owner._showGlobalStatusNotice('Experimental Navara engine', {
|
||||||
|
state: 'retry',
|
||||||
|
detail: 'No data layers on this engine yet',
|
||||||
|
persistent: true,
|
||||||
|
});
|
||||||
|
assert.equal(detail(), 'No data layers on this engine yet');
|
||||||
|
owner._showGlobalStatusNotice('NOT ON THIS ENGINE', {
|
||||||
|
state: 'retry',
|
||||||
|
detail: 'Kept in the link: CCTV',
|
||||||
|
dwellMs: 15_000,
|
||||||
|
});
|
||||||
|
assert.equal(detail(), 'Kept in the link: CCTV');
|
||||||
|
now += 14_000;
|
||||||
|
owner._updateGlobalLoadingFeedback(now);
|
||||||
|
assert.equal(detail(), 'Kept in the link: CCTV', 'still up after 14 s');
|
||||||
|
now += 2_000;
|
||||||
|
owner._updateGlobalLoadingFeedback(now);
|
||||||
|
owner._updateGlobalLoadingFeedback(now);
|
||||||
|
assert.equal(
|
||||||
|
detail(),
|
||||||
|
'No data layers on this engine yet',
|
||||||
|
'the engine notice comes back',
|
||||||
|
);
|
||||||
|
assert.equal(owner._globalStatusNotice?.persistent, true);
|
||||||
|
owner.destroy();
|
||||||
|
} finally {
|
||||||
|
performance.now = realNow;
|
||||||
|
f.restore();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('a persistent notice that arrives under a finite one waits for it', () => {
|
||||||
|
const f = fixture();
|
||||||
|
const realNow = performance.now;
|
||||||
|
let now = 1_000;
|
||||||
|
performance.now = () => now;
|
||||||
|
try {
|
||||||
|
const owner = new ShellFeedback({ readLayers: () => [] });
|
||||||
|
const detail = () => f.nodes.get('global-loading-detail').textContent;
|
||||||
|
owner._showGlobalStatusNotice('NOT ON THIS ENGINE', {
|
||||||
|
state: 'retry',
|
||||||
|
detail: 'Kept in the link: Earthquakes',
|
||||||
|
dwellMs: 15_000,
|
||||||
|
});
|
||||||
|
owner._showGlobalStatusNotice('Experimental Navara engine', {
|
||||||
|
state: 'retry',
|
||||||
|
detail: 'No data layers on this engine yet',
|
||||||
|
persistent: true,
|
||||||
|
});
|
||||||
|
assert.equal(detail(), 'Kept in the link: Earthquakes');
|
||||||
|
now += 16_000;
|
||||||
|
owner._updateGlobalLoadingFeedback(now);
|
||||||
|
owner._updateGlobalLoadingFeedback(now);
|
||||||
|
assert.equal(detail(), 'No data layers on this engine yet');
|
||||||
|
owner.destroy();
|
||||||
|
} finally {
|
||||||
|
performance.now = realNow;
|
||||||
|
f.restore();
|
||||||
|
}
|
||||||
|
});
|
||||||
Reference in new issue
Block a user