Fixes youtube video repeating when watching in playlist + refreshing page if video stopped downloading
当前为
// ==UserScript==
// @name Loop Fix
// @description Fixes youtube video repeating when watching in playlist + refreshing page if video stopped downloading
// @version 0.1.6
// @author 0vC4
// @namespace https://greasyfork.org/users/670183
// @match *://*.youtube.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @run-at document-start
// @license MIT
// @grant none
// ==/UserScript==
(() => {
function blockEvents(condition, ...events) {
events = events.flat();
const tag = window.EventTarget.prototype;
tag._add = tag.addEventListener;
tag.addEventListener = function (name, callback, options) {
if (!events.includes(name)) return tag._add.call(this, name, callback, options);
function cb(e) {
if (!condition.call(this)) return;
callback.call(this, e);
};
tag._add.call(this, name, cb, options);
};
}
blockEvents(function() {
return !this.loop; // have loop = block events
}, 'pause', 'timeupdate', 'waiting');
})();
const log = window.console.log;
window.loopState = localStorage.getItem('loopState') ?? false;
function clicking(e) {
window.loopState = JSON.parse(this.ariaChecked);
};
let created = false;
let refreshing = false;
let loaded = false;
let oldVid = null;
window.setInterval(()=>{
const vid = window.document.querySelector('video.html5-main-video');
if (vid) {
// to prevent false detecting when changing video
if (vid != oldVid) {
loaded = false;
oldVid = vid;
}
if (!created) {
created = true;
localStorage.removeItem('loopState');
// refresh if no data for half sec
const callback = () => {
if (!loaded && vid.readyState === window.HTMLMediaElement.HAVE_NOTHING) {
localStorage.setItem('loopState', window.loopState);
window.location.href = window.location.href;
}
};
const blob = new window.Blob([`setTimeout(() => postMessage(0), 500);`]);
const workerScript = window.URL.createObjectURL(blob);
const script = window.trustedTypes && window.trustedTypes.createPolicy ? window.trustedTypes.createPolicy('timeout', {createScriptURL: str => str}).createScriptURL(workerScript) : workerScript;
const worker = new window.Worker(script);
worker.onmessage = callback;
}
// apply loopState after .src or page refresh
if (vid.loop != window.loopState) vid.loop = window.loopState;
// to prevent early page refresh
if (vid.readyState === window.HTMLMediaElement.HAVE_CURRENT_DATA) loaded = true;
const noData = vid.readyState === window.HTMLMediaElement.HAVE_CURRENT_DATA || vid.readyState === window.HTMLMediaElement.HAVE_METADATA;
if (loaded && !refreshing && noData && !vid.paused && +vid.currentTime.toFixed(0) >= +vid.buffered.end(0).toFixed(0) - 1) {
localStorage.setItem('loopState', window.loopState);
window.location.href = window.location.href.split('?')[0] + '?t=' + vid.currentTime.toFixed(0) + '&' + window.location.href.split('?')[1];
refreshing = true;
}
}
// attach loop click detector
const repeat = window.document.querySelectorAll('.ytp-menuitem[tabindex="-1"]')[0];
if (repeat && repeat.onclick != clicking) {
repeat.onclick = clicking
}
});