mirror of
https://github.com/ranaldsgift/KefinTweaks.git
synced 2026-11-05 15:52:47 +01:00
Improve support for Client Cache query types
This commit is contained in:
1 parent
7abf79bbe5
commit
3229ba4123
6 files changed
+295
-99
No files matched your search
@@ -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
|
||||
};
|
||||
})();
|
||||
+11
-21
@@ -448,6 +448,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
/** Defer crawl until idle/hidden/fallback after home has a chance to paint. */
|
||||
let bootstrapStarted = false;
|
||||
let bootstrapScheduled = false;
|
||||
|
||||
@@ -462,30 +463,19 @@
|
||||
}
|
||||
}
|
||||
|
||||
/** Defer crawl until home has painted (or 3s after login) so home getQuery is not starved. */
|
||||
function scheduleBootstrap() {
|
||||
if (bootstrapScheduled) return;
|
||||
bootstrapScheduled = true;
|
||||
|
||||
const start = () => { bootstrap(); };
|
||||
|
||||
const onPainted = () => {
|
||||
document.removeEventListener('kefinTweaksHomePainted', onPainted);
|
||||
start();
|
||||
};
|
||||
document.addEventListener('kefinTweaksHomePainted', onPainted);
|
||||
|
||||
waitForLoginReady().then((ok) => {
|
||||
if (!ok) {
|
||||
document.removeEventListener('kefinTweaksHomePainted', onPainted);
|
||||
start();
|
||||
return;
|
||||
}
|
||||
setTimeout(() => {
|
||||
document.removeEventListener('kefinTweaksHomePainted', onPainted);
|
||||
start();
|
||||
}, 3000);
|
||||
});
|
||||
const utils = window.LibraryCacheUtils;
|
||||
if (utils?.scheduleIdleBootstrap) {
|
||||
utils.scheduleIdleBootstrap({
|
||||
waitForLogin: waitForLoginReady,
|
||||
onReady: () => { bootstrap(); }
|
||||
});
|
||||
return;
|
||||
}
|
||||
// Fallback if LibraryCacheUtils not loaded yet
|
||||
waitForLoginReady().then(() => bootstrap());
|
||||
}
|
||||
|
||||
window.MoviesCache = {
|
||||
|
||||
+16
-31
@@ -7,7 +7,7 @@
|
||||
const WARN = (...args) => console.warn('[KefinTweaks PeopleCache]', ...args);
|
||||
const ERR = (...args) => console.error('[KefinTweaks PeopleCache]', ...args);
|
||||
|
||||
const CACHE_NAME = 'library_top_people_v4';
|
||||
const CACHE_NAME = 'library_top_people_v3';
|
||||
const DEFAULT_MIN = 10;
|
||||
const DEFAULT_PER_TYPE_MAX = 100;
|
||||
const EPISODE_CHUNK_SIZE = 500;
|
||||
@@ -337,7 +337,7 @@
|
||||
const params = new URLSearchParams({
|
||||
IncludeItemTypes: 'Episode',
|
||||
Recursive: 'true',
|
||||
Fields: 'People,ImageBlurHashes',
|
||||
Fields: 'People',
|
||||
ExcludeLocationTypes: 'Virtual',
|
||||
EnableTotalRecordCount: 'false',
|
||||
SortBy: 'DateCreated',
|
||||
@@ -460,7 +460,7 @@
|
||||
setEpisodeCrawl(startIndex, newestAt, oldestApplied);
|
||||
await persistPeople({ prune: false });
|
||||
}
|
||||
} else {
|
||||
} else {
|
||||
LOG('Episode people sync: full crawl…');
|
||||
startIndex = 0;
|
||||
newestAt = null;
|
||||
@@ -747,7 +747,7 @@
|
||||
try {
|
||||
const cache = window.IndexedDBCache;
|
||||
const userId = window.ApiClient.getCurrentUserId();
|
||||
if (cache && await cache.isCacheValid(CACHE_NAME, userId)) {
|
||||
if (cache) {
|
||||
const cached = await cache.get(CACHE_NAME, userId);
|
||||
if (cached?.isComplete && Array.isArray(cached.peopleData)) {
|
||||
const currentMode = shouldLoadPeopleEpisodeData();
|
||||
@@ -791,7 +791,7 @@
|
||||
// Resume partial, incremental watermark, or start full — never wipe on missing watermark alone
|
||||
scheduleEpisodePeopleSync();
|
||||
}
|
||||
return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -906,12 +906,7 @@
|
||||
if (personType === 'Director') list = filterRoleList('Director', itemType);
|
||||
else if (personType === 'Writer') list = filterRoleList('Writer', itemType);
|
||||
else list = filterRoleList('Actor', itemType);
|
||||
return list.slice(0, limit).map((p) => {
|
||||
const out = { Id: p.Id, Name: p.Name, Type: 'Person' };
|
||||
if (p.PrimaryImageTag) out.PrimaryImageTag = p.PrimaryImageTag;
|
||||
if (p.ImageBlurHashes) out.ImageBlurHashes = p.ImageBlurHashes;
|
||||
return out;
|
||||
});
|
||||
return list.slice(0, limit).map((p) => ({ Id: p.Id, Name: p.Name, Type: 'Person' }));
|
||||
}
|
||||
|
||||
async function waitForLoginReady(maxWaitMs = 60000) {
|
||||
@@ -926,6 +921,7 @@
|
||||
return window.userHelper.waitForLogin(maxWaitMs);
|
||||
}
|
||||
|
||||
/** Defer crawl until idle/hidden/fallback after home has a chance to paint. */
|
||||
let bootstrapStarted = false;
|
||||
let bootstrapScheduled = false;
|
||||
|
||||
@@ -945,26 +941,15 @@
|
||||
function scheduleBootstrap() {
|
||||
if (bootstrapScheduled) return;
|
||||
bootstrapScheduled = true;
|
||||
|
||||
const start = () => { bootstrap(); };
|
||||
|
||||
const onPainted = () => {
|
||||
document.removeEventListener('kefinTweaksHomePainted', onPainted);
|
||||
start();
|
||||
};
|
||||
document.addEventListener('kefinTweaksHomePainted', onPainted);
|
||||
|
||||
waitForLoginReady().then((ok) => {
|
||||
if (!ok) {
|
||||
document.removeEventListener('kefinTweaksHomePainted', onPainted);
|
||||
start();
|
||||
return;
|
||||
}
|
||||
setTimeout(() => {
|
||||
document.removeEventListener('kefinTweaksHomePainted', onPainted);
|
||||
start();
|
||||
}, 3000);
|
||||
});
|
||||
const utils = window.LibraryCacheUtils;
|
||||
if (utils?.scheduleIdleBootstrap) {
|
||||
utils.scheduleIdleBootstrap({
|
||||
waitForLogin: waitForLoginReady,
|
||||
onReady: () => { bootstrap(); }
|
||||
});
|
||||
return;
|
||||
}
|
||||
waitForLoginReady().then(() => bootstrap());
|
||||
}
|
||||
|
||||
window.PeopleCache = {
|
||||
|
||||
+10
-20
@@ -316,6 +316,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
/** Defer crawl until idle/hidden/fallback after home has a chance to paint. */
|
||||
let bootstrapStarted = false;
|
||||
let bootstrapScheduled = false;
|
||||
|
||||
@@ -333,26 +334,15 @@
|
||||
function scheduleBootstrap() {
|
||||
if (bootstrapScheduled) return;
|
||||
bootstrapScheduled = true;
|
||||
|
||||
const start = () => { bootstrap(); };
|
||||
|
||||
const onPainted = () => {
|
||||
document.removeEventListener('kefinTweaksHomePainted', onPainted);
|
||||
start();
|
||||
};
|
||||
document.addEventListener('kefinTweaksHomePainted', onPainted);
|
||||
|
||||
waitForLoginReady().then((ok) => {
|
||||
if (!ok) {
|
||||
document.removeEventListener('kefinTweaksHomePainted', onPainted);
|
||||
start();
|
||||
return;
|
||||
}
|
||||
setTimeout(() => {
|
||||
document.removeEventListener('kefinTweaksHomePainted', onPainted);
|
||||
start();
|
||||
}, 3000);
|
||||
});
|
||||
const utils = window.LibraryCacheUtils;
|
||||
if (utils?.scheduleIdleBootstrap) {
|
||||
utils.scheduleIdleBootstrap({
|
||||
waitForLogin: waitForLoginReady,
|
||||
onReady: () => { bootstrap(); }
|
||||
});
|
||||
return;
|
||||
}
|
||||
waitForLoginReady().then(() => bootstrap());
|
||||
}
|
||||
|
||||
window.SeriesCache = {
|
||||
|
||||
Reference in new issue
Block a user