fix(vessels): pin the idle-render contract and move the entry to a fragment

- The trailing visibility frame uses the layer's injectable runtime timer and
  is cancelled by resetState as well as disable and destroy.
- An empty-feed regular pass records the camera pose, so later in-cadence
  frames do not keep scheduling trailing frames.
- New renderGovernor.test.mjs: a parked camera schedules nothing, a stopped
  camera gets exactly one trailing frame and no self-wake, a forced pass
  requests its frame, destroy cancels the timer.
- The CHANGELOG entry moves to changelog.d/871-vessels-idle-render.md; docs
  say the hold also covers vessels dimmed under a live target.
This commit is contained in:
Said Turksever committed 2026-10-28 15:15:57 +00:00
1 parent 87133e8dbf
commit e6d2babea0
6 files changed
+175 -5

No files matched your search

+11 -3
View File
@@ -223,7 +223,7 @@ export function createRendering({
0,
VISIBILITY_UPDATE_MS - (now - state.lastVisibilityUpdate),
);
state.trailingVisibilityTimer = setTimeout(() => {
state.trailingVisibilityTimer = vesselState._aisRuntime.setTimeout(() => {
state.trailingVisibilityTimer = null;
if (state.feed.enabled) governorRequestRender('ais-vessels-visibility');
}, waitMs);
@@ -231,7 +231,7 @@ export function createRendering({
function cancelTrailingVisibilityPass() {
if (!state.trailingVisibilityTimer) return;
clearTimeout(state.trailingVisibilityTimer);
vesselState._aisRuntime.clearTimeout(state.trailingVisibilityTimer);
state.trailingVisibilityTimer = null;
}
@@ -256,7 +256,15 @@ export function createRendering({
if (focusPass) state.lastFocusUpdate = now;
if (!state.records.all.length) {
// No records — flush any lingering card entries (vanished-feed case).
if (regularPass) updateClusteredLabels([]);
// Still record the pose this pass evaluated, or every later frame that
// falls inside the cadence would schedule another trailing frame.
if (regularPass) {
if (state.viewer?.camera)
vesselState._lastCamPoseSig = cameraPoseSignature(
state.viewer.camera,
);
updateClusteredLabels([]);
}
if (focusPass) {
state.activeFocusCount = 0;
releaseContinuousRender('ais-vessels');