Release 2.6.13
This commit is contained in:
@@ -2,6 +2,14 @@
|
|||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
## 2.6.13 - 2026-08-08
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- The player bundle now keeps the browser-only QR export dependencies lazy-loaded, so the remote player image no longer needs `puppeteer-core` or `@sparticuz/chromium` at startup.
|
||||||
|
- Remote player startup sync now falls back to `WEB_INTERNAL_URL` when it is configured, which avoids 404s when the bridge is not the correct sync target.
|
||||||
|
- The player startup sync and media-write info logs were removed to keep normal remote-player operation quieter.
|
||||||
|
|
||||||
## 2.6.12 - 2026-08-08
|
## 2.6.12 - 2026-08-08
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pulse-signage-player",
|
"name": "pulse-signage-player",
|
||||||
"version": "2.6.12",
|
"version": "2.6.13",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "Pulse Signage player application bundle",
|
"description": "Pulse Signage player application bundle",
|
||||||
"main": "src/common.js",
|
"main": "src/common.js",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pulse-signage-web",
|
"name": "pulse-signage-web",
|
||||||
"version": "2.6.12",
|
"version": "2.6.13",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "Pulse Signage web and bridge application bundle",
|
"description": "Pulse Signage web and bridge application bundle",
|
||||||
"main": "src/common.js",
|
"main": "src/common.js",
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "pulse-signage",
|
"name": "pulse-signage",
|
||||||
"version": "2.5.9",
|
"version": "2.6.13",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "pulse-signage",
|
"name": "pulse-signage",
|
||||||
"version": "2.5.9",
|
"version": "2.6.13",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sparticuz/chromium": "^137.0.0",
|
"@sparticuz/chromium": "^137.0.0",
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pulse-signage",
|
"name": "pulse-signage",
|
||||||
"version": "2.6.12",
|
"version": "2.6.13",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "Pulse Signage application with MySQL and media storage",
|
"description": "Pulse Signage application with MySQL and media storage",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
+7
-7
@@ -1,8 +1,6 @@
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const QRCodeStyling = require(path.join(__dirname, '..', 'web', 'public', 'vendor', 'qr-code-styling', 'qr-code-styling.js'));
|
const QRCodeStyling = require(path.join(__dirname, '..', 'web', 'public', 'vendor', 'qr-code-styling', 'qr-code-styling.js'));
|
||||||
const puppeteer = require('puppeteer-core');
|
|
||||||
const chromiumModule = require('@sparticuz/chromium');
|
|
||||||
const QR_PNG_WIDTH = 2048;
|
const QR_PNG_WIDTH = 2048;
|
||||||
const QR_STYLING_SCRIPT_PATH = path.join(__dirname, '..', 'web', 'public', 'vendor', 'qr-code-styling', 'qr-code-styling.js');
|
const QR_STYLING_SCRIPT_PATH = path.join(__dirname, '..', 'web', 'public', 'vendor', 'qr-code-styling', 'qr-code-styling.js');
|
||||||
const SYSTEM_CHROMIUM_PATHS = [
|
const SYSTEM_CHROMIUM_PATHS = [
|
||||||
@@ -13,11 +11,6 @@ const SYSTEM_CHROMIUM_PATHS = [
|
|||||||
'/usr/local/bin/chromium',
|
'/usr/local/bin/chromium',
|
||||||
'/snap/bin/chromium'
|
'/snap/bin/chromium'
|
||||||
].filter(Boolean);
|
].filter(Boolean);
|
||||||
const chromium = chromiumModule && typeof chromiumModule.executablePath === 'function'
|
|
||||||
? chromiumModule
|
|
||||||
: chromiumModule && chromiumModule.default && typeof chromiumModule.default.executablePath === 'function'
|
|
||||||
? chromiumModule.default
|
|
||||||
: chromiumModule;
|
|
||||||
let qrBrowserPromise = null;
|
let qrBrowserPromise = null;
|
||||||
|
|
||||||
function escapeXml(value) {
|
function escapeXml(value) {
|
||||||
@@ -353,6 +346,13 @@ function getQrBrowser() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
qrBrowserPromise = (async function () {
|
qrBrowserPromise = (async function () {
|
||||||
|
const puppeteer = require('puppeteer-core');
|
||||||
|
const chromiumModule = require('@sparticuz/chromium');
|
||||||
|
const chromium = chromiumModule && typeof chromiumModule.executablePath === 'function'
|
||||||
|
? chromiumModule
|
||||||
|
: chromiumModule && chromiumModule.default && typeof chromiumModule.default.executablePath === 'function'
|
||||||
|
? chromiumModule.default
|
||||||
|
: chromiumModule;
|
||||||
let executablePath = SYSTEM_CHROMIUM_PATHS.find(function (candidate) {
|
let executablePath = SYSTEM_CHROMIUM_PATHS.find(function (candidate) {
|
||||||
return fs.existsSync(candidate);
|
return fs.existsSync(candidate);
|
||||||
}) || '';
|
}) || '';
|
||||||
|
|||||||
+7
-31
@@ -22,6 +22,7 @@ async function start() {
|
|||||||
const PORT = Number(process.env.PLAYER_PORT || 8081);
|
const PORT = Number(process.env.PLAYER_PORT || 8081);
|
||||||
const PLAYER_PUBLIC_URL = String(process.env.PLAYER_PUBLIC_URL || process.env.PLAYER_BASE_URL || '').trim().replace(/\/$/, '');
|
const PLAYER_PUBLIC_URL = String(process.env.PLAYER_PUBLIC_URL || process.env.PLAYER_BASE_URL || '').trim().replace(/\/$/, '');
|
||||||
const BRIDGE_PUBLIC_URL = String(process.env.BRIDGE_PUBLIC_URL || '').trim().replace(/\/$/, '');
|
const BRIDGE_PUBLIC_URL = String(process.env.BRIDGE_PUBLIC_URL || '').trim().replace(/\/$/, '');
|
||||||
|
const WEB_INTERNAL_URL = String(process.env.WEB_INTERNAL_URL || '').trim().replace(/\/$/, '');
|
||||||
const isRemotePlayer = Boolean(BRIDGE_PUBLIC_URL);
|
const isRemotePlayer = Boolean(BRIDGE_PUBLIC_URL);
|
||||||
const PLAYER_INTERNAL_URL = String(isRemotePlayer ? BRIDGE_PUBLIC_URL : (process.env.PLAYER_INTERNAL_URL || PLAYER_PUBLIC_URL || process.env.PLAYER_BASE_URL || '')).trim().replace(/\/$/, '');
|
const PLAYER_INTERNAL_URL = String(isRemotePlayer ? BRIDGE_PUBLIC_URL : (process.env.PLAYER_INTERNAL_URL || PLAYER_PUBLIC_URL || process.env.PLAYER_BASE_URL || '')).trim().replace(/\/$/, '');
|
||||||
const PLAYER_DEVICE_ID = getConfiguredPlayerIdentifier();
|
const PLAYER_DEVICE_ID = getConfiguredPlayerIdentifier();
|
||||||
@@ -133,7 +134,8 @@ async function start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function triggerWebMediaSync() {
|
async function triggerWebMediaSync() {
|
||||||
if (!isRemotePlayer || !BRIDGE_PUBLIC_URL) {
|
const syncBaseUrl = WEB_INTERNAL_URL || BRIDGE_PUBLIC_URL;
|
||||||
|
if (!isRemotePlayer || !syncBaseUrl) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,16 +146,12 @@ async function start() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.info('[player] Triggering startup media sync', {
|
|
||||||
playerIdentifier: PLAYER_DEVICE_ID,
|
|
||||||
bridgeBaseUrl: BRIDGE_PUBLIC_URL
|
|
||||||
});
|
|
||||||
const authHeaders = createRequestAuthHeaders({
|
const authHeaders = createRequestAuthHeaders({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
pathname: '/api/internal/sync/player-media',
|
pathname: '/api/internal/sync/player-media',
|
||||||
body: requestBody
|
body: requestBody
|
||||||
});
|
});
|
||||||
const response = await fetch(`${BRIDGE_PUBLIC_URL}/api/internal/sync/player-media`, {
|
const response = await fetch(`${syncBaseUrl}/api/internal/sync/player-media`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: Object.assign({
|
headers: Object.assign({
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
@@ -162,11 +160,6 @@ async function start() {
|
|||||||
body: JSON.stringify(requestBody)
|
body: JSON.stringify(requestBody)
|
||||||
});
|
});
|
||||||
|
|
||||||
console.info('[player] Startup media sync response', {
|
|
||||||
ok: Boolean(response && response.ok),
|
|
||||||
status: response && response.status ? response.status : null
|
|
||||||
});
|
|
||||||
|
|
||||||
return Boolean(response && response.ok);
|
return Boolean(response && response.ok);
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
console.warn('[player] Startup media sync failed');
|
console.warn('[player] Startup media sync failed');
|
||||||
@@ -175,7 +168,8 @@ async function start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function triggerWebFontSync() {
|
async function triggerWebFontSync() {
|
||||||
if (!isRemotePlayer || !BRIDGE_PUBLIC_URL) {
|
const syncBaseUrl = WEB_INTERNAL_URL || BRIDGE_PUBLIC_URL;
|
||||||
|
if (!isRemotePlayer || !syncBaseUrl) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,16 +180,12 @@ async function start() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.info('[player] Triggering startup font sync', {
|
|
||||||
playerIdentifier: PLAYER_DEVICE_ID,
|
|
||||||
bridgeBaseUrl: BRIDGE_PUBLIC_URL
|
|
||||||
});
|
|
||||||
const authHeaders = createRequestAuthHeaders({
|
const authHeaders = createRequestAuthHeaders({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
pathname: '/api/internal/sync/player-font',
|
pathname: '/api/internal/sync/player-font',
|
||||||
body: requestBody
|
body: requestBody
|
||||||
});
|
});
|
||||||
const response = await fetch(`${BRIDGE_PUBLIC_URL}/api/internal/sync/player-font`, {
|
const response = await fetch(`${syncBaseUrl}/api/internal/sync/player-font`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: Object.assign({
|
headers: Object.assign({
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
@@ -204,11 +194,6 @@ async function start() {
|
|||||||
body: JSON.stringify(requestBody)
|
body: JSON.stringify(requestBody)
|
||||||
});
|
});
|
||||||
|
|
||||||
console.info('[player] Startup font sync response', {
|
|
||||||
ok: Boolean(response && response.ok),
|
|
||||||
status: response && response.status ? response.status : null
|
|
||||||
});
|
|
||||||
|
|
||||||
return Boolean(response && response.ok);
|
return Boolean(response && response.ok);
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
console.warn('[player] Startup font sync failed');
|
console.warn('[player] Startup font sync failed');
|
||||||
@@ -257,18 +242,9 @@ async function start() {
|
|||||||
response.error = 'Invalid media payload.';
|
response.error = 'Invalid media payload.';
|
||||||
} else {
|
} else {
|
||||||
const bodyBuffer = Buffer.from(bodyBase64, 'base64');
|
const bodyBuffer = Buffer.from(bodyBase64, 'base64');
|
||||||
console.info('[player] Writing media file', {
|
|
||||||
relativePath: relativePath,
|
|
||||||
filePath: filePath,
|
|
||||||
bytes: bodyBuffer.length
|
|
||||||
});
|
|
||||||
await fs.promises.mkdir(path.dirname(filePath), { recursive: true });
|
await fs.promises.mkdir(path.dirname(filePath), { recursive: true });
|
||||||
await fs.promises.writeFile(filePath, bodyBuffer);
|
await fs.promises.writeFile(filePath, bodyBuffer);
|
||||||
response.ok = true;
|
response.ok = true;
|
||||||
console.info('[player] Media file written', {
|
|
||||||
relativePath: relativePath,
|
|
||||||
filePath: filePath
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} else if (command === 'media-delete') {
|
} else if (command === 'media-delete') {
|
||||||
const relativePath = String(payload.relativePath || payload.filename || '').trim();
|
const relativePath = String(payload.relativePath || payload.filename || '').trim();
|
||||||
|
|||||||
Reference in New Issue
Block a user