@@ -117,6 +117,7 @@ window.cancelAnimFrame = (function () {
|
|||||||
|
|
||||||
// Clear grid cache to force fresh render on next navigation
|
// Clear grid cache to force fresh render on next navigation
|
||||||
if (typeof gridCacheMap !== 'undefined') gridCacheMap.clear();
|
if (typeof gridCacheMap !== 'undefined') gridCacheMap.clear();
|
||||||
|
if (window._gridAjaxCache) window._gridAjaxCache.clear();
|
||||||
|
|
||||||
// Update elements with data-bg (grid items).
|
// Update elements with data-bg (grid items).
|
||||||
// We look for any data-bg or inline style containing the thumbnail path for this ID.
|
// We look for any data-bg or inline style containing the thumbnail path for this ID.
|
||||||
@@ -653,6 +654,7 @@ window.cancelAnimFrame = (function () {
|
|||||||
if (data.success) {
|
if (data.success) {
|
||||||
window.flashMessage('ALL MODE ACTIVATED');
|
window.flashMessage('ALL MODE ACTIVATED');
|
||||||
gridCacheMap.clear();
|
gridCacheMap.clear();
|
||||||
|
if (window._gridAjaxCache) window._gridAjaxCache.clear();
|
||||||
const isGridView = document.querySelector('.posts, .tags-grid');
|
const isGridView = document.querySelector('.posts, .tags-grid');
|
||||||
let reloadPromise = null;
|
let reloadPromise = null;
|
||||||
if (isGridView) {
|
if (isGridView) {
|
||||||
@@ -708,6 +710,7 @@ window.cancelAnimFrame = (function () {
|
|||||||
: 'ALL MODE ACTIVATED';
|
: 'ALL MODE ACTIVATED';
|
||||||
window.flashMessage(label);
|
window.flashMessage(label);
|
||||||
gridCacheMap.clear();
|
gridCacheMap.clear();
|
||||||
|
if (window._gridAjaxCache) window._gridAjaxCache.clear();
|
||||||
const isGridView = document.querySelector('.posts, .tags-grid');
|
const isGridView = document.querySelector('.posts, .tags-grid');
|
||||||
const isItemView = document.getElementById('prev') || document.getElementById('next');
|
const isItemView = document.getElementById('prev') || document.getElementById('next');
|
||||||
let reloadPromise = null;
|
let reloadPromise = null;
|
||||||
@@ -2118,6 +2121,16 @@ window.cancelAnimFrame = (function () {
|
|||||||
};
|
};
|
||||||
window.initSidebarRightToggle();
|
window.initSidebarRightToggle();
|
||||||
|
|
||||||
|
// ── AJAX grid response cache (stale-while-revalidate) ────────────────────
|
||||||
|
// The AJAX endpoint has Cache-Control: no-store on the server, so the browser
|
||||||
|
// never caches it. Every logo click was a full DB query + round-trip, making
|
||||||
|
// Chromium feel slow vs Firefox (which has lower fetch overhead internally).
|
||||||
|
// We cache the JSON response in JS memory keyed by the stable ajaxUrl (no _t
|
||||||
|
// param) and serve it instantly on repeat visits, then refetch in background.
|
||||||
|
const _gridAjaxCache = new Map(); // key → { data, ts }
|
||||||
|
const _GRID_AJAX_TTL = 60_000; // 60 s — fresh enough, fast enough
|
||||||
|
window._gridAjaxCache = _gridAjaxCache; // expose for clearing on mode change / upload
|
||||||
|
|
||||||
const loadPageAjax = async (url, replace = true, options = {}) => {
|
const loadPageAjax = async (url, replace = true, options = {}) => {
|
||||||
if (isNavigating) return;
|
if (isNavigating) return;
|
||||||
|
|
||||||
@@ -2436,7 +2449,7 @@ window.cancelAnimFrame = (function () {
|
|||||||
|
|
||||||
const isRandom = document.cookie.includes('random_mode=1') || url.includes('random=1') || window.location.search.includes('random=1');
|
const isRandom = document.cookie.includes('random_mode=1') || url.includes('random=1') || window.location.search.includes('random=1');
|
||||||
if (isRandom) ajaxUrl += `&random=1`;
|
if (isRandom) ajaxUrl += `&random=1`;
|
||||||
ajaxUrl += `&_t=${Date.now()}`;
|
// NOTE: _t=Date.now() cache-buster removed — we use the JS-level _gridAjaxCache instead.
|
||||||
const isStrict = window.f0ckSession?.strict_mode || (localStorage.getItem('search_strict') === 'true');
|
const isStrict = window.f0ckSession?.strict_mode || (localStorage.getItem('search_strict') === 'true');
|
||||||
if (isStrict || url.includes('strict=1') || window.location.search.includes('strict=1')) {
|
if (isStrict || url.includes('strict=1') || window.location.search.includes('strict=1')) {
|
||||||
ajaxUrl += (ajaxUrl.includes('?') ? '&' : '?') + 'strict=1';
|
ajaxUrl += (ajaxUrl.includes('?') ? '&' : '?') + 'strict=1';
|
||||||
@@ -2451,11 +2464,32 @@ window.cancelAnimFrame = (function () {
|
|||||||
|
|
||||||
if (window.randomizeLogo) window.randomizeLogo();
|
if (window.randomizeLogo) window.randomizeLogo();
|
||||||
|
|
||||||
const response = await fetch(needsFullHtmlFetch ? url : ajaxUrl, {
|
// ── Stale-while-revalidate for grid AJAX ──────────────────────────────
|
||||||
|
// For grid fetches (not full-HTML structural pages), check the JS cache.
|
||||||
|
// Random mode gets a shorter TTL since content is expected to differ each time.
|
||||||
|
const _ajaxCacheTtl = isRandom ? 10_000 : _GRID_AJAX_TTL;
|
||||||
|
const _ajaxCached = !needsFullHtmlFetch && _gridAjaxCache.get(ajaxUrl);
|
||||||
|
const _ajaxCacheHit = _ajaxCached && (Date.now() - _ajaxCached.ts < _ajaxCacheTtl);
|
||||||
|
|
||||||
|
let response;
|
||||||
|
if (_ajaxCacheHit) {
|
||||||
|
// Serve from cache instantly, then kick off a background refresh
|
||||||
|
const _cachedData = _ajaxCached.data;
|
||||||
|
// Background refetch — update cache silently
|
||||||
|
fetch(ajaxUrl, { credentials: 'include', headers: fetchHeaders })
|
||||||
|
.then(r => r.ok ? r.json() : null)
|
||||||
|
.then(d => { if (d) _gridAjaxCache.set(ajaxUrl, { data: d, ts: Date.now() }); })
|
||||||
|
.catch(() => {});
|
||||||
|
|
||||||
|
// Jump straight to processing the cached data
|
||||||
|
// (skip the await fetch below by injecting a resolved-response shim)
|
||||||
|
response = { ok: true, _cachedData };
|
||||||
|
} else {
|
||||||
|
response = await fetch(needsFullHtmlFetch ? url : ajaxUrl, {
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
headers: fetchHeaders,
|
headers: fetchHeaders
|
||||||
cache: 'no-store'
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (needsFullHtmlFetch) {
|
if (needsFullHtmlFetch) {
|
||||||
if (!main) {
|
if (!main) {
|
||||||
@@ -2856,7 +2890,17 @@ window.cancelAnimFrame = (function () {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
// Use cached data directly, or parse fresh response and store in cache
|
||||||
|
const data = response._cachedData
|
||||||
|
? response._cachedData
|
||||||
|
: await (async () => {
|
||||||
|
const d = await response.json();
|
||||||
|
// Store in cache for next visit (grid fetches only, not full-HTML pages)
|
||||||
|
if (!needsFullHtmlFetch && d && d.success) {
|
||||||
|
_gridAjaxCache.set(ajaxUrl, { data: d, ts: Date.now() });
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
})();
|
||||||
|
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
if (replace) {
|
if (replace) {
|
||||||
|
|||||||
Reference in New Issue
Block a user