Skip to content

Cache full images when saving attachments - #1671

Merged
osyed merged 9 commits into
mainfrom
issue-1656-save-image-cache-phase1
Sep 1, 2026
Merged

Cache full images when saving attachments#1671
osyed merged 9 commits into
mainfrom
issue-1656-save-image-cache-phase1

Conversation

@dnlbui

@dnlbui dnlbui commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

What Changed

This PR adds Phase 1 of the full-image attachment cache by making image Save cache-first.

  • FullImageCache stores decrypted, full-resolution image Blobs by attachment URL in IndexedDB.
  • Image Save checks IndexedDB first. A miss downloads and decrypts the original once, caches it best-effort, and continues through the existing browser or React Native filesystem-save path.
  • A hit skips the attachment request and decryption while still using the current message filename for filesystem export.
  • Non-image downloads remain unchanged, and cache failures do not prevent a freshly decrypted image from being saved.
  • A database upgrade blocked by an older open tab now rejects cache initialization so Save falls back to the uncached flow instead of waiting indefinitely.

IndexedDB Changes

  • liberdus_thumbnails upgrades from version 1 to version 2 and retains its existing thumbnails object store.
  • The upgrade adds a fullImages object store using attachment url as its primary key and cachedAt as its only index, matching the thumbnail cache's simple device-shared identity model.
  • Each record stores the URL, MIME type, Blob size, decrypted full-resolution Blob, and cache timestamp. Filenames are not cached because Save uses the current message's filename.
  • Full images have an independent 250 MiB application limit and remain excluded from thumbnail backup and restore.

Fixed Flow

  1. The user selects Save for an image attachment.
  2. Liberdus looks up the full image by attachment URL.
  3. On a hit, the cached Blob is returned without fetching or decrypting again.
  4. On a miss, Liberdus downloads and decrypts the original, stores it best-effort, and returns it.
  5. If IndexedDB is unavailable or its version upgrade is blocked, Liberdus bypasses the cache and continues with the normal download.
  6. The Blob is passed to the existing browser download or React Native DOWNLOAD_ATTACHMENT bridge.

Why

Saving the same image previously repeated the attachment-server request and decryption every time. Persisting the decrypted full image makes later saves faster and lets a cached image be saved when the attachment server is unavailable. Treating blocked database upgrades as cache failures also keeps Save usable during deployments when an older app tab still owns the previous database connection.

Validation

  • node --test tests/issue-1656-full-image-cache.test.mjs tests/popup-select-container.test.mjs
  • node --check app.js
  • git diff --check origin/main...issue-1656-save-image-cache-phase1

Related to #1656

@osyed
osyed merged commit 3e7d750 into main Sep 1, 2026
1 check passed
@dnlbui dnlbui linked an issue Sep 1, 2026 that may be closed by this pull request
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.

Avoid re-downloading attachments

2 participants