From a390c32defcc5a6e0af84febfe773b8cd4b01001 Mon Sep 17 00:00:00 2001 From: "@permadeath.com" Date: Tue, 18 Aug 2026 11:07:08 -0400 Subject: [PATCH] feat: answer a drop-caches message in the worker Drops the scoped caches, detection's probe answers and the per-tab detection states, and answers with how many entries went. In the worker because two thirds of that is the worker's. The tab states go out through `setTabState`, so each badge drops back to idle as its state does rather than standing for something no longer stored anywhere. The account mirror and the reader choice are left alone: dropping a cache is not signing out. Co-Authored-By: Claude Opus 5 (1M context) --- src/background.ts | 37 +++++++++++++++++++++++++++++++++++-- src/lib/types.ts | 2 ++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/background.ts b/src/background.ts index 0d8bdd6..dd1c7bc 100644 --- a/src/background.ts +++ b/src/background.ts @@ -5,8 +5,8 @@ // {did, handle} into chrome.storage.local under `session` for the worker. import { listRecords, parseAtUri, resolveDid } from './lib/atproto' -import { cached } from './lib/cache' -import { detectPage } from './lib/detection' +import { cached, dropAll } from './lib/cache' +import { detectPage, dropProbes } from './lib/detection' import { type IconState, badgeFor, iconStateFor, titleFor } from './lib/icon' import { FOLLOWS_CAP, type FollowList, followingDids } from './lib/subscribers' import { welcomeUrl } from './lib/welcome' @@ -235,6 +235,36 @@ async function computeState( return state } +// --- dropping everything remembered (dev channel) ---------------------------- + +/** + * Everything the extension has remembered about what it fetched: the scoped + * caches (src/lib/cache.ts), detection's well-known probe answers + * (src/lib/detection.ts), and the per-tab detection states above. + * + * In the worker rather than in the popup because two thirds of that is the + * worker's. The tab states go through `setTabState`, so every badge drops back + * to idle as its state does instead of leaving a green dot standing for + * something no longer stored anywhere — which is also what makes the drop + * visible without opening the popup again. + * + * The account mirror and the stored reader choice are deliberately untouched: + * dropping a cache is not signing out, and not a factory reset. + */ +async function dropCaches(): Promise<{ dropped: number }> { + const all = await chrome.storage.session.get(null) + const tabIds = Object.keys(all) + .filter((k) => k.startsWith('tab:')) + .map((k) => Number(k.slice(4))) + await Promise.all(tabIds.map((tabId) => setTabState(tabId, undefined))) + const [entries, probes] = await Promise.all([dropAll(), dropProbes()]) + console.debug( + `[substandard] dropped ${entries} cache entr(ies), ${probes} probe answer(s)`, + `and ${tabIds.length} tab state(s)`, + ) + return { dropped: entries + probes + tabIds.length } +} + function isHttpUrl(url: string | undefined): url is string { return !!url && /^https?:\/\//.test(url) } @@ -279,6 +309,9 @@ async function handle(msg: Msg, sender: chrome.runtime.MessageSender): Promise