Move the changelog entry to changelog.d and clear review leftovers

The entry now lives in changelog.d/1471-context-panel-cleanup.md with
credit, as CONTRIBUTING asks, and CHANGELOG.md is back to main.

CURRENT-STATE no longer lists a compact Radio power control and scopes
the readability description to what Cyber keeps. The responsive glow
comment no longer cites the removed Radio popover, and qa-radio's
pick-buffer comment is back above settleRadioFrames.

Four test fixtures stop stubbing the removed launcher sync, and
PanelChrome drops the _syncRailPanelCollapseButton pass-through, wiring
the layout controller straight to _syncPanelCollapseButton.
This commit is contained in:
Said Turksever committed 2026-10-29 16:35:44 +00:00
1 parent 97b7307b14
commit 9520238bfb
10 files changed
+14 -24

No files matched your search

-9
View File
@@ -2,15 +2,6 @@
## [Unreleased] ## [Unreleased]
- Remove the Radio icon from the Context panel header, along with the compact
Radio player it opened. Radio stays in Context as its own section, with one
Enable control and full playback. Cockpit's compact Radio is unchanged.
- Make the Context panel easier to read: the Contacts / Space Missions modes
are one segmented control, labels and guidance are larger and higher
contrast, the standby hint is plain text instead of a dashed box, and the
panel no longer draws a glow halo.
## [0.3.0] — 2026-10-27 — Street Level, On Your Phone, in Your Language ## [0.3.0] — 2026-10-27 — Street Level, On Your Phone, in Your Language
- Show a Street Level view facing 359.5° or more as 0°. The viewer caption - Show a Street Level view facing 359.5° or more as 0°. The viewer caption
@@ -0,0 +1,7 @@
- Remove the Radio icon from the Context panel header, along with the compact
Radio player it opened; Radio stays in Context as its own section, and
Cockpit's compact Radio is unchanged. Context is also easier to read: the
Contacts / Space Missions modes are one segmented control, labels and
guidance are larger and higher contrast, the standby hint is plain text
instead of a dashed box, and the panel draws no glow halo. Cyber keeps its
own framed buttons and red titles (asturksever, #1471).
+2 -2
View File
@@ -1996,7 +1996,7 @@ they do not reduce the materialized entity count or establish an FPS gain.
rotation and mission-marker highlight as pointer hover. Focus alone does not rotation and mission-marker highlight as pointer hover. Focus alone does not
select the mission; Enter or Space performs selection. Keyboard and pointer select the mission; Enter or Space performs selection. Keyboard and pointer
preview ownership remain independent when the pointer is parked over the list. preview ownership remain independent when the pointer is parked over the list.
- Radio power controls in the full, compact, and Cockpit surfaces, Search Nearby - Radio power controls in the full and Cockpit surfaces, Search Nearby
Sites, and Clear Selected Layers remain focusable while lifecycle work is in Sites, and Clear Selected Layers remain focusable while lifecycle work is in
progress. They announce busy/disabled semantics and ignore repeat activation progress. They announce busy/disabled semantics and ignore repeat activation
until the operation settles, so async work cannot drop the keyboard ring. until the operation settles, so async work cannot drop the keyboard ring.
@@ -4786,7 +4786,7 @@ silently demoting every later lookup for the session.
- If a civilian or military aircraft is already tracked when `CONTACTS` becomes operational, that source-owned track is adopted as the Context subject before nearest-contact autofocus. Context rechecks the tracker after its dependencies settle, so a newer selection wins, while an explicit clear during activation prevents fallback from silently selecting a replacement. Cockpit entry remains unavailable until that Context transaction has settled, so its camera takeover cannot clear Cesium tracking before adoption. Adoption does not recreate tracking or transfer camera ownership; it initializes the normal 250 km ring, history, proximity results, and Cockpit Previous/Next state for the original aircraft. - If a civilian or military aircraft is already tracked when `CONTACTS` becomes operational, that source-owned track is adopted as the Context subject before nearest-contact autofocus. Context rechecks the tracker after its dependencies settle, so a newer selection wins, while an explicit clear during activation prevents fallback from silently selecting a replacement. Cockpit entry remains unavailable until that Context transaction has settled, so its camera takeover cannot clear Cesium tracking before adoption. Adoption does not recreate tracking or transfer camera ownership; it initializes the normal 250 km ring, history, proximity results, and Cockpit Previous/Next state for the original aircraft.
- `SEARCH NEARBY SITES` retains the bounded OSM results and makes one user-initiated, view-biased Google Maps Places text search for “military installation.” Google results are source-stamped, deduplicated against OSM by rounded location/name, and remain mapped context rather than operational claims. If Places is unavailable or the API is not enabled for the supplied key, OSM context remains available. A view across the antimeridian is searched around its own centre, with a radius from its real width. - `SEARCH NEARBY SITES` retains the bounded OSM results and makes one user-initiated, view-biased Google Maps Places text search for “military installation.” Google results are source-stamped, deduplicated against OSM by rounded location/name, and remain mapped context rather than operational claims. If Places is unavailable or the API is not enabled for the supplied key, OSM context remains available. A view across the antimeridian is searched around its own centre, with a radius from its real width.
- The Context header holds only its title and collapse control. It no longer carries a Radio shortcut or a compact Radio player: Radio is the `RADIO` section inside the panel, with its own disclosure and the single `ENABLE` power control. Cockpit keeps its own compact Radio utility. - The Context header holds only its title and collapse control. It no longer carries a Radio shortcut or a compact Radio player: Radio is the `RADIO` section inside the panel, with its own disclosure and the single `ENABLE` power control. Cockpit keeps its own compact Radio utility.
- Context is set for reading: the two modes form one segmented control with 10 px labels, the standby guidance is plain left-aligned text rather than a dashed placeholder, action buttons use 10 px labels, section titles use `--text-secondary`, and the panel draws no glow halo. - Context is set for reading in every theme: mode, standby and action labels are 10 px, and the panel draws no glow halo. Outside Cyber, the two modes form one segmented control, the standby guidance is plain left-aligned text rather than a dashed placeholder, and the expanded panel's section titles use `--text-secondary`. Cyber keeps its separately framed mode buttons, its red panel titles, and in layout-focus a framed, centred standby card over its radar art.
- The expanded desktop header omits the redundant `ON` label; the active mode button carries state. Expanded Contact results also omit the duplicate `GLOBAL CONTEXT` / `CONTEXT ONLY` status row and begin with the selected subject and its 250 km scope. Global Context does not fabricate a selected-entity model preview: the provisional hand-authored aircraft wireframe was removed because it was not geometry extracted from the selected entity's actual asset. - The expanded desktop header omits the redundant `ON` label; the active mode button carries state. Expanded Contact results also omit the duplicate `GLOBAL CONTEXT` / `CONTEXT ONLY` status row and begin with the selected subject and its 250 km scope. Global Context does not fabricate a selected-entity model preview: the provisional hand-authored aircraft wireframe was removed because it was not geometry extracted from the selected entity's actual asset.
- Dependency ownership is reversible: disabling Global Context releases only dependencies it enabled, while user-enabled layers remain on. This also removes the Military-layer suppression handoff when Global Context owned Military, allowing an already-enabled civilian Flights layer to resume its normal mixed rendering. If OpenSky is unavailable and has no last-good cache, Flights requests a capped 250 nm adsb.lol point snapshot around the current view anchor and labels that provenance explicitly; it never relabels military-feed rows as civilian data. If both inputs fail, Flights remains `UNKNOWN`. - Dependency ownership is reversible: disabling Global Context releases only dependencies it enabled, while user-enabled layers remain on. This also removes the Military-layer suppression handoff when Global Context owned Military, allowing an already-enabled civilian Flights layer to resume its normal mixed rendering. If OpenSky is unavailable and has no last-good cache, Flights requests a capped 250 nm adsb.lol point snapshot around the current view anchor and labels that provenance explicitly; it never relabels military-feed rows as civilian data. If both inputs fail, Flights remains `UNKNOWN`.
- Space Missions is replay-isolated: Rocket Launches and Satellites are the only Data Layers permitted while the mode is active. Direct UI and voice entry capture the same pre-entry snapshot; internal dependency and restoration enables do not create a user-owned Context session. Entry waits for incompatible layers to shut down, direct incompatible enables are blocked before lifecycle work, and the entry gate remains active through the complete Rocket Launches enable. A newer same-target ON request takes ownership of the pending entry without releasing its isolation snapshot, including when it arrives while the prior request is awaiting the adoption guard. A caller abort, resource cancellation, newer OFF, or layer teardown waits for exact manager settlement and restores that snapshot without resurrecting Rocket Launches. If an abort lands after only part of a restore settles, Context completes the same exact target without the stale caller signal and then replays newer explicit layer intent. Dedicated Voice Context cancellation reports a stable cancelled result plus the current Context state; generic layer visibility additionally exposes manager phase, reason, successor, and lifecycle details. Once an exact voice visibility intent commits, a newer voice turn cannot relabel it as cancelled while Context settlement completes; pre-commit aborts remain cancellable and final lifecycle mismatches remain failures. Clear Selected Layers reserves its complete captured OFF set before sequential teardown; a newer absolute request of any origin supersedes only its layer reservation and remains authoritative. A rejected layer teardown retains the truthful enabled state, rolls already-stopped siblings back to the captured pre-entry set, and aborts replay; rapid exit/re-entry serializes the full Satellite enabled-state and parameter restore before a new snapshot is taken. Contacts remains additive and restores user-enabled layers normally. - Space Missions is replay-isolated: Rocket Launches and Satellites are the only Data Layers permitted while the mode is active. Direct UI and voice entry capture the same pre-entry snapshot; internal dependency and restoration enables do not create a user-owned Context session. Entry waits for incompatible layers to shut down, direct incompatible enables are blocked before lifecycle work, and the entry gate remains active through the complete Rocket Launches enable. A newer same-target ON request takes ownership of the pending entry without releasing its isolation snapshot, including when it arrives while the prior request is awaiting the adoption guard. A caller abort, resource cancellation, newer OFF, or layer teardown waits for exact manager settlement and restores that snapshot without resurrecting Rocket Launches. If an abort lands after only part of a restore settles, Context completes the same exact target without the stale caller signal and then replays newer explicit layer intent. Dedicated Voice Context cancellation reports a stable cancelled result plus the current Context state; generic layer visibility additionally exposes manager phase, reason, successor, and lifecycle details. Once an exact voice visibility intent commits, a newer voice turn cannot relabel it as cancelled while Context settlement completes; pre-commit aborts remain cancellable and final lifecycle mismatches remain failures. Clear Selected Layers reserves its complete captured OFF set before sequential teardown; a newer absolute request of any origin supersedes only its layer reservation and remains authoritative. A rejected layer teardown retains the truthful enabled state, rolls already-stopped siblings back to the captured pre-entry set, and aborts replay; rapid exit/re-entry serializes the full Satellite enabled-state and parameter restore before a new snapshot is taken. Contacts remains additive and restores user-enabled layers normally.
+2 -2
View File
@@ -81,8 +81,6 @@ function check(name, ok, detail = '') {
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
// Native pick buffers and clustered overlay entries settle on rendered frames,
// not on wall-clock sleeps, particularly with software rendering.
// Radio lives only inside Context; a user reaches its controls by expanding // Radio lives only inside Context; a user reaches its controls by expanding
// Context and then Radio. Returns the prior collapse state so a step can put // Context and then Radio. Returns the prior collapse state so a step can put
// the panels back for the scenarios that follow. // the panels back for the scenarios that follow.
@@ -109,6 +107,8 @@ async function restoreRadioPanels(page, prior) {
}, prior); }, prior);
} }
// Native pick buffers and clustered overlay entries settle on rendered frames,
// not on wall-clock sleeps, particularly with software rendering.
async function settleRadioFrames(page) { async function settleRadioFrames(page) {
await page.evaluate(() => new Promise((resolve, reject) => { await page.evaluate(() => new Promise((resolve, reject) => {
const scene = window.__godsEyeView.viewer.scene; const scene = window.__godsEyeView.viewer.scene;
-1
View File
@@ -88,7 +88,6 @@ test('radio option text and accessible name use the same localized parentheses',
setLocale(locale); setLocale(locale);
const host = { const host = {
_radioPanel: element(), _radioFilter: element(), _radioPanel: element(), _radioFilter: element(),
_syncContextRadioLauncherState() {},
actions: { getLifecycle: () => null, scheduleLayout() {} }, actions: { getLifecycle: () => null, scheduleLayout() {} },
}; };
renderRadioState.call(host, { renderRadioState.call(host, {
+1 -6
View File
@@ -71,8 +71,7 @@ export class PanelChrome {
variant: this.hud.getVariant(), variant: this.hud.getVariant(),
}), }),
scheduleCockpitLayout: () => this.cockpitView?.scheduleContextLayout(), scheduleCockpitLayout: () => this.cockpitView?.scheduleContextLayout(),
syncPanelCollapseButton: (panel) => syncPanelCollapseButton: (panel) => this._syncPanelCollapseButton(panel),
this._syncRailPanelCollapseButton(panel),
readDisplayScrollTop: () => readDisplayScrollTop: () =>
this._displayPortalScrollRestoreOwner === 'standard' this._displayPortalScrollRestoreOwner === 'standard'
? this._standardDisplayScrollTop ? this._standardDisplayScrollTop
@@ -292,10 +291,6 @@ export class PanelChrome {
return this._panelLayout._scheduleLeftPanelLayout(options0); return this._panelLayout._scheduleLeftPanelLayout(options0);
} }
_syncRailPanelCollapseButton(panelEl) {
this._syncPanelCollapseButton(panelEl);
}
_syncPanelCollapseButton(panelEl) { _syncPanelCollapseButton(panelEl) {
const isRightRail = [ const isRightRail = [
'pp-toggles', 'pp-toggles',
@@ -22,7 +22,6 @@ function render(audioError) {
destroyed: false, destroyed: false,
_radioPanel: el(), _radioPanel: el(),
_radioPlaybackState: el(), _radioPlaybackState: el(),
_syncContextRadioLauncherState() {},
actions: { actions: {
getLifecycle: () => null, getLifecycle: () => null,
preservePanelStateDuringClear: () => false, preservePanelStateDuringClear: () => false,
@@ -27,7 +27,6 @@ for (const lifecycleState of ['enabling', 'disabling']) {
destroyed: false, destroyed: false,
_radioPanel: el(), _radioPanel: el(),
_radioEnableBtn: enable, _radioEnableBtn: enable,
_syncContextRadioLauncherState() {},
actions: { actions: {
getLifecycle: () => ({ getLifecycle: () => ({
lifecycleState, lifecycleState,
+1 -1
View File
@@ -281,7 +281,7 @@ test('weather rail orders between CCTV and Context, observes and syncs chrome',
const weather = f.nodes.get('weather-panel'); const weather = f.nodes.get('weather-panel');
stack.children = [weather, f.nodes.get('global-context-panel')]; stack.children = [weather, f.nodes.get('global-context-panel')];
const synced = []; const synced = [];
const chrome = { _syncContextRadioLauncherState() {} }; const chrome = {};
const owner = new PanelLayoutController({ const owner = new PanelLayoutController({
readHud: () => ({}), readHud: () => ({}),
scheduleCockpitLayout() {}, scheduleCockpitLayout() {},
+1 -1
View File
@@ -205,7 +205,7 @@
under the expanded panel plus a vertical scrollbar that scrolls nothing under the expanded panel plus a vertical scrollbar that scrolls nothing
but glow. Pin the glow to the panel box here — its blur is ink overflow, but glow. Pin the glow to the panel box here — its blur is ink overflow,
which never scrolls — instead of clipping the rail, which would also clip which never scrolls — instead of clipping the rail, which would also clip
legitimate content such as the Context radio popover. */ legitimate content that extends past a panel's edge. */
#left-panel-stack .panel-glow, #left-panel-stack .panel-glow,
#right-context-rail .panel-glow { #right-context-rail .panel-glow {
inset: 0; inset: 0;