feat(timeout): proietta spot video sul display durante il time out

Aggiunge il flag `timeout` nello stato e l'action `toggleTimeout`: dal
controller il pulsante Time Out commuta la modalità e il display copre il
tabellone con i video .mp4 della cartella `spot/` (non versionata).

- un solo video → loop; più video → sequenza alfabetica con ritorno al primo;
  cartella vuota/assente → overlay "TIME OUT".
- `src/spot-utils.js` (listSpotVideos) elenca i .mp4; endpoint `/spot/list`
  + file statici `/spot/<file>.mp4` serviti sia in prod (server.js) sia in
  dev (vite-plugin-websocket.js).
- il display avvia i video con audio e ripiega su muto se il browser blocca
  l'autoplay con suono.
- il controller resta operativo ma evidenzia la modalità con banner e
  pulsante arancione pulsante, in entrambi i layout (mobile ed esteso).
This commit is contained in:
2026-06-21 18:35:08 +02:00
parent ffba5b368d
commit fb4b14b282
7 changed files with 160 additions and 1 deletions
+9 -1
View File
@@ -6,19 +6,27 @@ import { dirname, join } from 'path'
import { setupWebSocketHandler } from './src/websocket-handler.js'
import { printServerInfo } from './src/server-utils.js'
import { loadState, saveState } from './src/persist.js'
import { listSpotVideos } from './src/spot-utils.js'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
const DIST_DIR = join(__dirname, 'dist')
const SPOT_DIR = join(__dirname, 'spot')
// Crea l'app Express (asset statici + route display/controller) senza avviare il
// listen né il WebSocket: così il routing è testabile in isolamento.
export function createApp(distDir = DIST_DIR) {
export function createApp(distDir = DIST_DIR, spotDir = SPOT_DIR) {
const app = express()
app.use(express.static(distDir, { index: false }))
// Video spot del time out: elenco JSON + file statici (range requests gestiti
// da express.static, così il seeking dei video funziona). La route /spot/list
// va prima dello static per non collidere con un eventuale file "list".
app.get('/spot/list', (_req, res) => res.json(listSpotVideos(spotDir)))
app.use('/spot', express.static(spotDir))
app.get(['/', '/display', '/display/*splat'], (_req, res) => {
res.sendFile(join(distDir, 'index.html'))
})