From 4dbd0bda9f36cbef70ce0a02dc1c84abc22c3cf0 Mon Sep 17 00:00:00 2001 From: itsrubberduck Date: Sun, 26 Jul 2026 20:12:34 +0200 Subject: [PATCH] fix(live-atc): keep the callsign visible on narrow screens MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The cockpit HUD is already a sticky top bar carrying the callsign, but a media query hid the whole flight-context group below 720px — so on a phone the pilot had no way to see their own callsign without opening the flight sheet. Shrink the group there instead of hiding it. Verified at 320/375/1280px: the callsign stays in the sticky bar while the body scrolls, and the HUD row still fits without horizontal overflow (318px of 318 at the 320px width). Also fills two gaps the mock dev harness had after the ATIS work: it now stubs /api/airports/:icao/atis, and its STT fallback no longer transcribes to "say again", which the backend now intercepts as a request to repeat. Co-Authored-By: Claude Opus 5 --- .../live-atc/cockpit/CockpitShell.vue | 14 +++++++++- app/plugins/mock-live-atc.client.ts | 27 ++++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/app/components/live-atc/cockpit/CockpitShell.vue b/app/components/live-atc/cockpit/CockpitShell.vue index 430c112..5b6114c 100644 --- a/app/components/live-atc/cockpit/CockpitShell.vue +++ b/app/components/live-atc/cockpit/CockpitShell.vue @@ -910,8 +910,20 @@ onMounted(() => { } } @media (max-width: 720px) { + /* The callsign stays put at every width — the pilot needs it on every + transmission, and the HUD is the one element that is always on screen. + Shrink it here rather than hiding the group. */ .hud-context-group { - display: none; + margin-left: 0; + flex: 0 1 auto; + min-width: 0; + } + .hud-context-btn { + min-width: 0; + padding: 4px 8px; + } + .hud-context-callsign { + max-width: 104px; } } @media (max-width: 860px) { diff --git a/app/plugins/mock-live-atc.client.ts b/app/plugins/mock-live-atc.client.ts index d4a4329..626665c 100644 --- a/app/plugins/mock-live-atc.client.ts +++ b/app/plugins/mock-live-atc.client.ts @@ -44,6 +44,28 @@ export default defineNuxtPlugin(() => { const METAR = 'EDDF 101950Z 25008KT 9999 FEW040 18/12 Q1013 NOSIG' + // Matches FREQS above: one ATIS station on 118.025 broadcasting information K. + const ATIS = { + icao: 'EDDF', + source: 'vatsim', + letter: 'K', + letterDep: 'K', + letterArr: 'K', + runwayDep: '25C', + runwayArr: '25L', + runwaySource: 'atis', + qnhHpa: 1013, + surfaceWind: '250/08', + observedAt: null, + stations: [{ + frequency: '118.025', + callsign: 'EDDF_ATIS', + variant: null, + letter: 'K', + text: 'FRANKFURT INFORMATION K, DEP RWY 25C, EXPECT ILS APPROACH RUNWAY 25L, QNH 1013', + }], + } + const json = (data: unknown) => data // Return a canned response for a mocked Nuxt path, or the sentinel MISS. @@ -56,6 +78,7 @@ export default defineNuxtPlugin(() => { if (path === '/api/auth/login') return json({ accessToken: 'mock-token', user: MOCK_USER }) if (/^\/api\/airports\/[^/]+\/frequencies$/.test(path)) return json(FREQS) + if (/^\/api\/airports\/[^/]+\/atis$/.test(path)) return json(ATIS) if (path === '/api/vatsim/metar') return METAR if (path === '/api/vatsim/flightplans') return json({ flightplans: [] }) @@ -67,7 +90,9 @@ export default defineNuxtPlugin(() => { // a PTT press behaves as a correct readback against the real backend. if (path === '/api/atc/ptt') { const expected = opts?.body?.expected - const transcription = (Array.isArray(expected) ? expected[0] : expected) || 'say again' + // The fallback must not be standard phraseology: "say again" is + // intercepted by the backend and repeats the transmission instead. + const transcription = (Array.isArray(expected) ? expected[0] : expected) || 'unreadable' return json({ success: true, transcription }) }