Collapse the CCTV panel when the user switches CCTV off inside Contacts

Turning a layer on does not leave Contacts, so a user could turn CCTV back
on inside the mode and off again; the layer was still in the session
snapshot and the panel stayed open on an empty frame. The snapshot now
records every layer the user switched during the session, and
suspendsLayer is true only for a layer isolation switched off that the
user has not touched since.
This commit is contained in:
Sameh Khamis committed 2026-11-13 18:12:44 -08:00
1 parent f29b0b2639
commit f0ee1b95ca
4 files changed
+47 -2

No files matched your search

+1
View File
@@ -277,6 +277,7 @@ export function recordContextSessionUserChange({
) {
return false;
}
snapshot.userSwitched?.add(change.layerId);
const isCompanion = CONTEXT_COMPANIONS.has(change.layerId);
if (change.enabled) {
if (CONTEXT_ENTRY_LAYER_IDS.includes(change.layerId)) return false;
+7 -2
View File
@@ -61,12 +61,17 @@ export class ContextControls {
}
/**
* Whether Context isolation switched this layer off and leaving the mode
* restores it. Such a layer is suspended, not switched off by the user.
* restores it. Such a layer is suspended, not switched off by the user: a
* layer the user switched during the session is theirs again.
* @param {string} layerId Layer id.
* @returns {boolean}
*/
suspendsLayer(layerId) {
return Boolean(this._contextSessionSnapshot?.enabledLayerIds?.has(layerId));
const snapshot = this._contextSessionSnapshot;
return Boolean(
snapshot?.enabledLayerIds?.has(layerId) &&
!snapshot.userSwitched?.has(layerId),
);
}
setClearBusy(...args) {
if (!this.destroyed) this.actions.setClearBusy(...args);
+36
View File
@@ -1,6 +1,7 @@
import assert from 'node:assert/strict';
import { test } from 'node:test';
import { ContextControls } from './contextControls.js';
import { recordContextSessionUserChange } from '../contextModePolicy.js';
class Button extends EventTarget {
constructor() {
@@ -189,3 +190,38 @@ test('a layer Context isolation switches off is suspended until the mode is left
await controls._dataManager.setEnabled('cctv', false);
assert.deepEqual(seen.at(-1), ['cctv', false, false]);
});
test('a layer the user switches inside the mode is no longer suspended', async (t) => {
const { controls } = fixture(t);
const enabled = new Set(['cctv']);
controls._dataManager = {
layers: new Map([['cctv', {}]]),
getEnabledLayerIds: () => [...enabled],
getLayerParams: () => null,
isEffectivelyEnabled: (layerId) => enabled.has(layerId),
isEnabled: (layerId) => enabled.has(layerId),
async setEnabled(layerId, next) {
if (next) enabled.add(layerId);
else enabled.delete(layerId);
return true;
},
};
controls._captureContextSessionSnapshot();
await controls._clearLayersOutsideContextMode('flights');
assert.equal(controls.suspendsLayer('cctv'), true);
// Inside Contacts the user turns CCTV back on, then off again: the panel
// must close like any other switch-off.
for (const next of [true, false]) {
recordContextSessionUserChange({
snapshot: controls._contextSessionSnapshot,
change: {
type: 'visibility',
origin: 'user',
layerId: 'cctv',
enabled: next,
},
effectiveContextMode: 'flights',
});
}
assert.equal(controls.suspendsLayer('cctv'), false);
});
+3
View File
@@ -36,6 +36,8 @@ export function _captureContextSessionSnapshot({ excludeLayerIds = [] } = {}) {
),
userAdded: new Set(),
userRemoved: new Set(),
// Every layer the user switched during the session, either way.
userSwitched: new Set(),
params,
};
}
@@ -149,6 +151,7 @@ export async function _restoreContextSession({
enabledLayerIds: new Set(restoreState.enabledLayerIds),
userAdded: new Set(),
userRemoved: new Set(),
userSwitched: new Set(),
params: snapshot.params,
};
}