Fix player cached images and blank time dates
This commit is contained in:
@@ -8,6 +8,8 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
- Fixed the template background image media picker Upload media button so it opens the file selector.
|
||||
- Fixed the template designer empty background message moving when the background image is removed.
|
||||
- Fixed cached API and RSS images not being served by the player after being downloaded.
|
||||
- Fixed blank time/date regions displaying the default clock format on the player.
|
||||
|
||||
## 2.13.2 - 2026-09-11
|
||||
|
||||
|
||||
@@ -489,10 +489,6 @@ function createLocalControlService(options) {
|
||||
}
|
||||
}
|
||||
|
||||
app.use('/media/player-cache', function (_req, res) {
|
||||
return res.sendStatus(404);
|
||||
});
|
||||
|
||||
app.get('/local-control', function (req, res) {
|
||||
res.set('Cache-Control', 'no-store');
|
||||
res.type('html').send(renderPageV2());
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
var registry = window.pulsePlayerRegionTypes;
|
||||
var placeholderUtils = window.placeholderUtils || {};
|
||||
var DEFAULT_FORMAT = '{{hh}}:{{mm}}';
|
||||
var DEFAULT_STYLE = {
|
||||
font_family: 'Arial',
|
||||
font_size: 32,
|
||||
@@ -223,7 +222,7 @@ function resolveTimeDateTemplatePlaceholder(values, expression) {
|
||||
}
|
||||
|
||||
function renderTimeDateTemplate(format, timeZone, date) {
|
||||
var template = String(format || '').trim() || DEFAULT_FORMAT;
|
||||
var template = String(format || '').trim();
|
||||
var values = getTimeDateFormattedParts(timeZone, date);
|
||||
return template.replace(/\{\{\s*([a-zA-Z0-9_.()\-]+)\s*\}\}/g, function (_match, key) {
|
||||
return String(resolveTimeDateTemplatePlaceholder(values, key, { timeZone: timeZone }) || '');
|
||||
@@ -243,7 +242,7 @@ function getTextStyle(regionContent, region) {
|
||||
|
||||
function renderTimeDateRegion(region, regionContent) {
|
||||
var content = regionContent && typeof regionContent === 'object' ? regionContent : {};
|
||||
var format = String(content.value !== undefined ? content.value : content.text || '').trim() || DEFAULT_FORMAT;
|
||||
var format = String(content.value !== undefined ? content.value : content.text || '').trim();
|
||||
var timeZone = resolveTimeZone(content.timezone || content.time_zone || '');
|
||||
var style = getTextStyle(content, region);
|
||||
var fontFamily = style.font_family ? 'font-family:' + escapeHtml(style.font_family) + ';' : '';
|
||||
@@ -259,7 +258,7 @@ function updateTimeDateRegion(element) {
|
||||
return;
|
||||
}
|
||||
|
||||
var format = String(element.dataset.timeDateFormat || '').trim() || DEFAULT_FORMAT;
|
||||
var format = String(element.dataset.timeDateFormat || '').trim();
|
||||
var timeZone = String(element.dataset.timeDateTimezone || '').trim();
|
||||
var scaleWrapper = element.querySelector('.template-region-text-scale');
|
||||
if (!scaleWrapper) {
|
||||
|
||||
@@ -31,6 +31,25 @@ async function createTestService(options) {
|
||||
return { app, server, service, temporaryDirectory };
|
||||
}
|
||||
|
||||
test('local control leaves cached player media available to the static media route', async () => {
|
||||
const { app, server, temporaryDirectory } = await createTestService();
|
||||
const cachedImagePath = path.join(temporaryDirectory, 'player-cache', 'remote-images', 'cached-image.png');
|
||||
await fs.promises.mkdir(path.dirname(cachedImagePath), { recursive: true });
|
||||
await fs.promises.writeFile(cachedImagePath, 'cached-image');
|
||||
app.use('/media', express.static(temporaryDirectory));
|
||||
const listener = app.listen(0);
|
||||
try {
|
||||
const address = listener.address();
|
||||
const response = await fetch(`http://127.0.0.1:${address.port}/media/player-cache/remote-images/cached-image.png`);
|
||||
assert.equal(response.status, 200);
|
||||
assert.equal(await response.text(), 'cached-image');
|
||||
} finally {
|
||||
await new Promise((resolve) => listener.close(resolve));
|
||||
server.close();
|
||||
await fs.promises.rm(temporaryDirectory, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test('local control authenticates only cached eligible users and scopes commands to local runtime', async () => {
|
||||
const { app, service, temporaryDirectory } = await createTestService();
|
||||
const password = hashPassword('CorrectHorseBatteryStaple!');
|
||||
|
||||
@@ -63,3 +63,22 @@ test('time/date region renders placeholder tokens on the player side', () => {
|
||||
|
||||
assert.match(markup, /<p>\d{2}:\d{2}<\/p>/);
|
||||
});
|
||||
|
||||
test('time/date region stays blank when its format is blank', () => {
|
||||
const module = loadTimeDateModule();
|
||||
const markup = module.renderRegion(
|
||||
{
|
||||
pixelWidth: 320,
|
||||
pixelHeight: 180,
|
||||
canvasScale: 1,
|
||||
baseStyle: 'position:absolute;'
|
||||
},
|
||||
{
|
||||
value: '',
|
||||
timezone: 'UTC'
|
||||
}
|
||||
);
|
||||
|
||||
assert.match(markup, /data-time-date-format=""/);
|
||||
assert.doesNotMatch(markup, /<p>\d{2}:\d{2}<\/p>/);
|
||||
});
|
||||
Reference in New Issue
Block a user