Global hash strip: suppress re-scan on anchor-only URL changes

This commit is contained in:
admin
2026-05-27 00:50:15 +02:00
parent 2d6a95682f
commit 87d3f6d12c
2 changed files with 27 additions and 3 deletions
+26 -2
View File
@@ -639,24 +639,42 @@ async function persistTabResult(tab, result) {
} catch {}
}
// URL fragment (hash) never affects server response or our ID extraction. Strip it
// when comparing URLs so in-page anchor jumps (e.g. `#gallery-1`, `#gallery-2`) don't
// invalidate the tab cache or re-trigger scans. See exoticaz.to gallery navigation.
function stripHash(url) {
if (typeof url !== "string") return url;
const i = url.indexOf("#");
return i === -1 ? url : url.slice(0, i);
}
// Tracks the last full URL we saw per tab so we can detect hash-only changes
// (which Chrome still reports via `chrome.tabs.onUpdated` with `changeInfo.url`).
const tabLastUrl = new Map(); // tabId -> last full url seen
async function getTabResult(tab) {
if (!tab || tab.id == null) return null;
try {
const got = await chrome.storage.session.get(tabCacheKey(tab.id));
const entry = got[tabCacheKey(tab.id)];
if (!entry) return null;
if (entry.url !== (tab.url || "")) return null;
if (stripHash(entry.url) !== stripHash(tab.url || "")) return null;
return entry;
} catch { return null; }
}
chrome.tabs.onUpdated.addListener((tabId, changeInfo) => {
if (changeInfo.url) chrome.storage.session.remove(tabCacheKey(tabId));
if (!changeInfo.url) return;
const prev = tabLastUrl.get(tabId);
// Hash-only change → keep the cached result; same page, just a fragment jump.
if (prev && stripHash(prev) === stripHash(changeInfo.url)) return;
chrome.storage.session.remove(tabCacheKey(tabId));
});
chrome.tabs.onRemoved.addListener((tabId) => {
stopBadgeSpinner(tabId);
chrome.storage.session.remove(tabCacheKey(tabId));
lastAutoCheck.delete(tabId);
tabLastUrl.delete(tabId);
const t = pendingSpaTimer.get(tabId);
if (t) { clearTimeout(t); pendingSpaTimer.delete(tabId); }
});
@@ -999,6 +1017,7 @@ chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
if (changeInfo.status === "complete") {
const t = pendingSpaTimer.get(tabId);
if (t) { clearTimeout(t); pendingSpaTimer.delete(tabId); }
tabLastUrl.set(tabId, tab.url);
maybeAutoCheck(tabId, tab, "complete");
return;
}
@@ -1006,6 +1025,11 @@ chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
// the page has a chance to update its title/DOM, and so a real reload (which
// also emits a url change before complete) doesn't double-fire.
if (typeof changeInfo.url === "string") {
const prevUrl = tabLastUrl.get(tabId);
tabLastUrl.set(tabId, changeInfo.url);
// Hash-only change (e.g. `#gallery-2` anchor jump) is purely client-side UI
// state. Suppress the SPA scan trigger so anchor navigation doesn't re-fire.
if (prevUrl && stripHash(prevUrl) === stripHash(changeInfo.url)) return;
const prev = pendingSpaTimer.get(tabId);
if (prev) clearTimeout(prev);
const handle = setTimeout(() => {