diff --git a/.omni/e42f8a19-untitled/memory.md b/.omni/e42f8a19-untitled/memory.md index 1760ebe..7786a80 100644 --- a/.omni/e42f8a19-untitled/memory.md +++ b/.omni/e42f8a19-untitled/memory.md @@ -19,6 +19,7 @@ - Selection capture is coordinated in `src/background/service-worker.ts`: popup sends `CAPTURE_SCREENSHOT`, service worker injects the selection overlay, then receives `SELECTION_COMPLETE` and crops via the offscreen document. - Popup runtime message listeners must ignore unrelated messages synchronously; an async listener can interfere with offscreen `ADD_WATERMARK` responses while the popup is open. +- Extension badge count is maintained by background `updateExtensionBadge()` from IndexedDB asset count; popup-side deletes should send `REFRESH_BADGE`. --- -_Last system refresh: 2026-05-06 07:09 UTC_ +_Last system refresh: 2026-05-06 07:28 UTC_ diff --git a/src/background/service-worker.ts b/src/background/service-worker.ts index 46fb494..2df42e8 100644 --- a/src/background/service-worker.ts +++ b/src/background/service-worker.ts @@ -173,6 +173,17 @@ chrome.runtime.onMessage.addListener((message: ExtensionMessage, sender, sendRes }); return true; + case 'REFRESH_BADGE': + // Only allow from extension pages, not content scripts + if (sender.tab) { + sendResponse({ success: false, error: 'Unauthorized sender' }); + return false; + } + updateExtensionBadge() + .then(() => sendResponse({ success: true })) + .catch((error) => sendResponse({ success: false, error: error.message })); + return true; + default: logger.warn('Unknown message type:', message.type); sendResponse({ success: false, error: 'Unknown message type' }); diff --git a/src/popup/popup.tsx b/src/popup/popup.tsx index be5a9f1..386f5c6 100644 --- a/src/popup/popup.tsx +++ b/src/popup/popup.tsx @@ -195,6 +195,17 @@ function PopupApp() { } } + async function refreshExtensionBadge() { + try { + const response = await chrome.runtime.sendMessage({ type: 'REFRESH_BADGE' }); + if (!response?.success) { + logger.warn('Failed to refresh badge:', response?.error || 'Unknown error'); + } + } catch (error) { + logger.warn('Failed to refresh badge:', error); + } + } + async function handleDeleteAsset(assetId: string) { if (!confirm('Are you sure you want to delete this screenshot?')) { return; @@ -204,6 +215,7 @@ function PopupApp() { const updatedAssets = await indexedDBService.getAllAssets(); setAssets(updatedAssets); setEditingAsset(null); + await refreshExtensionBadge(); } catch (error) { logger.error('Failed to delete asset:', error); alert('Failed to delete screenshot'); @@ -257,6 +269,7 @@ function PopupApp() { try { const allAssets = await indexedDBService.getAllAssets(); await Promise.all(allAssets.map((asset) => indexedDBService.deleteAsset(asset.id))); + await refreshExtensionBadge(); } catch (error) { logger.error('Failed to clear IndexedDB assets on logout:', error); } diff --git a/src/types/index.ts b/src/types/index.ts index 8c8e3ac..9fb99a0 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -47,7 +47,8 @@ export type MessageType = | 'ADD_WATERMARK' | 'START_GOOGLE_AUTH' | 'SELECTION_COMPLETE' - | 'CROP_IMAGE'; + | 'CROP_IMAGE' + | 'REFRESH_BADGE'; export interface ExtensionMessage { type: MessageType;