Initial commit: X-Plane G1000 web cockpit + bridge + Tauri desktop app
- server/: Node bridge (datarefs/commands, navdata, CIFP procedures, flight plan) - web/: React cockpit (PFD/MFD/Map, VFR six-pack, AFCS, FMS CDU), PWA, collapsible sidebar - desktop/: Tauri 2 launcher (Bun sidecar, system tray, updater) + Linux build via Docker - scripts/: prep-desktop, build-linux, Gitea release + latest.json Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.4 KiB |
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "G1000 Glass Cockpit",
|
||||
"short_name": "G1000",
|
||||
"description": "X-Plane 12 G1000 glass cockpit — PFD / MFD / FMS over your LAN",
|
||||
"start_url": "/",
|
||||
"scope": "/",
|
||||
"display": "standalone",
|
||||
"orientation": "landscape",
|
||||
"background_color": "#000000",
|
||||
"theme_color": "#000000",
|
||||
"icons": [
|
||||
{ "src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png" },
|
||||
{ "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png" },
|
||||
{ "src": "/icons/icon-512-maskable.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" }
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Minimal service worker: caches the app shell so the cockpit launches fast and
|
||||
// survives brief network blips. Live data (the bridge WebSocket, /api, and map
|
||||
// tiles) is never cached — only same-origin GET app assets.
|
||||
const CACHE = 'g1000-shell-v1';
|
||||
|
||||
self.addEventListener('install', () => self.skipWaiting());
|
||||
|
||||
self.addEventListener('activate', (e) => {
|
||||
e.waitUntil(
|
||||
caches.keys().then((keys) => Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k))))
|
||||
.then(() => self.clients.claim())
|
||||
);
|
||||
});
|
||||
|
||||
self.addEventListener('fetch', (e) => {
|
||||
const url = new URL(e.request.url);
|
||||
// Only same-origin GET app shell; skip the API and let the WS pass through.
|
||||
if (e.request.method !== 'GET' || url.origin !== location.origin) return;
|
||||
if (url.pathname.startsWith('/api') || url.pathname === '/ws') return;
|
||||
|
||||
// Stale-while-revalidate: serve cache fast, refresh in the background.
|
||||
e.respondWith(
|
||||
caches.open(CACHE).then(async (cache) => {
|
||||
const cached = await cache.match(e.request);
|
||||
const network = fetch(e.request)
|
||||
.then((res) => { if (res && res.ok) cache.put(e.request, res.clone()); return res; })
|
||||
.catch(() => cached);
|
||||
return cached || network;
|
||||
})
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user