Release v2.15.2
This commit is contained in:
1 parent
ddcc665f81
commit
7295f83f04
43 files changed
+2526
-104
No files matched your search
@@ -206,19 +206,28 @@ window.addEventListener('keydown', handlePlayerKeydown);
|
||||
|
||||
// Move to the previous or next active slide.
|
||||
function navigateSlides(offset) {
|
||||
const manualSlides = getCurrentActiveSlides();
|
||||
clearSlideTimer();
|
||||
applyPendingPlaylistUpdate();
|
||||
let manualSlides = getCurrentActiveSlides();
|
||||
if (!manualSlides.length) {
|
||||
return;
|
||||
}
|
||||
let currentIndex = manualSlides.findIndex(function (slide) {
|
||||
return slide && lastRenderedSlide && slide.id === lastRenderedSlide.id;
|
||||
});
|
||||
let currentIndex = Number(index);
|
||||
if (!Number.isInteger(currentIndex) || !manualSlides[currentIndex] || !lastRenderedSlide || manualSlides[currentIndex].id !== lastRenderedSlide.id) {
|
||||
currentIndex = manualSlides.findIndex(function (slide) {
|
||||
return slide && lastRenderedSlide && slide.id === lastRenderedSlide.id;
|
||||
});
|
||||
}
|
||||
if (currentIndex < 0) {
|
||||
currentIndex = Math.min(Math.max(index, 0), manualSlides.length - 1);
|
||||
}
|
||||
const nextIndex = (currentIndex + offset + manualSlides.length) % manualSlides.length;
|
||||
clearSlideTimer();
|
||||
applyPendingPlaylistUpdate();
|
||||
let nextIndex = (currentIndex + offset + manualSlides.length) % manualSlides.length;
|
||||
if (offset > 0 && currentIndex + offset >= manualSlides.length) {
|
||||
playlistPassNumber += 1;
|
||||
clearActiveSlidesCache();
|
||||
manualSlides = getCurrentActiveSlides();
|
||||
nextIndex = 0;
|
||||
}
|
||||
renderSlideAtIndex(manualSlides, nextIndex);
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +85,7 @@ function applyPendingPlaylistUpdate() {
|
||||
var nextIndex = Number(index || 0);
|
||||
slides = pendingPlaylistUpdate.slides;
|
||||
currentPlaylistSignature = pendingPlaylistUpdate.signature;
|
||||
playlistPassNumber = 0;
|
||||
currentPlaylistFadeBetweenSlides = pendingPlaylistUpdate.fadeBetweenSlides;
|
||||
currentPlaylistSkipUnavailableRtmp = Boolean(pendingPlaylistUpdate.skipUnavailableRtmp);
|
||||
pendingPlaylistUpdate = null;
|
||||
|
||||
@@ -21,9 +21,85 @@ function getWebpageUrls(sourceSlides) {
|
||||
// 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) {
|
||||
const eligibleSlides = (Array.isArray(sourceSlides) ? sourceSlides : []).filter(function (slide) {
|
||||
return isSlideActive(slide, now);
|
||||
});
|
||||
const groups = new Map();
|
||||
eligibleSlides.forEach(function (slide) {
|
||||
const groupKey = String(slide && slide.groupKey || '');
|
||||
if (!groupKey) {
|
||||
return;
|
||||
}
|
||||
if (!groups.has(groupKey)) {
|
||||
groups.set(groupKey, []);
|
||||
}
|
||||
groups.get(groupKey).push(slide);
|
||||
});
|
||||
|
||||
const selectedGroups = new Map();
|
||||
groups.forEach(function (members, groupKey) {
|
||||
if (members[0].groupMode === 'repeat') {
|
||||
const repeatCount = Math.min(100, Math.max(1, Math.floor(Number(members[0].groupRepeatCount) || 1)));
|
||||
const repeated = [];
|
||||
for (let repetition = 0; repetition < repeatCount; repetition += 1) {
|
||||
repeated.push.apply(repeated, members);
|
||||
}
|
||||
selectedGroups.set(groupKey, repeated);
|
||||
return;
|
||||
}
|
||||
const pickCount = Math.min(members.length, Math.max(1, Math.floor(Number(members[0].groupPickCount) || 1)));
|
||||
const passNumber = Number(playlistPassNumber) || 0;
|
||||
if (members[0].groupShuffle) {
|
||||
selectedGroups.set(groupKey, members.slice().sort(function (left, right) {
|
||||
return getGroupSlideSelectionScore(groupKey, left.id, passNumber) - getGroupSlideSelectionScore(groupKey, right.id, passNumber);
|
||||
}).slice(0, pickCount));
|
||||
} else {
|
||||
selectedGroups.set(groupKey, Array.from({ length: pickCount }, function (_value, offset) {
|
||||
return members[(passNumber * pickCount + offset) % members.length];
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
const result = [];
|
||||
eligibleSlides.forEach(function (slide) {
|
||||
if (!slide.groupKey) {
|
||||
result.push(slide);
|
||||
} else if (selectedGroups.has(slide.groupKey)) {
|
||||
result.push.apply(result, selectedGroups.get(slide.groupKey));
|
||||
selectedGroups.delete(slide.groupKey);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function getGroupSlideSelectionScore(groupKey, slideId, cycleNumber) {
|
||||
const value = String(groupKey || '') + '|' + String(cycleNumber || 0) + '|' + String(slideId || '');
|
||||
let hash = 2166136261;
|
||||
for (let index = 0; index < value.length; index += 1) {
|
||||
hash ^= value.charCodeAt(index);
|
||||
hash = Math.imul(hash, 16777619);
|
||||
}
|
||||
return hash >>> 0;
|
||||
}
|
||||
|
||||
function hasSelectableGroupVariants() {
|
||||
const now = new Date();
|
||||
const eligibleGroups = new Map();
|
||||
(Array.isArray(slides) ? slides : []).forEach(function (slide) {
|
||||
const groupKey = String(slide && slide.groupKey || '');
|
||||
if (!groupKey || !isSlideActive(slide, now)) {
|
||||
return;
|
||||
}
|
||||
if (!eligibleGroups.has(groupKey)) {
|
||||
eligibleGroups.set(groupKey, []);
|
||||
}
|
||||
eligibleGroups.get(groupKey).push(slide);
|
||||
});
|
||||
return Array.from(eligibleGroups.values()).some(function (members) {
|
||||
if (members[0].groupMode === 'repeat') return false;
|
||||
return members.length > Math.max(1, Number(members[0] && members[0].groupPickCount) || 1)
|
||||
|| (members.length > 1 && Boolean(members[0].groupShuffle));
|
||||
});
|
||||
}
|
||||
|
||||
// Build a cache key for the active slide set.
|
||||
@@ -36,7 +112,8 @@ function getActiveSlidesCacheKey() {
|
||||
now.getDate(),
|
||||
now.getHours(),
|
||||
now.getMinutes(),
|
||||
now.getSeconds()
|
||||
now.getSeconds(),
|
||||
playlistPassNumber
|
||||
].join('|');
|
||||
}
|
||||
|
||||
|
||||
@@ -193,12 +193,18 @@ function matchesScheduleRule(rule, now) {
|
||||
// Determine whether a slide should be shown at the current time.
|
||||
function isSlideActive(slide, now) {
|
||||
const rules = Array.isArray(slide.scheduleRules) ? slide.scheduleRules : [];
|
||||
if (!rules.length) {
|
||||
return true;
|
||||
}
|
||||
return rules.some(function (rule) {
|
||||
if (rules.length && !rules.some(function (rule) {
|
||||
return matchesScheduleRule(rule, now);
|
||||
});
|
||||
})) {
|
||||
return false;
|
||||
}
|
||||
const groupRules = parseScheduleRules(slide.groupScheduleRules || slide.group_schedule_rules_json);
|
||||
if (slide.groupKey && groupRules.length && !groupRules.some(function (rule) {
|
||||
return matchesScheduleRule(rule, now);
|
||||
})) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Build the cache key for a template layout.
|
||||
function getTemplateLayoutCacheKey(template) {
|
||||
|
||||
@@ -122,15 +122,23 @@ function scheduleSlideAdvance(delayMs) {
|
||||
pausedRemainingMs = null;
|
||||
clearSlideOutroTimer();
|
||||
applyPendingPlaylistUpdate();
|
||||
const activeSlides = getCurrentActiveSlides();
|
||||
if (activeSlides.length < 2) {
|
||||
let activeSlides = getCurrentActiveSlides();
|
||||
const hasGroupVariants = typeof hasSelectableGroupVariants === 'function' && hasSelectableGroupVariants();
|
||||
if (activeSlides.length < 2 && !hasGroupVariants) {
|
||||
showCurrent();
|
||||
return;
|
||||
}
|
||||
if (index >= activeSlides.length) {
|
||||
index = 0;
|
||||
}
|
||||
index = (index + 1) % activeSlides.length;
|
||||
if (index + 1 >= activeSlides.length) {
|
||||
playlistPassNumber += 1;
|
||||
clearActiveSlidesCache();
|
||||
activeSlides = getCurrentActiveSlides();
|
||||
index = 0;
|
||||
} else {
|
||||
index += 1;
|
||||
}
|
||||
showCurrent();
|
||||
}, holdDelayMs);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user