From 393c31d86e398309ef4a51220ffd175365c4e226 Mon Sep 17 00:00:00 2001 From: Sameh Khamis Date: Sun, 13 Sep 2026 03:08:42 -0700 Subject: [PATCH] fix: prevent stopped Cockpit briefings from restarting --- src/ui/cockpitBriefing.js | 5 ++++ src/ui/cockpitController.test.mjs | 45 +++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/src/ui/cockpitBriefing.js b/src/ui/cockpitBriefing.js index d6f222cfc..c467ed865 100644 --- a/src/ui/cockpitBriefing.js +++ b/src/ui/cockpitBriefing.js @@ -11,6 +11,7 @@ import { } from './cockpitPresentation.js'; export function showBriefPage(index, { manual = false } = {}) { + if (this.destroyed) return; const count = COCKPIT_BRIEF_PAGES.length; this.briefPageIndex = ((Number(index) % count) + count) % count; const page = COCKPIT_BRIEF_PAGES[this.briefPageIndex]; @@ -41,6 +42,7 @@ export function showBriefPage(index, { manual = false } = {}) { } export function setBriefAutoRotate(enabled) { + if (this.destroyed) return; this.briefAutoRotateEnabled = Boolean(enabled); if (this.briefAutoToggle) { this.briefAutoToggle.setAttribute( @@ -60,6 +62,7 @@ export function setBriefAutoRotate(enabled) { } export function startBriefRotation({ reset = false } = {}) { + if (this.destroyed) return; if (reset) this.stopBriefRotation(); if ( !this.briefAutoRotateEnabled || @@ -71,6 +74,7 @@ export function startBriefRotation({ reset = false } = {}) { return; this.briefTimer = window.setTimeout(() => { this.briefTimer = null; + if (this.destroyed) return; const hasPointer = this.signalStream?.matches(':hover') === true; const hasFocus = this.signalStream?.contains(document.activeElement) === true; @@ -99,6 +103,7 @@ export function updateLocalPosition(info) { } export function maybeRefreshRegionalBrief(info) { + if (this.destroyed) return; if ( !this.active || !Number.isFinite(info.latitude) || diff --git a/src/ui/cockpitController.test.mjs b/src/ui/cockpitController.test.mjs index e92be00a2..c700bb537 100644 --- a/src/ui/cockpitController.test.mjs +++ b/src/ui/cockpitController.test.mjs @@ -164,3 +164,48 @@ test('stopping Cockpit revokes camera actions before deferred disposal releases env.restore(); } }); + +test('stopped Cockpit cannot rearm briefing rotation or request a fresh region', () => { + const env = environment(); + try { + const frames = new Map(); + let next = 0; + let fetches = 0; + let paints = 0; + env.viewer.scene.screenSpaceCameraController.enableInputs = true; + window.setTimeout = (callback) => { + frames.set(++next, callback); + return next; + }; + window.clearTimeout = (id) => frames.delete(id); + const owner = new CockpitViewController(env.viewer, { + services: { + regionalDistanceM: () => Infinity, + fetchRegionalBrief: () => { + fetches++; + return Promise.resolve({ articles: [] }); + }, + releaseContinuousRender() {}, + }, + }); + owner.active = true; + owner.showBriefPage = () => { + paints++; + }; + owner.setBriefAutoRotate(true); + assert.equal(frames.size, 1); + const queued = [...frames.values()][0]; + owner.stop(); + assert.equal(frames.size, 0); + queued(); + owner.setBriefAutoRotate(true); + owner.startBriefRotation(); + owner.maybeRefreshRegionalBrief({ latitude: 30, longitude: -97 }); + assert.equal(frames.size, 0); + assert.equal(paints, 0); + assert.equal(fetches, 0); + owner.dispose(); + } finally { + env.restore(); + } +});