Save worktree changes
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
// Collect unique webpage URLs from the slide list.
|
||||
function getWebpageUrls(sourceSlides) {
|
||||
const urls = [];
|
||||
(Array.isArray(sourceSlides) ? sourceSlides : []).forEach(function (slide) {
|
||||
const content = slide && slide.content ? slide.content : {};
|
||||
const regions = slide && slide.template && Array.isArray(slide.template.regions) ? slide.template.regions : [];
|
||||
regions.forEach(function (region) {
|
||||
if (region.region_type !== 'webpage') {
|
||||
return;
|
||||
}
|
||||
const regionContent = content[region.region_key] || {};
|
||||
const url = String(regionContent.value || '').trim();
|
||||
if (url && urls.indexOf(url) === -1) {
|
||||
urls.push(url);
|
||||
}
|
||||
});
|
||||
});
|
||||
return urls;
|
||||
}
|
||||
|
||||
// Filter the slides down to those that are active right now.
|
||||
function getActiveSlidesFrom(sourceSlides) {
|
||||
const now = new Date();
|
||||
return (Array.isArray(sourceSlides) ? sourceSlides : []).filter(function (slide) {
|
||||
return isSlideActive(slide, now);
|
||||
});
|
||||
}
|
||||
|
||||
// Build a cache key for the active slide set.
|
||||
function getActiveSlidesCacheKey() {
|
||||
const now = new Date();
|
||||
return [
|
||||
currentPlaylistSignature || '',
|
||||
now.getFullYear(),
|
||||
now.getMonth(),
|
||||
now.getDate(),
|
||||
now.getHours(),
|
||||
now.getMinutes(),
|
||||
now.getSeconds()
|
||||
].join('|');
|
||||
}
|
||||
|
||||
// Return the cached active slide set for the current playlist and second.
|
||||
function getCurrentActiveSlides() {
|
||||
const cacheKey = getActiveSlidesCacheKey();
|
||||
if (cacheKey !== activeSlidesCacheKey) {
|
||||
activeSlidesCacheValue = getActiveSlidesFrom(slides);
|
||||
activeSlidesCacheKey = cacheKey;
|
||||
}
|
||||
return activeSlidesCacheValue;
|
||||
}
|
||||
|
||||
// Clear the cached active slide set.
|
||||
function clearActiveSlidesCache() {
|
||||
activeSlidesCacheKey = '';
|
||||
activeSlidesCacheValue = [];
|
||||
}
|
||||
|
||||
// Reset render caches when the viewport changes.
|
||||
function syncRenderCacheViewport() {
|
||||
var viewportKey = window.innerWidth + 'x' + window.innerHeight;
|
||||
if (renderCacheViewportKey === viewportKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
renderCacheViewportKey = viewportKey;
|
||||
slideMarkupCache = Object.create(null);
|
||||
templateLayoutCache = Object.create(null);
|
||||
templateRenderPlanCache = Object.create(null);
|
||||
}
|
||||
|
||||
// Build a signature for the currently rendered view.
|
||||
function getCurrentRenderKey(activeSlides) {
|
||||
const viewportKey = window.innerWidth + 'x' + window.innerHeight;
|
||||
const availableSlides = Array.isArray(activeSlides) ? activeSlides : [];
|
||||
if (!availableSlides.length) {
|
||||
return [currentPlaylistSignature || '', viewportKey, 'empty', slides.length ? 'scheduled' : 'assigned'].join('|');
|
||||
}
|
||||
let normalizedIndex = Number(index || 0);
|
||||
if (!Number.isFinite(normalizedIndex) || normalizedIndex < 0 || normalizedIndex >= availableSlides.length) {
|
||||
normalizedIndex = 0;
|
||||
}
|
||||
const slide = availableSlides[normalizedIndex];
|
||||
return [currentPlaylistSignature || '', viewportKey, 'slide', slide && slide.id ? slide.id : ''].join('|');
|
||||
}
|
||||
|
||||
// Pick the current slide and the next slide for webpage preloading.
|
||||
function getWebpagePreloadSlides(sourceSlides, targetIndex) {
|
||||
const availableSlides = Array.isArray(sourceSlides) ? sourceSlides : [];
|
||||
if (!availableSlides.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let normalizedIndex = Number(targetIndex || 0);
|
||||
if (!Number.isFinite(normalizedIndex) || normalizedIndex < 0 || normalizedIndex >= availableSlides.length) {
|
||||
normalizedIndex = 0;
|
||||
}
|
||||
|
||||
const preloadSlides = [];
|
||||
const currentSlide = availableSlides[normalizedIndex];
|
||||
const nextSlide = availableSlides[normalizedIndex + 1];
|
||||
|
||||
if (currentSlide) {
|
||||
preloadSlides.push(currentSlide);
|
||||
}
|
||||
if (nextSlide && nextSlide !== currentSlide) {
|
||||
preloadSlides.push(nextSlide);
|
||||
}
|
||||
|
||||
return preloadSlides;
|
||||
}
|
||||
|
||||
// Mount hidden iframe preloads for the chosen webpage URLs.
|
||||
function syncWebpagePreloads(sourceSlides, targetIndex) {
|
||||
const urls = getWebpageUrls(getWebpagePreloadSlides(sourceSlides, targetIndex));
|
||||
const signature = urls.join('\n');
|
||||
if (signature === preloadSignature) {
|
||||
return;
|
||||
}
|
||||
if (!urls.length) {
|
||||
preloadSignature = '';
|
||||
if (preloadContainer) {
|
||||
preloadContainer.innerHTML = '';
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!preloadContainer) {
|
||||
preloadContainer = document.createElement('div');
|
||||
preloadContainer.className = 'webpage-preloads';
|
||||
preloadContainer.setAttribute('aria-hidden', 'true');
|
||||
document.body.appendChild(preloadContainer);
|
||||
}
|
||||
preloadContainer.innerHTML = urls.map(function (url) {
|
||||
return '<iframe class="webpage-preload-frame" src="' + escapeHtml(url) + '" title="Webpage preload" tabindex="-1" loading="eager" referrerpolicy="no-referrer" scrolling="no"></iframe>';
|
||||
}).join('');
|
||||
preloadSignature = signature;
|
||||
}
|
||||
|
||||
// Return a stable client id for this browser session.
|
||||
function getCommandClientId() {
|
||||
if (commandClientId) {
|
||||
return commandClientId;
|
||||
}
|
||||
try {
|
||||
var storedClientId = window.localStorage.getItem(commandClientStorageKey);
|
||||
if (storedClientId) {
|
||||
commandClientId = storedClientId;
|
||||
return commandClientId;
|
||||
}
|
||||
} catch (_error) {
|
||||
// fall through to ephemeral ID generation
|
||||
}
|
||||
commandClientId = (window.crypto && window.crypto.randomUUID ? window.crypto.randomUUID() : 'client-' + Date.now() + '-' + Math.random().toString(16).slice(2));
|
||||
try {
|
||||
window.localStorage.setItem(commandClientStorageKey, commandClientId);
|
||||
} catch (_error2) {
|
||||
// ignore storage errors
|
||||
}
|
||||
return commandClientId;
|
||||
}
|
||||
|
||||
// Load the most recent playlist snapshot from browser storage.
|
||||
function loadPlaylistSnapshot() {
|
||||
try {
|
||||
var raw = window.localStorage.getItem(playlistSnapshotStorageKey);
|
||||
if (!raw) {
|
||||
return null;
|
||||
}
|
||||
var parsed = JSON.parse(raw);
|
||||
if (!parsed || !Array.isArray(parsed.slides)) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
slides: parsed.slides.map(normalizeSlide),
|
||||
signature: String(parsed.signature || ''),
|
||||
fadeBetweenSlides: Boolean(parsed.fadeBetweenSlides),
|
||||
etag: String(parsed.etag || '')
|
||||
};
|
||||
} catch (_error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Save the latest playlist snapshot for offline recovery.
|
||||
function savePlaylistSnapshot(data) {
|
||||
try {
|
||||
window.localStorage.setItem(playlistSnapshotStorageKey, JSON.stringify({
|
||||
slides: Array.isArray(data && data.slides) ? data.slides : [],
|
||||
signature: String(data && data.signature || ''),
|
||||
fadeBetweenSlides: Boolean(data && data.fadeBetweenSlides),
|
||||
etag: String(data && data.etag || ''),
|
||||
savedAt: new Date().toISOString()
|
||||
}));
|
||||
} catch (_error) {
|
||||
// ignore storage errors
|
||||
}
|
||||
}
|
||||
|
||||
// Apply a playlist snapshot to the current in-memory state.
|
||||
function applyPlaylistSnapshot(data) {
|
||||
if (!data || !Array.isArray(data.slides)) {
|
||||
return false;
|
||||
}
|
||||
slides = data.slides.map(normalizeSlide);
|
||||
currentPlaylistSignature = String(data.signature || '');
|
||||
currentPlaylistFadeBetweenSlides = Boolean(data.fadeBetweenSlides);
|
||||
currentPlaylistEtag = String(data.etag || '');
|
||||
pendingPlaylistUpdate = null;
|
||||
clearActiveSlidesCache();
|
||||
slideMarkupCache = Object.create(null);
|
||||
templateLayoutCache = Object.create(null);
|
||||
templateRenderPlanCache = Object.create(null);
|
||||
renderCacheViewportKey = '';
|
||||
index = 0;
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user