New separate project (the Electron Mac app stays untouched). Reuses the visual engine (WebGL shaders, effect catalog, Web Audio) verbatim and replaces Electron IPC with a Node HTTP+WebSocket server: - server.js: serves the kiosk output page + mobile control PWA, relays the same ctl/rpt JSON protocol over WebSocket, plus REST for media library/upload, JSON state (pads), waveform peaks and MP4 recording (ffmpeg). - public/js/net.js: window.djv shim over WebSocket+HTTP so output.js runs intact. - public/index.html + control.js: touch-first mobile remote (effects, media/queue, ticker, pads, audio/EQ, fullscreen + recording). - PWA (manifest + service worker + generated icons). - scripts/: Chromium kiosk launcher + install-pi.sh (systemd units for Pi 5). Verified: REST endpoints, WebSocket relay both directions, control PWA loads the 2958-effect catalog and renders. (Headless WebGL output not testable without GPU.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
20 lines
1015 B
JavaScript
20 lines
1015 B
JavaScript
// Minimal app-shell cache so the remote installs as a PWA and the UI loads fast.
|
|
// API, media and websockets are always fetched from the network (never cached).
|
|
const CACHE = 'djv-shell-v1';
|
|
const SHELL = [
|
|
'./', 'index.html', 'css/mobile.css',
|
|
'js/net.js', 'js/control.js', 'js/engine/shaders.js', 'js/engine/effects.js',
|
|
'manifest.webmanifest', 'icons/icon-192.png', 'icons/icon-512.png'
|
|
];
|
|
self.addEventListener('install', (e) => {
|
|
e.waitUntil(caches.open(CACHE).then((c) => c.addAll(SHELL)).then(() => self.skipWaiting()));
|
|
});
|
|
self.addEventListener('activate', (e) => {
|
|
e.waitUntil(caches.keys().then((ks) => Promise.all(ks.filter((k) => k !== CACHE).map((k) => caches.delete(k)))).then(() => self.clients.claim()));
|
|
});
|
|
self.addEventListener('fetch', (e) => {
|
|
const url = new URL(e.request.url);
|
|
if (e.request.method !== 'GET' || url.pathname.startsWith('/api') || url.pathname.startsWith('/media')) return;
|
|
e.respondWith(caches.match(e.request).then((hit) => hit || fetch(e.request)));
|
|
});
|