mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
fix(street-level): /revmain cleanup after the slim rebuild
- Google 3D: the OPEN button re-measures a ground whose tiles are still loading (a few times, a second apart) and on a map change, not only after the next camera move. - Mapillary: two mounts on one host during the first download share one build instead of leaking a second WebGL viewer. - Retired floating-panel keys (v8 panelPos, panelFloatHintShown) are dropped from localStorage; dead inline-position resets, the drag JSDoc and the dead qa-ui-disposal observer branch are gone. - Docs: z ladder, panel chrome, position storage and the fixture gate's actual coverage; changelog fragment for #974 (old .gev-cache/mapillary can be deleted). - ru/es: the layer is named as everywhere else in the UI. - Fixtures and test fakes: unused exports removed; a fake credit removal of an absent credit no longer drops another one; the tile test reset frees upstream slots. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
00e8e3b997
commit
28e0ba7104
22 files changed
+220
-74
No files matched your search
@@ -53,8 +53,7 @@ import { applyLocaleChoice, mountLocalePicker } from './localePicker.js';
|
||||
* Responsibilities:
|
||||
* - Visual controls and presets backed by the VisualEffects controller.
|
||||
* - Bloom and sharpen post-processing toggle/intensity control.
|
||||
* - Draggable/collapsible panel system with localStorage persistence,
|
||||
* z-order stacking, and viewport-clamped positioning.
|
||||
* - Collapsible rail panels with their collapsed state kept in localStorage.
|
||||
* - CCTV panel: camera selection, coverage toggle, projection, calibration
|
||||
* sliders, auto-hop, and summary typewriter effect.
|
||||
* - Location bar with city/POI preset pills, QWERTY key navigation,
|
||||
@@ -1204,19 +1203,6 @@ export class StyleManager extends ShellFacade {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a panel draggable via its handle element. Implements:
|
||||
* - Z-order promotion: each pointerdown increments the global z-counter
|
||||
* so the clicked panel floats above siblings.
|
||||
* - Viewport clamping: drag moves are clamped to a 6px inset from all edges.
|
||||
* - Right-rail pinning: pp-toggles panel is re-anchored right after drag.
|
||||
* - CCTV viewport sync: cctv-panel recalculates scroll height after drag.
|
||||
* @param {string} panelId - DOM id of the panel.
|
||||
* @param {HTMLElement} panelEl - The panel DOM element.
|
||||
* @param {HTMLElement} handleEl - The drag handle element within the panel.
|
||||
* @returns {void}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Programmatically collapses or expands a panel, persists the state,
|
||||
* and triggers layout recalculation for dependent panels.
|
||||
|
||||
@@ -189,12 +189,6 @@ export class PanelLayoutController {
|
||||
const stack = this._rightPanelStack;
|
||||
if (!stack || !this._ppToggles) return;
|
||||
|
||||
this._ppToggles.style.removeProperty('top');
|
||||
this._ppToggles.style.removeProperty('right');
|
||||
this._ppToggles.style.removeProperty('bottom');
|
||||
this._ppToggles.style.removeProperty('left');
|
||||
this._ppToggles.style.removeProperty('z-index');
|
||||
this._ppToggles.querySelector('.pp-header-row')?.removeAttribute('title');
|
||||
stack.prepend(this._ppToggles);
|
||||
const globalContextPanel = document.getElementById('global-context-panel');
|
||||
for (const panel of [
|
||||
@@ -204,8 +198,6 @@ export class PanelLayoutController {
|
||||
this._streetLevelPanel,
|
||||
]) {
|
||||
if (!panel) continue;
|
||||
for (const property of ['top', 'right', 'bottom', 'left', 'z-index'])
|
||||
panel.style.removeProperty(property);
|
||||
stack.insertBefore(panel, globalContextPanel);
|
||||
this._syncPanelCollapseButton(panel);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,11 @@ const PANEL_LAYOUT_STORAGE_VERSION = 'v6';
|
||||
* the layout-reset notice and the documented key.
|
||||
*/
|
||||
const PANEL_POSITION_STORAGE_VERSION = 'v8';
|
||||
/** Floating panels' stored positions and hint flag: nothing reads them now. */
|
||||
const RETIRED_PANEL_KEY_PREFIXES = [
|
||||
`godsEyeView.${PANEL_POSITION_STORAGE_VERSION}.panelPos.`,
|
||||
`godsEyeView.${PANEL_POSITION_STORAGE_VERSION}.panelFloatHintShown`,
|
||||
];
|
||||
export class PanelPositionControls {
|
||||
constructor({ syncPanelCollapseButton, showToast }) {
|
||||
this._syncPanelCollapseButton = syncPanelCollapseButton;
|
||||
@@ -15,6 +20,7 @@ export class PanelPositionControls {
|
||||
}
|
||||
|
||||
_maybeNotifyLayoutReset() {
|
||||
this._dropRetiredPanelKeys();
|
||||
try {
|
||||
const marker = `godsEyeView.${PANEL_POSITION_STORAGE_VERSION}.layoutResetNotified`;
|
||||
if (localStorage.getItem(marker)) return;
|
||||
@@ -32,6 +38,16 @@ export class PanelPositionControls {
|
||||
}
|
||||
}
|
||||
|
||||
_dropRetiredPanelKeys() {
|
||||
try {
|
||||
for (const key of Object.keys(localStorage))
|
||||
if (RETIRED_PANEL_KEY_PREFIXES.some((prefix) => key.startsWith(prefix)))
|
||||
localStorage.removeItem(key);
|
||||
} catch {
|
||||
// storage unavailable
|
||||
}
|
||||
}
|
||||
|
||||
_panelCollapseStorageKey(panelId) {
|
||||
return `godsEyeView.${PANEL_LAYOUT_STORAGE_VERSION}.panelCollapsed.${panelId}`;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import { PanelPositionControls } from './panelPositionControls.js';
|
||||
|
||||
/** A localStorage stand-in whose keys enumerate like the real one. */
|
||||
function fakeStorage(entries) {
|
||||
const storage = {};
|
||||
Object.defineProperties(storage, {
|
||||
getItem: { value: (key) => (key in storage ? storage[key] : null) },
|
||||
setItem: { value: (key, value) => (storage[key] = String(value)) },
|
||||
removeItem: { value: (key) => delete storage[key] },
|
||||
});
|
||||
Object.assign(storage, entries);
|
||||
return storage;
|
||||
}
|
||||
|
||||
test('the floating panels’ stored positions and hint flag are dropped; collapse state stays', (t) => {
|
||||
const saved = globalThis.localStorage;
|
||||
globalThis.localStorage = fakeStorage({
|
||||
'godsEyeView.v8.panelPos.cctv-panel': '{"x":1}',
|
||||
'godsEyeView.v8.panelFloatHintShown': '1',
|
||||
'godsEyeView.v6.panelCollapsed.cctv-panel': '1',
|
||||
'godsEyeView.v8.layoutResetNotified': '1',
|
||||
});
|
||||
t.after(() => {
|
||||
globalThis.localStorage = saved;
|
||||
});
|
||||
const controls = new PanelPositionControls({ showToast() {} });
|
||||
controls._maybeNotifyLayoutReset();
|
||||
assert.deepEqual(Object.keys(globalThis.localStorage).sort(), [
|
||||
'godsEyeView.v6.panelCollapsed.cctv-panel',
|
||||
'godsEyeView.v8.layoutResetNotified',
|
||||
]);
|
||||
});
|
||||
@@ -228,7 +228,7 @@ test('recording restores the original HUD after repeated entry and revokes retai
|
||||
}
|
||||
});
|
||||
|
||||
test('weather rail orders between CCTV and Context, resets positions, observes and syncs chrome', (t) => {
|
||||
test('weather rail orders between CCTV and Context, observes and syncs chrome', (t) => {
|
||||
const f = fixture();
|
||||
const observed = new Set();
|
||||
const previousResizeObserver = globalThis.ResizeObserver;
|
||||
@@ -263,16 +263,7 @@ test('weather rail orders between CCTV and Context, resets positions, observes a
|
||||
]) {
|
||||
const panel = f.nodes.get(id) || f.element();
|
||||
panel.id = id;
|
||||
const positions = new Map(
|
||||
['top', 'right', 'bottom', 'left', 'z-index'].map((key) => [
|
||||
key,
|
||||
'20px',
|
||||
]),
|
||||
);
|
||||
panel.style = {
|
||||
removeProperty: (key) => positions.delete(key),
|
||||
positions,
|
||||
};
|
||||
panel.style = {};
|
||||
panel.classList.add('collapsed');
|
||||
const button = f.element();
|
||||
button.closest = () => panel;
|
||||
@@ -307,7 +298,6 @@ test('weather rail orders between CCTV and Context, resets positions, observes a
|
||||
);
|
||||
assert.ok(synced.includes('weather-panel'));
|
||||
assert.ok(observed.has(weather));
|
||||
assert.equal(weather.style.positions.size, 0);
|
||||
assert.equal(weather.button.textContent, '◀');
|
||||
assert.equal(weather.button.getAttribute('aria-expanded'), 'false');
|
||||
assert.equal(weather.button.title, 'Expand WEATHER');
|
||||
|
||||
Vendored
+1
-1
@@ -381,7 +381,7 @@ body.cockpit-mode #cockpit-cloud-effects.active {
|
||||
position: fixed;
|
||||
right: 36px;
|
||||
bottom: 36px;
|
||||
/* Z ladder: panels 100-139, voice pill 150, toast 200, clean-view-exit 300 */
|
||||
/* Z ladder: panels ~100, voice pill 150, toast 200, clean-view-exit 300 */
|
||||
z-index: 150;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in new issue
Block a user