mirror of
https://github.com/OpenSquawk/OpenSquawk
synced 2026-08-01 22:26:04 +08:00
- 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.
37 lines
1.3 KiB
TypeScript
37 lines
1.3 KiB
TypeScript
// 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)
|
|
},
|
|
}
|
|
}
|