mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-12 06:12:18 +00:00
Hide map panels when entering the cockpit
This commit is contained in:
1 parent
2087b55b47
commit
73ea608881
4 files changed
+51
-7
No files matched your search
@@ -4,6 +4,7 @@ import fs from 'node:fs';
|
|||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
import puppeteer from 'puppeteer';
|
import puppeteer from 'puppeteer';
|
||||||
|
import { blockPaidQaMaps } from './qa-map-policy.mjs';
|
||||||
|
|
||||||
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||||||
const shotsDir = path.join(repoRoot, 'qa-shots', 'cockpit-utility');
|
const shotsDir = path.join(repoRoot, 'qa-shots', 'cockpit-utility');
|
||||||
@@ -29,6 +30,7 @@ const browser = await puppeteer.launch({
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
const page = await browser.newPage();
|
const page = await browser.newPage();
|
||||||
|
await blockPaidQaMaps(page);
|
||||||
const failures = [];
|
const failures = [];
|
||||||
const consoleErrors = [];
|
const consoleErrors = [];
|
||||||
const localHttpErrors = [];
|
const localHttpErrors = [];
|
||||||
@@ -827,6 +829,7 @@ try {
|
|||||||
const readinessPage = await browser.newPage();
|
const readinessPage = await browser.newPage();
|
||||||
let deferredInstallationReadiness;
|
let deferredInstallationReadiness;
|
||||||
try {
|
try {
|
||||||
|
await blockPaidQaMaps(readinessPage);
|
||||||
await readinessPage.setViewport({ width: 1440, height: 900 });
|
await readinessPage.setViewport({ width: 1440, height: 900 });
|
||||||
readinessPage.on('pageerror', (error) => consoleErrors.push(error.message));
|
readinessPage.on('pageerror', (error) => consoleErrors.push(error.message));
|
||||||
await readinessPage.setRequestInterception(true);
|
await readinessPage.setRequestInterception(true);
|
||||||
@@ -1150,6 +1153,14 @@ try {
|
|||||||
},
|
},
|
||||||
{ timeout: 10_000 },
|
{ timeout: 10_000 },
|
||||||
);
|
);
|
||||||
|
const startsClear = await page.evaluate(() => {
|
||||||
|
const hidden = ['left-panel-stack', 'intel-hud', 'corner-actions',
|
||||||
|
'cockpit-context', 'cockpit-signal-stream', 'cockpit-utility-controls'];
|
||||||
|
return hidden.every((id) => document.getElementById(id)?.getClientRects().length === 0)
|
||||||
|
&& document.getElementById('cockpit-speed-value').getClientRects().length > 0;
|
||||||
|
});
|
||||||
|
check('Cockpit starts with flight instruments and hides the map panels', startsClear);
|
||||||
|
await page.click('#cockpit-panels-toggle');
|
||||||
const firstCockpitContact = await page.evaluate(() => {
|
const firstCockpitContact = await page.evaluate(() => {
|
||||||
const awareness = window.__godsEyeView.dataManager.layers
|
const awareness = window.__godsEyeView.dataManager.layers
|
||||||
.get('military-awareness')?.module;
|
.get('military-awareness')?.module;
|
||||||
@@ -1511,6 +1522,9 @@ try {
|
|||||||
const before = read();
|
const before = read();
|
||||||
document.getElementById('cockpit-entry')?.click();
|
document.getElementById('cockpit-entry')?.click();
|
||||||
await new Promise((resolve) => setTimeout(resolve, 120));
|
await new Promise((resolve) => setTimeout(resolve, 120));
|
||||||
|
const startsClear = document.getElementById('cockpit-panels-toggle').getAttribute('aria-pressed') === 'false';
|
||||||
|
document.getElementById('cockpit-panels-toggle').click();
|
||||||
|
await new Promise((resolve) => requestAnimationFrame(resolve));
|
||||||
const during = read();
|
const during = read();
|
||||||
manager.setPanelCollapsed('data-panel', false, { persist: false, syncShare: false });
|
manager.setPanelCollapsed('data-panel', false, { persist: false, syncShare: false });
|
||||||
await new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve)));
|
await new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve)));
|
||||||
@@ -1531,6 +1545,7 @@ try {
|
|||||||
before,
|
before,
|
||||||
during,
|
during,
|
||||||
after: read(),
|
after: read(),
|
||||||
|
startsClear,
|
||||||
exited,
|
exited,
|
||||||
clearancePx,
|
clearancePx,
|
||||||
contactAutoCollapsed,
|
contactAutoCollapsed,
|
||||||
@@ -1540,7 +1555,7 @@ try {
|
|||||||
});
|
});
|
||||||
check(
|
check(
|
||||||
'Cockpit temporarily collapses standard panels and restores the exact map layout on exit',
|
'Cockpit temporarily collapses standard panels and restores the exact map layout on exit',
|
||||||
cockpitPanelRoundTrip.exited
|
cockpitPanelRoundTrip.exited && cockpitPanelRoundTrip.startsClear
|
||||||
&& Object.values(cockpitPanelRoundTrip.during).every(Boolean)
|
&& Object.values(cockpitPanelRoundTrip.during).every(Boolean)
|
||||||
&& JSON.stringify(cockpitPanelRoundTrip.after)
|
&& JSON.stringify(cockpitPanelRoundTrip.after)
|
||||||
=== JSON.stringify(cockpitPanelRoundTrip.before)
|
=== JSON.stringify(cockpitPanelRoundTrip.before)
|
||||||
@@ -1605,6 +1620,7 @@ try {
|
|||||||
const states = [read()];
|
const states = [read()];
|
||||||
for (let index = 0; index < 6; index += 1) {
|
for (let index = 0; index < 6; index += 1) {
|
||||||
current.click();
|
current.click();
|
||||||
|
await Promise.resolve();
|
||||||
states.push(read());
|
states.push(read());
|
||||||
}
|
}
|
||||||
const originalStyle = manager.activeStyle;
|
const originalStyle = manager.activeStyle;
|
||||||
@@ -1616,8 +1632,10 @@ try {
|
|||||||
const enteredOnNoir = await reenter();
|
const enteredOnNoir = await reenter();
|
||||||
const entryNoir = read();
|
const entryNoir = read();
|
||||||
cockpit.setVisionMode('optical');
|
cockpit.setVisionMode('optical');
|
||||||
|
await Promise.resolve();
|
||||||
const normalInsideNoir = read();
|
const normalInsideNoir = read();
|
||||||
cockpit.setVisionMode('crt');
|
cockpit.setVisionMode('crt');
|
||||||
|
await Promise.resolve();
|
||||||
const cockpitOnlyCrt = read();
|
const cockpitOnlyCrt = read();
|
||||||
const exitedNoir = cockpit.exit({ restoreTracking: true }) === true;
|
const exitedNoir = cockpit.exit({ restoreTracking: true }) === true;
|
||||||
await settle();
|
await settle();
|
||||||
@@ -1692,6 +1710,9 @@ try {
|
|||||||
await page.screenshot({ path: path.join(shotsDir, 'vision-noir.png') });
|
await page.screenshot({ path: path.join(shotsDir, 'vision-noir.png') });
|
||||||
await page.evaluate(() => window.__godsEyeView.styleManager.cockpitView.setVisionMode('optical'));
|
await page.evaluate(() => window.__godsEyeView.styleManager.cockpitView.setVisionMode('optical'));
|
||||||
|
|
||||||
|
await page.$eval('#cockpit-panels-toggle', button => {
|
||||||
|
if (button.getAttribute('aria-pressed') === 'false') button.click();
|
||||||
|
});
|
||||||
const desktopState = async (variant, openKind) => page.evaluate(async ({ variantName, kind }) => {
|
const desktopState = async (variant, openKind) => page.evaluate(async ({ variantName, kind }) => {
|
||||||
const manager = window.__godsEyeView.styleManager;
|
const manager = window.__godsEyeView.styleManager;
|
||||||
const hud = document.getElementById('cockpit-hud');
|
const hud = document.getElementById('cockpit-hud');
|
||||||
@@ -1877,7 +1898,7 @@ try {
|
|||||||
// the wall Cockpit actually solves against — not by injecting an anchor.
|
// the wall Cockpit actually solves against — not by injecting an anchor.
|
||||||
// The card is bottom-anchored, so an explicit height moves its top edge.
|
// The card is bottom-anchored, so an explicit height moves its top edge.
|
||||||
const minTop = Math.max(96, window.innerHeight * 0.12);
|
const minTop = Math.max(96, window.innerHeight * 0.12);
|
||||||
const moveSignalTopTo = (wantTop) => {
|
const moveSignalTopTo = async (wantTop) => {
|
||||||
for (let pass = 0; pass < 8; pass += 1) {
|
for (let pass = 0; pass < 8; pass += 1) {
|
||||||
const rect = signal.getBoundingClientRect();
|
const rect = signal.getBoundingClientRect();
|
||||||
const delta = wantTop - rect.top;
|
const delta = wantTop - rect.top;
|
||||||
@@ -1890,9 +1911,11 @@ try {
|
|||||||
// the now-shorter strip, so idempotence is asserted where the strip's
|
// the now-shorter strip, so idempotence is asserted where the strip's
|
||||||
// composition is unchanged.)
|
// composition is unchanged.)
|
||||||
manager.cockpitView.syncSignalLayout();
|
manager.cockpitView.syncSignalLayout();
|
||||||
|
await Promise.resolve();
|
||||||
const firstPassTop = hud.style.getPropertyValue('--cockpit-utility-top');
|
const firstPassTop = hud.style.getPropertyValue('--cockpit-utility-top');
|
||||||
const firstPassPrimaryOnly = utility.classList.contains('layout-primary-only');
|
const firstPassPrimaryOnly = utility.classList.contains('layout-primary-only');
|
||||||
manager.cockpitView.syncSignalLayout();
|
manager.cockpitView.syncSignalLayout();
|
||||||
|
await Promise.resolve();
|
||||||
return {
|
return {
|
||||||
firstPassTop,
|
firstPassTop,
|
||||||
firstPassPrimaryOnly,
|
firstPassPrimaryOnly,
|
||||||
@@ -1903,6 +1926,7 @@ try {
|
|||||||
signal.style.maxHeight = 'none';
|
signal.style.maxHeight = 'none';
|
||||||
signal.style.height = '150px';
|
signal.style.height = '150px';
|
||||||
manager.cockpitView.syncSignalLayout();
|
manager.cockpitView.syncSignalLayout();
|
||||||
|
await Promise.resolve();
|
||||||
const expandedHeight = Math.max(displayControl.scrollHeight, displayControl.getBoundingClientRect().height);
|
const expandedHeight = Math.max(displayControl.scrollHeight, displayControl.getBoundingClientRect().height);
|
||||||
const collapsedHeight = Math.max(50, radioControl.scrollHeight);
|
const collapsedHeight = Math.max(50, radioControl.scrollHeight);
|
||||||
const stripHeight = expandedHeight + collapsedHeight + 7;
|
const stripHeight = expandedHeight + collapsedHeight + 7;
|
||||||
@@ -1927,11 +1951,11 @@ try {
|
|||||||
// because 150 px of card leaves a corridor sized for the OLD strip. Seed from
|
// because 150 px of card leaves a corridor sized for the OLD strip. Seed from
|
||||||
// the measured requirement instead, which holds for any future panel height,
|
// the measured requirement instead, which holds for any future panel height,
|
||||||
// and assert the precondition rather than assuming it.
|
// and assert the precondition rather than assuming it.
|
||||||
const roomySeed = moveSignalTopTo(exactSignalTop + 80);
|
const roomySeed = await moveSignalTopTo(exactSignalTop + 80);
|
||||||
const roomySeedExpanded = !utility.classList.contains('layout-primary-only')
|
const roomySeedExpanded = !utility.classList.contains('layout-primary-only')
|
||||||
&& roomySeed.firstPassPrimaryOnly === false;
|
&& roomySeed.firstPassPrimaryOnly === false;
|
||||||
const exact = {
|
const exact = {
|
||||||
...moveSignalTopTo(exactSignalTop),
|
...await moveSignalTopTo(exactSignalTop),
|
||||||
utilityTop: hud.style.getPropertyValue('--cockpit-utility-top'),
|
utilityTop: hud.style.getPropertyValue('--cockpit-utility-top'),
|
||||||
primaryOnly: utility.classList.contains('layout-primary-only'),
|
primaryOnly: utility.classList.contains('layout-primary-only'),
|
||||||
siblingVisible: getComputedStyle(radioControl).display !== 'none',
|
siblingVisible: getComputedStyle(radioControl).display !== 'none',
|
||||||
@@ -1941,7 +1965,7 @@ try {
|
|||||||
const constrained = {
|
const constrained = {
|
||||||
// One pixel on the far side of the same fit (`exactSignalTop` already sits
|
// One pixel on the far side of the same fit (`exactSignalTop` already sits
|
||||||
// one pixel inside it), so this is still the one-pixel constraint it claims.
|
// one pixel inside it), so this is still the one-pixel constraint it claims.
|
||||||
...moveSignalTopTo(exactSignalTop - 2 * BOUNDARY_EPSILON_PX),
|
...await moveSignalTopTo(exactSignalTop - 2 * BOUNDARY_EPSILON_PX),
|
||||||
utilityTop: hud.style.getPropertyValue('--cockpit-utility-top'),
|
utilityTop: hud.style.getPropertyValue('--cockpit-utility-top'),
|
||||||
primaryOnly: utility.classList.contains('layout-primary-only'),
|
primaryOnly: utility.classList.contains('layout-primary-only'),
|
||||||
siblingDisplay: getComputedStyle(radioControl).display,
|
siblingDisplay: getComputedStyle(radioControl).display,
|
||||||
@@ -1952,7 +1976,7 @@ try {
|
|||||||
<= signal.getBoundingClientRect().top - 7,
|
<= signal.getBoundingClientRect().top - 7,
|
||||||
};
|
};
|
||||||
const restored = {
|
const restored = {
|
||||||
...moveSignalTopTo(exactSignalTop + 80),
|
...await moveSignalTopTo(exactSignalTop + 80),
|
||||||
utilityTop: hud.style.getPropertyValue('--cockpit-utility-top'),
|
utilityTop: hud.style.getPropertyValue('--cockpit-utility-top'),
|
||||||
primaryOnly: utility.classList.contains('layout-primary-only'),
|
primaryOnly: utility.classList.contains('layout-primary-only'),
|
||||||
siblingVisible: getComputedStyle(radioControl).display !== 'none',
|
siblingVisible: getComputedStyle(radioControl).display !== 'none',
|
||||||
|
|||||||
@@ -210,6 +210,9 @@ export class CockpitViewController {
|
|||||||
this._listen(this.entry, 'click', () => this.enter());
|
this._listen(this.entry, 'click', () => this.enter());
|
||||||
this._listen(this.tr3bToggle, 'click', () => this.toggleTrackedTr3b());
|
this._listen(this.tr3bToggle, 'click', () => this.toggleTrackedTr3b());
|
||||||
this._listen(this.mapViewButton, 'click', () => this.exit());
|
this._listen(this.mapViewButton, 'click', () => this.exit());
|
||||||
|
this._listen(document.getElementById('view-switcher'), 'click', (event) => {
|
||||||
|
if (event.target.closest?.('#cockpit-panels-toggle')) this.scheduleContextLayout();
|
||||||
|
});
|
||||||
this._listen(this.visionPrevious, 'click', () => this.cycleVisionMode(-1));
|
this._listen(this.visionPrevious, 'click', () => this.cycleVisionMode(-1));
|
||||||
this._listen(this.visionCurrent, 'click', () => this.cycleVisionMode(1));
|
this._listen(this.visionCurrent, 'click', () => this.cycleVisionMode(1));
|
||||||
this._listen(this.visionNext, 'click', () => this.cycleVisionMode(1));
|
this._listen(this.visionNext, 'click', () => this.cycleVisionMode(1));
|
||||||
|
|||||||
@@ -1984,6 +1984,13 @@ body.cockpit-mode
|
|||||||
) {
|
) {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
/* The visor starts with flight instruments. Panels restores the optional
|
||||||
|
displays for this flight without changing the map's panel preferences. */
|
||||||
|
body.cockpit-mode:has(#cockpit-panels-toggle[aria-pressed='false'])
|
||||||
|
:is(#left-panel-stack, #intel-hud, #corner-actions, #global-loading-status,
|
||||||
|
#cockpit-utility-controls, #cockpit-context, #cockpit-signal-stream) {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
body.cockpit-mode #left-panel-stack {
|
body.cockpit-mode #left-panel-stack {
|
||||||
z-index: 147;
|
z-index: 147;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { computed } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
import { t } from '../../i18n/index.js';
|
import { t } from '../../i18n/index.js';
|
||||||
import {
|
import {
|
||||||
createInstrumentState,
|
createInstrumentState,
|
||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
} from '../cockpitInstrumentState.js';
|
} from '../cockpitInstrumentState.js';
|
||||||
import { vClassToggle } from '../rail/classToggle.js';
|
import { vClassToggle } from '../rail/classToggle.js';
|
||||||
import { useCockpitStore } from '../stores/cockpit.js';
|
import { useCockpitStore } from '../stores/cockpit.js';
|
||||||
|
import { useRadioStore } from '../stores/radio.js';
|
||||||
import { useGlobeActionsStore } from '../stores/globeActions.js';
|
import { useGlobeActionsStore } from '../stores/globeActions.js';
|
||||||
import CockpitBriefing from './panels/CockpitBriefing.vue';
|
import CockpitBriefing from './panels/CockpitBriefing.vue';
|
||||||
import CockpitContext from './panels/CockpitContext.vue';
|
import CockpitContext from './panels/CockpitContext.vue';
|
||||||
@@ -23,6 +24,12 @@ import CockpitUtilityControls from './panels/CockpitUtilityControls.vue';
|
|||||||
const { presence, instruments, route, vision, utilityLayout } =
|
const { presence, instruments, route, vision, utilityLayout } =
|
||||||
storeToRefs(useCockpitStore());
|
storeToRefs(useCockpitStore());
|
||||||
const active = computed(() => Boolean(presence.value?.active));
|
const active = computed(() => Boolean(presence.value?.active));
|
||||||
|
const panelsOpen = ref(false);
|
||||||
|
const radio = useRadioStore();
|
||||||
|
watch(active, () => { panelsOpen.value = false; });
|
||||||
|
watch(() => radio.utility?.display || radio.utility?.radio, (open) => {
|
||||||
|
if (active.value && open) panelsOpen.value = true;
|
||||||
|
});
|
||||||
const globe = useGlobeActionsStore();
|
const globe = useGlobeActionsStore();
|
||||||
const { resetBusy } = storeToRefs(globe);
|
const { resetBusy } = storeToRefs(globe);
|
||||||
const initialInstruments = createInstrumentState();
|
const initialInstruments = createInstrumentState();
|
||||||
@@ -200,6 +207,9 @@ const tickStyle = (tick) =>
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<nav id="view-switcher" :aria-label="t('View switcher')">
|
<nav id="view-switcher" :aria-label="t('View switcher')">
|
||||||
|
<button v-if="active" id="cockpit-panels-toggle" type="button" :aria-pressed="panelsOpen" @click="panelsOpen = !panelsOpen">
|
||||||
|
<span>{{ t('Panels') }}</span>
|
||||||
|
</button>
|
||||||
<button id="cockpit-reset-globe" type="button" :aria-label="resetBusy ? t('Resetting cockpit to full globe view') : t('Reset cockpit to full globe view')" :title="t('Exit cockpit and return to full globe view')" :hidden="!active" @click="globe.act('reset')">
|
<button id="cockpit-reset-globe" type="button" :aria-label="resetBusy ? t('Resetting cockpit to full globe view') : t('Reset cockpit to full globe view')" :title="t('Exit cockpit and return to full globe view')" :hidden="!active" @click="globe.act('reset')">
|
||||||
<span class="material-symbols-outlined" aria-hidden="true">public</span>
|
<span class="material-symbols-outlined" aria-hidden="true">public</span>
|
||||||
<span>{{ t('RESET') }}</span>
|
<span>{{ t('RESET') }}</span>
|
||||||
|
|||||||
Reference in new issue
Block a user