Improve support for Client Cache query types

This commit is contained in:
HighImKevin committed 2026-10-01 06:48:17 -04:00
1 parent 7abf79bbe5
commit 3229ba4123
6 files changed
+295 -99

No files matched your search

+129 -1
View File
@@ -297,6 +297,133 @@
}
}
const IDLE_HOLD_MS = 15000;
const BOOTSTRAP_FALLBACK_MS = 30000;
const SESSION_READY_FALLBACK_MS = 30000;
function hasMouseIdle() {
return typeof document !== 'undefined'
&& document.body
&& document.body.classList.contains('mouseIdle');
}
/**
* After login (+ home painted or session-ready fallback), fire onReady once when
* the first of these happens: 15s continuous body.mouseIdle, document.hidden,
* or 30s fallback. Background tabs are allowed (and preferred).
*
* @param {{ waitForLogin: () => Promise<boolean>, onReady: () => void }} opts
*/
function scheduleIdleBootstrap(opts) {
const waitForLogin = opts?.waitForLogin;
const onReady = opts?.onReady;
if (typeof onReady !== 'function') return;
let fired = false;
let idleTimer = null;
let fallbackTimer = null;
let sessionReadyTimer = null;
let mo = null;
const cleanup = () => {
if (idleTimer) {
clearTimeout(idleTimer);
idleTimer = null;
}
if (fallbackTimer) {
clearTimeout(fallbackTimer);
fallbackTimer = null;
}
if (sessionReadyTimer) {
clearTimeout(sessionReadyTimer);
sessionReadyTimer = null;
}
if (mo) {
mo.disconnect();
mo = null;
}
document.removeEventListener('visibilitychange', onVisibility);
document.removeEventListener('kefinTweaksHomePainted', onHomePainted);
};
const fire = () => {
if (fired) return;
fired = true;
cleanup();
try {
onReady();
} catch (e) {
console.error('[KefinTweaks LibraryCacheUtils] scheduleIdleBootstrap onReady failed:', e);
}
};
const syncIdleHold = () => {
if (fired) return;
if (hasMouseIdle()) {
if (!idleTimer) {
idleTimer = setTimeout(() => {
idleTimer = null;
if (hasMouseIdle()) fire();
}, IDLE_HOLD_MS);
}
} else if (idleTimer) {
clearTimeout(idleTimer);
idleTimer = null;
}
};
const onVisibility = () => {
if (document.hidden) fire();
};
const armGates = () => {
if (fired) return;
if (document.hidden) {
fire();
return;
}
fallbackTimer = setTimeout(fire, BOOTSTRAP_FALLBACK_MS);
document.addEventListener('visibilitychange', onVisibility);
if (typeof MutationObserver !== 'undefined' && document.body) {
mo = new MutationObserver(syncIdleHold);
mo.observe(document.body, { attributes: true, attributeFilter: ['class'] });
}
syncIdleHold();
};
const onHomePainted = () => {
document.removeEventListener('kefinTweaksHomePainted', onHomePainted);
if (sessionReadyTimer) {
clearTimeout(sessionReadyTimer);
sessionReadyTimer = null;
}
armGates();
};
Promise.resolve()
.then(() => (typeof waitForLogin === 'function' ? waitForLogin() : true))
.then((ok) => {
if (fired) return;
if (!ok) {
fire();
return;
}
document.addEventListener('kefinTweaksHomePainted', onHomePainted);
sessionReadyTimer = setTimeout(() => {
sessionReadyTimer = null;
document.removeEventListener('kefinTweaksHomePainted', onHomePainted);
armGates();
}, SESSION_READY_FALLBACK_MS);
})
.catch((e) => {
console.error('[KefinTweaks LibraryCacheUtils] scheduleIdleBootstrap login wait failed:', e);
fire();
});
}
window.LibraryCacheUtils = {
stripMovieForCache,
stripSeriesForCache,
@@ -310,6 +437,7 @@
upsertById,
removeByIds,
isVideoPlaybackRoute,
waitWhileCacheNetworkPaused
waitWhileCacheNetworkPaused,
scheduleIdleBootstrap
};
})();