Fix seek issue and improve button animation smoothness (#209)

This commit is contained in:
rlauuzo 2024-07-07 22:42:45 +02:00 committed by GitHub
parent 4081c72edd
commit 009917b2e1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -100,6 +100,9 @@ introSkipper.d = function (msg) {
opacity: 0; opacity: 0;
transition: opacity 0.3s ease-in, transform 0.3s ease-out; transition: opacity 0.3s ease-in, transform 0.3s ease-out;
} }
#skipIntro.show .emby-button {
opacity: 1;
}
#skipIntro .emby-button:hover, #skipIntro .emby-button:hover,
#skipIntro .emby-button:focus { #skipIntro .emby-button:focus {
background-color: rgba(var(--accent),0.7); background-color: rgba(var(--accent),0.7);
@ -197,9 +200,8 @@ introSkipper.videoPositionChanged = function () {
const segment = introSkipper.getCurrentSegment(introSkipper.videoPlayer.currentTime); const segment = introSkipper.getCurrentSegment(introSkipper.videoPlayer.currentTime);
switch (segment.SegmentType) { switch (segment.SegmentType) {
case "None": case "None":
if (embyButton.style.opacity === '0') return; if (!skipButton.classList.contains('show')) return;
skipButton.classList.remove('show');
embyButton.style.opacity = '0';
embyButton.addEventListener("transitionend", () => { embyButton.addEventListener("transitionend", () => {
skipButton.classList.add("hide"); skipButton.classList.add("hide");
if (tvLayout) { if (tvLayout) {
@ -216,14 +218,16 @@ introSkipper.videoPositionChanged = function () {
break; break;
} }
if (!skipButton.classList.contains("hide")) return; if (!skipButton.classList.contains("hide")) return;
requestAnimationFrame(() => {
skipButton.classList.remove("hide"); skipButton.classList.remove("hide");
embyButton.style.opacity = '1'; requestAnimationFrame(() => {
skipButton.classList.add('show');
if (tvLayout) { if (tvLayout) {
introSkipper.overrideBlur(embyButton); introSkipper.overrideBlur(embyButton);
embyButton.focus({ focusVisible: true }); embyButton.focus({ focusVisible: true });
} }
});
});
} }
introSkipper.throttle = function (func, limit) { introSkipper.throttle = function (func, limit) {
let inThrottle; let inThrottle;
@ -245,34 +249,44 @@ introSkipper.doSkip = introSkipper.throttle(async function () {
console.warn("[intro skipper] doSkip() called without an active segment"); console.warn("[intro skipper] doSkip() called without an active segment");
return; return;
} }
const currentSrc = introSkipper.videoPlayer.currentSrc;
const controller = new AbortController();
const signal = controller.signal;
const seekToSegmentEnd = () => new Promise((resolve) => { const seekToSegmentEnd = () => new Promise((resolve) => {
const onSeeked = () => { const onSeeked = () => requestAnimationFrame(resolve);
setTimeout(() => { introSkipper.videoPlayer.addEventListener('seeked', onSeeked, { once: true, signal });
introSkipper.allowEnter = true;
resolve();
}, 50); // Wait 50ms after seek completes
};
introSkipper.videoPlayer.addEventListener('seeked', onSeeked, { once: true });
introSkipper.videoPlayer.currentTime = segment.IntroEnd; introSkipper.videoPlayer.currentTime = segment.IntroEnd;
}); });
const nextEpisodeLoaded = () => new Promise(resolve => {
const onLoadStart = () => resolve(true);
const timeoutId = setTimeout(() => resolve(false), 500);
introSkipper.videoPlayer.addEventListener('loadstart', onLoadStart, { signal });
signal.addEventListener('abort', () => clearTimeout(timeoutId));
});
// Disable keydown events // Disable keydown events
introSkipper.allowEnter = false; introSkipper.allowEnter = false;
// Check if the segment is "Credits" and skipping would leave less than 3 seconds of video try {
if (segment.SegmentType === "Credits" && introSkipper.videoPlayer.duration - segment.IntroEnd < 3) { // Check if the segment is "Credits" and skipping would leave less than 3 seconds of video
// Simulate 'N' key press to go to the next episode if (segment.SegmentType === "Credits" && introSkipper.videoPlayer.duration - segment.IntroEnd < 3) {
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'N', shiftKey: true, bubbles: true })); // Simulate 'N' key press to go to the next episode
// Check if the next episode actually starts loading document.dispatchEvent(new KeyboardEvent('keydown', { key: 'N', shiftKey: true, bubbles: true }));
const nextEpisodeLoaded = await Promise.race([ // Check if the next episode actually starts loading
new Promise(resolve => introSkipper.videoPlayer.addEventListener('loadstart', () => resolve(true), { once: true })), const loaded = await nextEpisodeLoaded();
new Promise(resolve => setTimeout(() => resolve(false), 300)) // If the next episode didn't load, just seek to the end of the current segment
]); if (!loaded) {
// If the next episode didn't load, just seek to the end of the current segment await new Promise(resolve => setTimeout(resolve, 100)); // Short delay
if (!nextEpisodeLoaded) await seekToSegmentEnd(); if (introSkipper.videoPlayer.currentSrc === currentSrc) {
else introSkipper.allowEnter = true; await seekToSegmentEnd();
return; }
}
} else {
// Default behavior: seek to the end of the current segment
await seekToSegmentEnd();
}
} finally {
introSkipper.allowEnter = true; // Always re-enable keydown events
controller.abort(); // Cleanup any remaining listeners
} }
// Default behavior: seek to the end of the current segment
await seekToSegmentEnd();
}, 3000); }, 3000);
/** Tests if an element with the provided selector exists. */ /** Tests if an element with the provided selector exists. */
introSkipper.testElement = function (selector) { return document.querySelector(selector); } introSkipper.testElement = function (selector) { return document.querySelector(selector); }