Implement video region support
This commit is contained in:
@@ -364,6 +364,19 @@ body.screen-blackout #app {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.template-region.video {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.template-region.video video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
display: block;
|
||||
pointer-events: none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.template-region.webpage iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
@@ -89,10 +89,10 @@ function scheduleSlideAdvance(delayMs) {
|
||||
}, holdDelayMs);
|
||||
}
|
||||
|
||||
// Add the fade time to a slide's hold duration so the configured duration remains visible.
|
||||
function getSlideHoldDelay(delayMs) {
|
||||
// Add the fade time to a slide's hold duration unless the slide duration already accounts for it.
|
||||
function getSlideHoldDelay(delayMs, skipFadePadding) {
|
||||
var holdDelayMs = Math.max(1, Number(delayMs || 0));
|
||||
return holdDelayMs + (currentPlaylistFadeBetweenSlides ? slideFadeDurationMs : 0);
|
||||
return holdDelayMs + (currentPlaylistFadeBetweenSlides && !skipFadePadding ? slideFadeDurationMs : 0);
|
||||
}
|
||||
|
||||
// Cancel any pending fade-transition cleanup.
|
||||
@@ -109,11 +109,48 @@ function renderSlideMarkup(markup, shouldFade) {
|
||||
if (typeof destroyRtmpRegions === 'function') {
|
||||
destroyRtmpRegions(app);
|
||||
}
|
||||
|
||||
function initializeRenderedVideoPlayback(root) {
|
||||
if (!root) {
|
||||
return;
|
||||
}
|
||||
|
||||
var videos = root.querySelectorAll('.template-region.video video');
|
||||
Array.prototype.forEach.call(videos, function (video) {
|
||||
if (!video) {
|
||||
return;
|
||||
}
|
||||
|
||||
video.autoplay = true;
|
||||
video.loop = true;
|
||||
video.muted = true;
|
||||
video.playsInline = true;
|
||||
|
||||
function startPlayback() {
|
||||
var playPromise = video.play && video.play();
|
||||
if (playPromise && typeof playPromise.catch === 'function') {
|
||||
playPromise.catch(function () {
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (video.readyState >= 2) {
|
||||
startPlayback();
|
||||
return;
|
||||
}
|
||||
|
||||
video.addEventListener('canplay', startPlayback, { once: true });
|
||||
video.addEventListener('loadedmetadata', startPlayback, { once: true });
|
||||
});
|
||||
}
|
||||
|
||||
if (!shouldFade) {
|
||||
app.innerHTML = markup;
|
||||
if (typeof syncRtmpRegions === 'function') {
|
||||
syncRtmpRegions(app);
|
||||
}
|
||||
initializeRenderedVideoPlayback(app);
|
||||
return app.firstElementChild;
|
||||
}
|
||||
|
||||
@@ -143,6 +180,7 @@ function renderSlideMarkup(markup, shouldFade) {
|
||||
if (typeof syncRtmpRegions === 'function') {
|
||||
syncRtmpRegions(nextShell);
|
||||
}
|
||||
initializeRenderedVideoPlayback(nextShell);
|
||||
return nextShell;
|
||||
}
|
||||
|
||||
@@ -162,6 +200,8 @@ function renderSlideMarkup(markup, shouldFade) {
|
||||
syncRtmpRegions(nextShell);
|
||||
}
|
||||
|
||||
initializeRenderedVideoPlayback(nextShell);
|
||||
|
||||
slideTransitionTimer = window.setTimeout(function () {
|
||||
if (previousShell && previousShell.parentNode) {
|
||||
previousShell.parentNode.removeChild(previousShell);
|
||||
|
||||
@@ -147,7 +147,7 @@ function refresh() {
|
||||
markRefreshHealthy();
|
||||
setOfflineBannerVisible(false);
|
||||
if (lastRenderedSlide && getCurrentActiveSlides().length < 2) {
|
||||
scheduleSlideAdvance(getSlideHoldDelay(Math.max(1, Number(lastRenderedSlide.duration_seconds || 10)) * 1000));
|
||||
scheduleSlideAdvance(getSlideHoldDelay(Math.max(1, Number(lastRenderedSlide.duration_seconds || 10)) * 1000));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -452,6 +452,9 @@ function getTemplateRenderPlan(template) {
|
||||
if (region.regionType === 'image') {
|
||||
return renderImageRegion(region, regionContent);
|
||||
}
|
||||
if (region.regionType === 'video') {
|
||||
return renderVideoRegion(region, regionContent);
|
||||
}
|
||||
if (region.regionType === 'webpage') {
|
||||
return renderWebpageRegion(region, regionContent);
|
||||
}
|
||||
@@ -517,9 +520,21 @@ function renderSlideShell(slide, canvasClass, canvasWidth, canvasHeight, innerHt
|
||||
// Build the cache key for rendered slide markup.
|
||||
function getSlideMarkupCacheKey(slide) {
|
||||
var viewportKey = window.innerWidth + 'x' + window.innerHeight;
|
||||
return [currentPlaylistSignature || '', slide && slide.id ? slide.id : '', slide && slide.template_id ? slide.template_id : '', viewportKey].join('|');
|
||||
return [currentPlaylistSignature || '', slide && slide.id ? slide.id : '', slide && slide.template_id ? slide.template_id : '', slide && slide.modified_at ? slide.modified_at : '', viewportKey, videoRegionRenderVersion || 0].join('|');
|
||||
}
|
||||
|
||||
function notifyVideoRegionSourceReady() {
|
||||
if (typeof videoRegionRenderVersion === 'number') {
|
||||
videoRegionRenderVersion += 1;
|
||||
}
|
||||
slideMarkupCache = Object.create(null);
|
||||
if (typeof showCurrent === 'function' && slides && slides.length) {
|
||||
showCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
window.notifyVideoRegionSourceReady = notifyVideoRegionSourceReady;
|
||||
|
||||
// Look up a previously rendered slide in the cache.
|
||||
function getCachedSlideMarkup(slide) {
|
||||
var cacheKey = getSlideMarkupCacheKey(slide);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const CACHE_VERSION = 'v1';
|
||||
const CACHE_VERSION = 'v2';
|
||||
const PAGE_CACHE = `pulse-signage-player-pages-${CACHE_VERSION}`;
|
||||
const ASSET_CACHE = `pulse-signage-player-assets-${CACHE_VERSION}`;
|
||||
const MEDIA_CACHE = `pulse-signage-player-media-${CACHE_VERSION}`;
|
||||
@@ -87,6 +87,10 @@ async function staleWhileRevalidate(request, cacheName) {
|
||||
return new Response('', { status: 504, statusText: 'Offline' });
|
||||
}
|
||||
|
||||
async function networkOnly(request) {
|
||||
return fetch(request);
|
||||
}
|
||||
|
||||
self.addEventListener('install', function (event) {
|
||||
self.skipWaiting();
|
||||
event.waitUntil(Promise.resolve());
|
||||
@@ -126,7 +130,7 @@ self.addEventListener('fetch', function (event) {
|
||||
}
|
||||
|
||||
if (url.pathname.startsWith('/media/')) {
|
||||
event.respondWith(staleWhileRevalidate(request, MEDIA_CACHE));
|
||||
event.respondWith(networkOnly(request));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user