mirror of
https://github.com/OpenSquawk/OpenSquawk
synced 2026-08-04 08:06:26 +08:00
fix(websim): keep bridge connected in background tabs, fix PFD clipping and layout
- Move physics and telemetry/status ticking from requestAnimationFrame/setInterval to a Web Worker (new shared/utils/intervalWorker.ts) — the intended usage is WebSim in one tab and /live-atc in another, so the WebSim tab is almost always backgrounded, and rAF stops entirely / setInterval throttles to ~1/min in that state, dropping the bridge connection after a few minutes. - Surface bridge failures in the header badge (connecting/error/connected) instead of showing "verbindet…" forever when telemetry POSTs are failing. - Replace the PFD's hardcoded 0.85 scale with a ResizeObserver-driven fit so it no longer clips the VS tape/altitude readout at typical panel widths. - Give the sidestick pad the same panel shell as the FCU/radio panels and stretch all three to equal height. - ExteriorView: camera height now reacts to altitude, the runway renders at its real distance/lateral offset (was a fixed spot only shown under 3 NM) with centerline/threshold markings, widened for visibility from the 12 NM range it's now shown from, plus fog and a gradient sky. Verified live: bridge badge stays green, PFD fits inside its panel at 1280x720, and the runway becomes visible on approach for all four spawn presets.
This commit is contained in:
36
shared/utils/intervalWorker.ts
Normal file
36
shared/utils/intervalWorker.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
// A plain Worker's timers are not subject to the background-tab throttling
|
||||
// that setInterval/requestAnimationFrame get on the main thread (Chrome clamps
|
||||
// background-tab setInterval down to ~1/min after a few minutes; rAF stops
|
||||
// entirely) — used by anything in WebSim that must keep ticking while its tab
|
||||
// is backgrounded (the intended usage: WebSim in one tab, /live-atc in
|
||||
// another). docs/plans/2026-07-16-codex-fixes-live-atc-loop-websim.md WP2 Fix 1.
|
||||
export function createIntervalWorker(intervalMs: number, onTick: () => void): { stop: () => void } | null {
|
||||
if (typeof Worker === 'undefined') return null
|
||||
|
||||
const source = `
|
||||
let timer = null
|
||||
self.onmessage = (e) => {
|
||||
if (e.data === 'start') {
|
||||
timer = setInterval(() => self.postMessage('tick'), ${intervalMs})
|
||||
} else if (e.data === 'stop') {
|
||||
if (timer !== null) clearInterval(timer)
|
||||
self.close()
|
||||
}
|
||||
}
|
||||
`
|
||||
const blob = new Blob([source], { type: 'application/javascript' })
|
||||
const url = URL.createObjectURL(blob)
|
||||
const worker = new Worker(url)
|
||||
worker.onmessage = (e: MessageEvent) => {
|
||||
if (e.data === 'tick') onTick()
|
||||
}
|
||||
worker.postMessage('start')
|
||||
|
||||
return {
|
||||
stop: () => {
|
||||
worker.postMessage('stop')
|
||||
worker.terminate()
|
||||
URL.revokeObjectURL(url)
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user