video end setting
This commit is contained in:
@@ -76,6 +76,22 @@ App.feed = App.feed || {};
|
||||
return Math.min(total - 1, Math.max(0, index));
|
||||
};
|
||||
|
||||
// True when the user wants a finished clip to replay; false when it should
|
||||
// auto-advance to the next video. Defaults to looping (see storage).
|
||||
const shouldLoop = function() {
|
||||
return App.storage.getFeedEndBehavior() !== 'scroll';
|
||||
};
|
||||
|
||||
// Smoothly scrolls to the slide after `fromIndex`; the scroll-snap container
|
||||
// fires onScroll, which promotes the new slide to active. No-ops at the end
|
||||
// of the list so the final clip simply stops on its last frame.
|
||||
const advanceToNext = function(fromIndex) {
|
||||
const next = clampIndex(fromIndex + 1);
|
||||
if (next < 0 || next === fromIndex) return;
|
||||
const scroller = getScroller();
|
||||
if (scroller) scroller.scrollTo({ top: next * slideHeight(), behavior: 'smooth' });
|
||||
};
|
||||
|
||||
// Remembers playback position per video id so scrolling away and back
|
||||
// resumes where the user left off. Slides kept in the window are merely
|
||||
// paused (instant resume); slides whose <video> is torn down to free
|
||||
@@ -302,7 +318,7 @@ App.feed = App.feed || {};
|
||||
const favKey = App.favorites ? App.favorites.getKey(v) : null;
|
||||
slide.innerHTML = `
|
||||
<img class="feed-poster" src="${v.thumb || ''}" alt="" loading="lazy" decoding="async">
|
||||
<video class="feed-video" muted playsinline webkit-playsinline loop preload="none"></video>
|
||||
<video class="feed-video" muted playsinline webkit-playsinline preload="none"></video>
|
||||
${liveBadge}
|
||||
${favKey ? `<button class="favorite-btn feed-fav-btn" type="button" data-fav-key="${favKey}"></button>` : ''}
|
||||
<div class="feed-info">
|
||||
@@ -318,7 +334,18 @@ App.feed = App.feed || {};
|
||||
`;
|
||||
const poster = slide.querySelector('.feed-poster');
|
||||
App.videos.attachNoReferrerRetry(poster);
|
||||
bindTimeline(slide, slide.querySelector('.feed-video'));
|
||||
const slideVideo = slide.querySelector('.feed-video');
|
||||
bindTimeline(slide, slideVideo);
|
||||
|
||||
// On video end, either loop (handled by the `loop` flag, so `ended`
|
||||
// never fires) or auto-scroll to the next clip. We only advance for the
|
||||
// active slide so a preloaded neighbour ending early can't hijack focus.
|
||||
slideVideo.loop = shouldLoop();
|
||||
slideVideo.addEventListener('ended', () => {
|
||||
if (shouldLoop()) return;
|
||||
if (!slide.classList.contains('is-active')) return;
|
||||
advanceToNext(slide._index);
|
||||
});
|
||||
|
||||
const favBtn = slide.querySelector('.feed-fav-btn');
|
||||
if (favBtn && App.favorites) {
|
||||
@@ -489,6 +516,16 @@ App.feed = App.feed || {};
|
||||
return !!state.feedOpen;
|
||||
};
|
||||
|
||||
// Re-applies the on-video-end preference to every rendered slide so toggling
|
||||
// the setting takes effect immediately, without needing to reopen the feed.
|
||||
App.feed.applyEndBehavior = function() {
|
||||
const loop = shouldLoop();
|
||||
slidesByIndex.forEach((slide) => {
|
||||
const video = slide.querySelector('.feed-video');
|
||||
if (video) video.loop = loop;
|
||||
});
|
||||
};
|
||||
|
||||
// Called whenever new video JSON is appended (e.g. after a prefetch). Lets
|
||||
// the open feed pick up newly buffered slides and extend its window if the
|
||||
// active slide is near the end.
|
||||
|
||||
Reference in New Issue
Block a user