99 lines
3.0 KiB
JavaScript
99 lines
3.0 KiB
JavaScript
(function () {
|
|
let settings = DEFAULT_SETTINGS;
|
|
const elementState = new WeakMap();
|
|
const CLICK_COOLDOWN_MS = 1500;
|
|
|
|
function isSkipIntroButton(text) {
|
|
return text.indexOf("skip intro") !== -1;
|
|
}
|
|
|
|
function isSkipCreditsButton(text) {
|
|
return text.indexOf("skip credit") !== -1;
|
|
}
|
|
|
|
function isVisible(el) {
|
|
const style = window.getComputedStyle(el);
|
|
return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0";
|
|
}
|
|
|
|
function getDelayMs(type) {
|
|
const seconds = type === "intro" ? settings.introDelaySeconds : settings.creditsDelaySeconds;
|
|
return clampDelaySeconds(seconds) * 1000;
|
|
}
|
|
|
|
function isStillEligible(el, type) {
|
|
if (!document.body.contains(el)) return false;
|
|
if (!isVisible(el)) return false;
|
|
if (type === "intro" && !settings.skipIntro) return false;
|
|
if (type === "credits" && !settings.skipCredits) return false;
|
|
if (!hostMatchesConfig(window.location.hostname, settings.plexUrl)) return false;
|
|
|
|
const text = (el.innerText || el.textContent || "").trim().toLowerCase();
|
|
return type === "intro" ? isSkipIntroButton(text) : isSkipCreditsButton(text);
|
|
}
|
|
|
|
function performClick(el) {
|
|
const state = elementState.get(el) || {};
|
|
state.timer = null;
|
|
state.lastClickAt = Date.now();
|
|
elementState.set(el, state);
|
|
el.click();
|
|
}
|
|
|
|
function scheduleClick(el, type) {
|
|
const state = elementState.get(el) || {};
|
|
if (state.timer) return;
|
|
if (state.lastClickAt && Date.now() - state.lastClickAt < CLICK_COOLDOWN_MS) return;
|
|
|
|
const delayMs = getDelayMs(type);
|
|
if (delayMs <= 0) {
|
|
performClick(el);
|
|
return;
|
|
}
|
|
|
|
state.timer = setTimeout(() => {
|
|
const current = elementState.get(el) || {};
|
|
current.timer = null;
|
|
elementState.set(el, current);
|
|
if (isStillEligible(el, type)) performClick(el);
|
|
}, delayMs);
|
|
elementState.set(el, state);
|
|
}
|
|
|
|
function scanAndClick() {
|
|
if (!settings.skipIntro && !settings.skipCredits) return;
|
|
if (!hostMatchesConfig(window.location.hostname, settings.plexUrl)) return;
|
|
|
|
const nodes = document.querySelectorAll('button, [role="button"]');
|
|
nodes.forEach((el) => {
|
|
const text = (el.innerText || el.textContent || "").trim().toLowerCase();
|
|
if (!text) return;
|
|
if (!isVisible(el)) return;
|
|
|
|
if (settings.skipIntro && isSkipIntroButton(text)) {
|
|
scheduleClick(el, "intro");
|
|
} else if (settings.skipCredits && isSkipCreditsButton(text)) {
|
|
scheduleClick(el, "credits");
|
|
}
|
|
});
|
|
}
|
|
|
|
function start() {
|
|
const observer = new MutationObserver(scanAndClick);
|
|
observer.observe(document.documentElement, { childList: true, subtree: true });
|
|
scanAndClick();
|
|
}
|
|
|
|
chrome.storage.sync.get(DEFAULT_SETTINGS, (loaded) => {
|
|
settings = loaded;
|
|
start();
|
|
});
|
|
|
|
chrome.storage.onChanged.addListener((changes, area) => {
|
|
if (area !== "sync") return;
|
|
Object.keys(changes).forEach((key) => {
|
|
settings[key] = changes[key].newValue;
|
|
});
|
|
});
|
|
})();
|