Skip to content

Eliminate base64 data URL bottlenecks in message passing and IndexedDB reads#33

Draft
Copilot wants to merge 2 commits intomainfrom
copilot/featureeliminate-base64-bottlenecks
Draft

Eliminate base64 data URL bottlenecks in message passing and IndexedDB reads#33
Copilot wants to merge 2 commits intomainfrom
copilot/featureeliminate-base64-bottlenecks

Conversation

Copy link

Copilot AI commented Mar 13, 2026

Full base64 screenshot data (2–10 MB per image) was being serialized through Chrome message channels twice per capture and loaded wholesale on every badge update and upload progress tick, causing excessive memory usage and potential service worker termination.

Changes

IndexedDB: lightweight query methods (IndexedDBService.ts)

  • getAssetCount() — uses IDBObjectStore.count(), no blob loading
  • getAllAssetMetadata() — cursor-based, omits the uri field; exported AssetMetadata = Omit<Asset, 'uri'> type

Watermark pipeline: IDB handoff instead of message-channel payload (service-worker.ts, offscreen.ts)

Previously, the raw data URL was sent to the offscreen doc and the watermarked URL sent back — 2× full serialization per capture. Now:

  1. Raw screenshot stored in IDB before watermarking
  2. ADD_WATERMARK message carries only assetId
  3. Offscreen doc reads from IDB, draws on canvas, writes watermarked URI back to IDB
  4. SCREENSHOT_CAPTURED notification to popup carries only assetId
// Before
sendMessage({ type: 'ADD_WATERMARK', payload: { dataUrl, ...settings } })
// After
await assetStorage.setAsset({ id: assetId, uri: rawDataUrl, ... });
sendMessage({ type: 'ADD_WATERMARK', payload: { assetId, ...settings } })

Badge updates: getAssetCount() instead of getAllAssets() (service-worker.ts)

No longer loads all asset blobs on every badge refresh.

Upload progress: targeted state update instead of full IDB reload (popup.tsx)

UPLOAD_PROGRESS with status: 'uploading' now does an in-place React state update on the specific asset. Full IDB reload only on status transitions (uploaded / failed).

// Before: full reload on every 500ms tick
const updatedAssets = await indexedDBService.getAllAssets();
setAssets(updatedAssets);

// After: surgical update during progress, reload only on status change
setAssets(prev => prev.map(a =>
  a.id === payload.assetId
    ? { ...a, status: 'uploading', metadata: { ...a.metadata, uploadProgress: payload.progress } }
    : a
));

Environment config: import.meta.env support (environment.ts)

VITE_API_URL and VITE_ENABLE_LOGGING read from Vite env vars. .env.development (logging on) and .env.production (logging off) added as committed defaults; override via .env.local.

Original prompt

This section details on the original issue you should resolve

<issue_title>[Feature][High] Eliminate base64 data URL bottlenecks in message passing and IndexedDB reads</issue_title>
<issue_description>## Summary

Multiple performance-critical paths pass full base64 screenshot data (2-10MB per image) through Chrome message channels and load entire asset datasets into memory, causing excessive memory usage and potential service worker termination.

Findings

1. Data URL Passed Through Message Channels (HIGH)

Files: src/background/service-worker.ts lines 241-255, 442-455, 350-357, 528-535

Full screenshot data URLs are serialized through chrome.runtime.sendMessage to the offscreen document for watermarking and back. For a 4K PNG screenshot, ~12MB of base64 is serialized twice. The same data URL is also sent in SCREENSHOT_CAPTURED messages to the popup.

Fix: Store the screenshot blob in IndexedDB first, then pass only the asset ID to the offscreen document. The offscreen document reads the blob, processes it, and writes the result back. For popup notifications, pass only the asset ID.

2. getAllAssets() Loads Full Base64 Data (HIGH)

Files: src/services/IndexedDBService.ts lines 129-145, src/popup/popup.tsx line 67, src/background/service-worker.ts line 626

getAllAssets() calls store.getAll() which loads every asset including the full base64 uri field. Called on popup load, on every 500ms progress tick, and for badge updates. With 6 assets queued, this means 12-60MB loaded into memory on each call.

Fix:

  • Add getAllAssetMetadata() using an IDB cursor that excludes the uri field
  • Add getAssetCount() for badge-only updates
  • Load full asset data only on demand (e.g., when displaying a specific thumbnail)

3. Popup Reloads Entire Asset List on Every Progress Tick (MEDIUM)

Files: src/popup/popup.tsx lines 243-251

UPLOAD_PROGRESS handler calls getAllAssets() on every tick (every 500ms). This triggers full IndexedDB read + React re-render of the entire asset list + checkCreditStatus call twice per second during uploads.

Fix: Update only the specific asset's progress in React state using the payload data directly. Only do full refresh on status transitions.

4. Hardcoded API URL With No Environment Switching (MEDIUM)

Files: src/config/environment.ts lines 13-17

API base URL is hardcoded. enableLogging is always true. No staging/development environment support despite --mode development in dev script.

Fix: Use Vite's import.meta.env with .env.development and .env.production files.

Expected Impact

  • 50-75% reduction in peak memory usage during capture
  • Prevents service worker termination due to memory limits
  • ~80% CPU reduction during upload progress updates
  • Enables proper staging/production separation

Labels

enhancement, priority:high</issue_description>

Comments on the Issue (you are @copilot in this section)


📱 Kick off Copilot coding agent tasks wherever you are with GitHub Mobile, available on iOS and Android.

…B reads

Co-authored-by: numbers-official <181934381+numbers-official@users.noreply.github.com>
Copilot AI changed the title [WIP] [Feature] Eliminate base64 data URL bottlenecks in message passing Eliminate base64 data URL bottlenecks in message passing and IndexedDB reads Mar 13, 2026
Copilot AI requested a review from numbers-official March 13, 2026 22:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature][High] Eliminate base64 data URL bottlenecks in message passing and IndexedDB reads

2 participants