Release v2.10.3
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile, web, pulse-signage-web) (push) Successful in 1m13s
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile.player, player, pulse-signage-player) (push) Successful in 31s

This commit is contained in:
2026-08-29 01:56:45 +01:00
parent 30814f3f46
commit 3f4f57020a
60 changed files with 1075 additions and 523 deletions
+33 -5
View File
@@ -1,3 +1,5 @@
// Player application bootstrap, media routes, websocket runtime, and onboarding wiring.
const express = require('express');
const fs = require('fs');
const http = require('http');
@@ -10,8 +12,10 @@ const { createRtmpStreamService } = require('./player/modules/rtmp-streams');
const { normalizeDeviceId, registerPlayerOnboardingRoutes, commitDeviceBinding } = require('./player/onboarding');
const { createOnboardingStore } = require('./player/onboarding/store');
const { registerPlayerRoutes } = require('./player/routes');
const { getPlayerRuntimeScripts } = require('./player/render-helpers');
const { ensureFontLibrary } = require('#src/web/lib/media/font-library');
const { createRequestAuthHeaders } = require('#src/request-auth');
const { withClientNameReservation } = require('#src/data/client-name-check');
const { getConfiguredPlayerIdentifier, recordPlayerHeartbeat } = require('#src/data/player-registry');
@@ -52,11 +56,28 @@ async function start() {
thinClientSocket.send(JSON.stringify({
type: 'snapshot',
deviceId: PLAYER_DEVICE_ID,
playerPublicBaseUrl: getPlayerPublicBaseUrl(),
slug: snapshot && snapshot.slug ? String(snapshot.slug).trim() : '',
connections: Array.isArray(snapshot && snapshot.connections) ? snapshot.connections : []
}));
} catch (_error) {
}
},
persistClientName: async function (deviceId, clientName) {
if (!pool || !deviceId || !clientName) {
return;
}
await withClientNameReservation(pool, clientName, async function () {
await pool.query(
`UPDATE d_onboarding_devices
SET client_name = ?, modified_at = CURRENT_TIMESTAMP
WHERE device_id = ?`,
[clientName, deviceId]
);
});
},
touchClientLastSeen: async function (deviceId) {
await common.touchOnboardingDeviceLastSeen(pool, deviceId);
}
});
const playerPlaylistService = isRemotePlayer
@@ -320,6 +341,14 @@ async function start() {
}
}
});
app.get('/assets/player-script/:name.js', function (req, res) {
const script = getPlayerRuntimeScripts().find(function (entry) { return entry[0] === req.params.name; });
if (!script) {
return res.sendStatus(404);
}
res.set('Cache-Control', 'no-cache');
return res.type('application/javascript').send(script[1]);
});
registerPlayerRoutes(app, {
pool: pool,
common: common,
@@ -328,6 +357,7 @@ async function start() {
playerRuntime: playerRuntime,
playerPlaylistService: playerPlaylistService,
rtmpStreamService: rtmpStreamService,
snapshotDir: path.join(MEDIA_DIR, 'player-cache', 'screen-playlists'),
playerInternalBaseUrl: PLAYER_INTERNAL_URL,
bridgeBaseUrl: BRIDGE_PUBLIC_URL,
playerDeviceId: PLAYER_DEVICE_ID,
@@ -391,7 +421,8 @@ async function start() {
internalBaseUrl: PLAYER_INTERNAL_URL,
pairingCode: activePairingCode,
pairingCodes: activePairingCodes,
pairingSessions: activePairingSessions
pairingSessions: activePairingSessions,
connections: playerRuntime.snapshotAllConnections()
}));
}
@@ -439,6 +470,7 @@ async function start() {
socket.send(JSON.stringify({
type: 'snapshot',
deviceId: PLAYER_DEVICE_ID,
playerPublicBaseUrl: getPlayerPublicBaseUrl(),
slug: String(slug || '').trim(),
connections: playerRuntime.snapshotConnections(slug)
}));
@@ -565,10 +597,6 @@ async function start() {
console.error(error);
});
if (playerRuntime.snapshotAllConnections().length > 0) {
await common.pruneStaleOnboardingDevices(pool);
}
await onboardingStore.flushBindings(function (entry) {
return commitDeviceBinding(
pool,