diff --git a/src/player/public/css/player.css b/src/player/public/css/player.css index 4fe8725..7daf5e4 100644 --- a/src/player/public/css/player.css +++ b/src/player/public/css/player.css @@ -395,18 +395,6 @@ body.screen-blackout #app { white-space: pre-wrap; } -.template-region.text > *, -.template-region.api > *, -.template-region.rss > * { - margin: 0; -} - -.template-region.text > * + *, -.template-region.api > * + *, -.template-region.rss > * + * { - margin-top: 0.5em; -} - .template-region.text ul, .template-region.text ol, .template-region.api ul, diff --git a/src/player/public/js/player-page-commands.js b/src/player/public/js/player-page-commands.js index 6eae6b1..07c8899 100644 --- a/src/player/public/js/player-page-commands.js +++ b/src/player/public/js/player-page-commands.js @@ -133,7 +133,7 @@ function scheduleSlideAdvance(delayMs) { applyPendingPlaylistUpdate(); const activeSlides = getCurrentActiveSlides(); if (activeSlides.length < 2) { - refresh(); + showCurrent(); return; } if (index >= activeSlides.length) { diff --git a/src/player/public/js/player-page-playback.js b/src/player/public/js/player-page-playback.js index cd1753f..f689396 100644 --- a/src/player/public/js/player-page-playback.js +++ b/src/player/public/js/player-page-playback.js @@ -99,6 +99,16 @@ function showCurrent() { lastRenderedViewKey = getCurrentRenderKey(activeSlides); } +function isSlideInList(slide, slideList) { + if (!slide || !Array.isArray(slideList)) { + return false; + } + + return slideList.some(function (item) { + return item && Number(item.id) === Number(slide.id); + }); +} + // Skip the current slide when an RTMP feed is unavailable and the playlist asks for it. function handleRtmpPlaybackFailure(message, options) { if (!currentPlaylistSkipUnavailableRtmp) { @@ -165,6 +175,7 @@ function refresh() { const data = JSON.parse(request.responseText || '{}'); const nextSignature = getPlaylistRevision(data); const nextSlides = Array.isArray(data.slides) ? data.slides.map(normalizeSlide) : []; + const nextActiveSlides = getActiveSlidesFrom(nextSlides); const nextFadeBetweenSlides = Boolean(data && data.playlist && data.playlist.fade_between_slides); const nextSkipUnavailableRtmp = Boolean(data && data.playlist && data.playlist.skip_unavailable_rtmp); savePlaylistSnapshot({ @@ -196,17 +207,22 @@ function refresh() { } return; } - syncWebpagePreloads(getActiveSlidesFrom(nextSlides), index); + syncWebpagePreloads(nextActiveSlides, index); if (typeof syncRtmpWarmups === 'function') { - syncRtmpWarmups(getActiveSlidesFrom(nextSlides), index); + syncRtmpWarmups(nextActiveSlides, index); } - if (currentActiveSlides.length < 2) { + if (nextActiveSlides.length < 2) { pendingPlaylistUpdate = { slides: nextSlides, signature: nextSignature, fadeBetweenSlides: nextFadeBetweenSlides, skipUnavailableRtmp: nextSkipUnavailableRtmp }; + if (!isSlideInList(lastRenderedSlide, nextSlides)) { + applyPendingPlaylistUpdate(); + showCurrent(); + return; + } logDebug('Playlist update detected; applying on next slide transition.'); return; } diff --git a/src/player/public/sw.js b/src/player/public/sw.js index 459c841..95a7f5c 100644 --- a/src/player/public/sw.js +++ b/src/player/public/sw.js @@ -61,7 +61,7 @@ async function networkFirst(request, cacheName, cacheKeyRequest) { if (cached) { return cached; } - throw _error; + return new Response('', { status: 504, statusText: 'Offline' }); } } diff --git a/src/web/public/css/theme-custom.css b/src/web/public/css/theme-custom.css index 5294ce8..4f3984e 100644 --- a/src/web/public/css/theme-custom.css +++ b/src/web/public/css/theme-custom.css @@ -1448,6 +1448,31 @@ html[data-bs-theme='dark'] .template-field-card .tox .tox-collection { box-sizing: border-box; } +.slide-preview-text-content { + line-height: 1.5; +} + +.slide-preview-text-content > * { + margin: 1em 0; +} + +.slide-preview-text-content > *:first-child { + margin-top: 0; +} + +.slide-preview-text-content > *:last-child { + margin-bottom: 1em; +} + +.slide-preview-text-content ul, +.slide-preview-text-content ol { + padding-left: 1.2em; +} + +.slide-preview-text-content code { + white-space: pre-wrap; +} + .slide-preview-image { width: 100%; height: 100%; diff --git a/src/web/public/js/regions/type/text.js b/src/web/public/js/regions/type/text.js index 9789a70..320da26 100644 --- a/src/web/public/js/regions/type/text.js +++ b/src/web/public/js/regions/type/text.js @@ -38,7 +38,7 @@ var fontSize = style && style.font_size ? 'font-size:' + Math.max(1, Math.round(Number(style.font_size))) + 'px;' : ''; var width = Math.max(1, Math.round(Number(region && region.width ? region.width : 0) || 1)); var height = Math.max(1, Math.round(Number(region && region.height ? region.height : 0) || 1)); - var wrapperStyle = 'width:' + width + 'px;height:' + height + 'px;overflow:hidden;' + fontFamily + fontSize + color; + var wrapperStyle = 'width:' + width + 'px;height:' + height + 'px;overflow:hidden;line-height:1.5;' + fontFamily + fontSize + color; return '
' + sanitizePreviewHtml(raw) + '
'; } diff --git a/src/web/routes/admin/playlists.js b/src/web/routes/admin/playlists.js index a541dac..714e242 100644 --- a/src/web/routes/admin/playlists.js +++ b/src/web/routes/admin/playlists.js @@ -295,7 +295,7 @@ module.exports = function registerPlaylistRoutes(app, deps) { }; await savePlaylistItems(connection, playlist, req.body, actorId, { updatePlaylist: false }); await connection.commit(); - redirectAfterSave(req, res, '/playlists?edit=' + result.insertId, { + redirectAfterSave(req, res, '/playlists/' + result.insertId + '/edit', { closeUrl: '/playlists', newUrl: '/playlists/new', message: 'Playlist created.' @@ -352,7 +352,7 @@ module.exports = function registerPlaylistRoutes(app, deps) { await connection.commit(); await notifyPlayerScreens(saveResult.affectedScreens, 'refresh'); await broadcastDashboardState(); - redirectAfterSave(req, res, '/playlists?edit=' + playlist.id, { + redirectAfterSave(req, res, '/playlists/' + playlist.id + '/edit', { closeUrl: '/playlists', newUrl: '/playlists/new', message: 'Playlist updated.' diff --git a/src/web/views/signage/slides/popup-preview.hbs b/src/web/views/signage/slides/popup-preview.hbs index 1f74835..eb8d501 100644 --- a/src/web/views/signage/slides/popup-preview.hbs +++ b/src/web/views/signage/slides/popup-preview.hbs @@ -27,6 +27,31 @@ box-sizing: border-box; display: block; } + + .slide-preview-text-content { + line-height: 1.5; + } + + .slide-preview-text-content > * { + margin: 1em 0; + } + + .slide-preview-text-content > *:first-child { + margin-top: 0; + } + + .slide-preview-text-content > *:last-child { + margin-bottom: 1em; + } + + .slide-preview-text-content ul, + .slide-preview-text-content ol { + padding-left: 1.2em; + } + + .slide-preview-text-content code { + white-space: pre-wrap; + }