Keep Vue layer rows mounted through globe switches and rollback

This commit is contained in:
German Khokhlov committed 2026-11-03 02:38:25 +04:00
1 parent 2ee09c5911
commit d7ab85f5c4
4 files changed
+31 -5

No files matched your search

+4
View File
@@ -96,6 +96,7 @@ try {
window.__handoff = {
dataManager,
entry,
row: document.querySelector('[data-layer-id="flights"] .data-toggle-btn'),
timer: entry.intervalId,
model: entry.module,
pollCount: window.__flightPolls,
@@ -145,6 +146,8 @@ try {
before.dataManager === dataManager &&
before.entry === entry &&
before.model === entry.module,
sameRow: Boolean(before.row) &&
before.row === document.querySelector('[data-layer-id="flights"] .data-toggle-btn'),
sameTimer:
before.timer === entry.intervalId && entry.intervalId != null,
sourcePolls: window.__flightPolls - before.pollCount,
@@ -162,6 +165,7 @@ try {
assert.ok(
result.sameOwner &&
result.sameTimer &&
result.sameRow &&
result.active &&
result.hud &&
result.drawn,
+7 -3
View File
@@ -34,10 +34,14 @@ export function createApplicationData({
`Data layers could not be destroyed: ${[...dataManager.layers.keys()].join(', ')}`,
);
});
const presentation = new LayerPresentation(dataManager, {
const presentation = layerSession?.presentation ?? new LayerPresentation(dataManager, {
weatherClock: catalog?.weatherClock,
});
defer(() => presentation.destroy());
if (layerSession) layerSession.presentation = presentation;
defer(() => {
if (layerSession && !layerSession.lifetime.signal.aborted) presentation.suspend();
else presentation.destroy();
});
onData?.(dataManager);
if (!catalog?.layers || !catalog?.metadata)
throw new TypeError('An application layer catalog is required');
@@ -66,7 +70,7 @@ export function createApplicationData({
delete window.__gevQaUnregisterLayer;
});
}
presentation.mount(document.getElementById('data-toggles'));
presentation.mount(document.getElementById('data-toggles'), catalog.weatherClock);
styleManager.attachDataManager(dataManager);
// The sonar scene draws on the viewer; the Navara engine has none.
if (viewer) defer(createCyberSonarScene(viewer, dataManager));
+9 -1
View File
@@ -17,6 +17,7 @@ export class LayerPresentation {
this._panel = null;
this.pendingVisible = false;
this._unsubscribe = manager.subscribeActivity((change) => {
if (this.suspended && change.type !== 'destroy-all') return;
if (change.type === 'status') this.refresh();
else if (change.type === 'destroy-all') this.destroy();
else {
@@ -67,9 +68,16 @@ export class LayerPresentation {
});
return this._panel;
}
mount(container) {
mount(container, weatherClock = this.weatherClock) {
this.weatherClock = weatherClock;
this.panel.weatherClock = weatherClock;
this.suspended = false;
this.panel.mount(container);
}
suspend() {
this.suspended = true;
this._panel?.suspend();
}
/** Hand the Recent Imagery readout factory to the panel (see LayerPanel). */
attachRecentImagery(factory) {
// Detaching never builds a panel that teardown already released.
+11 -1
View File
@@ -273,6 +273,7 @@ export class LayerPanel {
}
mount(container) {
if (this._destroyed) return;
this._suspended = false;
this._releaseBindings();
if (this._toggleContainer && this._toggleContainer !== container)
renderVue(null, this._toggleContainer);
@@ -315,6 +316,15 @@ export class LayerPanel {
this._cancelRowControlsRefresh = null;
for (const remove of this._removers.splice(0)) remove();
}
// During a globe switch the keyed Vue rows stay mounted. Their event
// generation expires here, before any legacy scene-owned modules are freed.
suspend() {
this._suspended = true;
this._releaseBindings();
this._weatherPanel?.destroy();
this._weatherPanel = null;
this.attachRecentImagery(null);
}
destroy() {
if (this._destroyed) return;
this._destroyed = true;
@@ -383,7 +393,7 @@ export class LayerPanel {
/** Present every row from the layers' current state and render them. */
_paint() {
if (this._destroyed || !this._toggleContainer) return;
if (this._destroyed || this._suspended || !this._toggleContainer) return;
const layers = new Map(this.getAll().map((layer) => [layer.id, layer]));
const items = this._rows.map((row) => {
if (row.heading) return { key: row.key, heading: t(row.heading) };