mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-15 15:52:21 +00:00
fix(ghostmaps): follow-up review fixes for the age switch
- Keep the open card across a widened reload only when its index still holds the same report; the server may answer a pinned version with newer bytes. - Narrowing to a window the loaded data already covers clears a failed wider reload, so the row no longer stays in error. - Label the every-age option "All" (contextual) so the six-option switch fits the row in every locale; tooltip and info line keep "All markers". Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
c4298c4450
commit
91ab9b5811
14 files changed
+81
-7
No files matched your search
@@ -423,9 +423,18 @@ export function createGhostMapsLayer({
|
||||
// Cull before the first frame so far-side pins never flash.
|
||||
_horizon.update(next.pins);
|
||||
await _viewer.dataSources.add(next.dataSource);
|
||||
// The new edition is on the globe before the old one leaves. A wider
|
||||
// window over the same edition keeps indices, so the card stays.
|
||||
unload(product.id, loaded?.version === next.version);
|
||||
// The new edition is on the globe before the old one leaves. The card
|
||||
// stays only if its index still holds the same report: the server
|
||||
// may answer a pinned version with newer bytes.
|
||||
const index = Number(_selectedKey?.split(':')[1]);
|
||||
const before = loaded?.features.get(index);
|
||||
const after = next.features.get(index);
|
||||
unload(
|
||||
product.id,
|
||||
Boolean(before && after) &&
|
||||
before.name === after.name &&
|
||||
before.description === after.description,
|
||||
);
|
||||
_loaded.set(product.id, next);
|
||||
} catch (error) {
|
||||
if (signal.aborted) return;
|
||||
@@ -477,12 +486,15 @@ export function createGhostMapsLayer({
|
||||
// Narrowing only removes markers. A product loaded with a narrower window
|
||||
// keeps its old ageDays, so sync() restores omitted placemarks from the
|
||||
// cached KMZ even though its upstream version has not changed.
|
||||
for (const item of _loaded.values())
|
||||
for (const [id, item] of _loaded)
|
||||
if (
|
||||
item.ageDays === null ||
|
||||
(ageDays !== null && item.ageDays >= ageDays)
|
||||
)
|
||||
) {
|
||||
item.ageDays = ageDays;
|
||||
// A failed wider reload no longer matters; a stale edition retries.
|
||||
_failed.delete(id);
|
||||
}
|
||||
notifyRow();
|
||||
return sync();
|
||||
}
|
||||
@@ -745,7 +757,7 @@ export function createGhostMapsLayer({
|
||||
id: `age-${days ?? 'all'}`,
|
||||
label:
|
||||
days === null
|
||||
? t('All markers')
|
||||
? t('All', { context: 'event age filter' })
|
||||
: t('{days}d', { days: formatNumber(days) }),
|
||||
title:
|
||||
days === null
|
||||
|
||||
@@ -558,3 +558,54 @@ test('a report dated yesterday is shown by 1d one hour into today (UTC)', async
|
||||
await ageChip(layer, 1).onClick();
|
||||
assert.equal(layer.getStats().count, 1);
|
||||
});
|
||||
|
||||
test('a widened reload that returns a different report at the selected index closes its card', async (t) => {
|
||||
let click;
|
||||
const cards = [];
|
||||
const reports = [dated('Recent', '11/2/2026'), dated('Older', '10/20/2026')];
|
||||
const { layer, viewer } = fixture(t, {
|
||||
now: () => Date.UTC(2026, 10, 3, 12),
|
||||
reports,
|
||||
controls: {
|
||||
overlayHost: { setEntries: (_id, entries) => cards.push(entries) },
|
||||
screenSpaceEventHandlerFactory: () => ({
|
||||
setInputAction: (fn) => {
|
||||
click = fn;
|
||||
},
|
||||
destroy() {},
|
||||
}),
|
||||
picking: { resolvePickId: (picked) => picked },
|
||||
},
|
||||
});
|
||||
await layer.update(viewer);
|
||||
viewer.scene.pick = () => 'ghostmaps:cip:0:0';
|
||||
click({ position: { x: 0, y: 0 } });
|
||||
assert.equal(cards.at(-1).length, 1);
|
||||
// The server answers the pinned version with a newer edition's bytes.
|
||||
reports[0] = dated('Replacement', '11/2/2026');
|
||||
await ageChip(layer, 30).onClick();
|
||||
assert.equal(layer.getStats().count, 2);
|
||||
assert.equal(
|
||||
cards.at(-1).length,
|
||||
0,
|
||||
'a different report must not keep the old card',
|
||||
);
|
||||
});
|
||||
|
||||
test('narrowing to a window the loaded data covers clears a failed wider reload', async (t) => {
|
||||
let fail = false;
|
||||
const { layer, viewer } = fixture(t, {
|
||||
now: () => Date.UTC(2026, 10, 3, 12),
|
||||
reports: [dated('Recent', '11/2/2026'), dated('Older', '10/20/2026')],
|
||||
beforeFileReturns: () => {
|
||||
if (fail) throw new Error('network down');
|
||||
},
|
||||
});
|
||||
await layer.update(viewer);
|
||||
fail = true;
|
||||
await ageChip(layer, 30).onClick();
|
||||
assert.ok(layer.getStats().error, 'the wider reload failed');
|
||||
await ageChip(layer, 3).onClick();
|
||||
assert.equal(layer.getStats().error, null);
|
||||
assert.equal(layer.getStats().count, 1);
|
||||
});
|
||||
Reference in new issue
Block a user