feat: BlurHash progressive placeholders for profile-picture avatars#515
Merged
Conversation
Carry the thumbnail rendition's BlurHash on ProfilePicture and render it as an instant blurred preview while a counterpart's avatar downloads, instead of a blank gradient. Ported from android code-payments/code-android-app#1131 (lean scope: BlurHash + placeholder; the existing largest-thumbnail selection is kept, avatars are fixed-size). - BlurHash: public-domain decoder + process-wide decode cache (FlipcashUI) - ProfilePicture.thumbnailBlurhash, read off the selected thumbnail rendition - SQLite: persist the blurhash (new column, SQLiteVersion 25 -> 26) - ContactAvatarView renders the blurhash while imageData is nil (precedence: bytes -> blurhash -> monogram) - Threaded through the tip/DM counterpart surfaces (conversation title + profile card, tip conversations list) - Tests: BlurHash decoder vectors; ProfilePicture blurhash extraction + legacy JSON back-compat
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A counterpart's profile-picture avatar currently shows a blank gradient (then a monogram) while its bytes download, then pops to the image. This ports the BlurHash placeholder from android #1131 so the avatar instead shows an instant blurred preview that resolves to the real thumbnail.
Scope is deliberately lean (the iOS side differs from Android): iOS
ProfilePicturecollapses the server's renditions to two blob IDs and avatars are fixed-size, so this keeps the existing "largest thumbnail" selection and adds only the BlurHash. Progressive path is BlurHash → full image (no avatar-view rework, no per-surface size selection). TheImageMetadata.blurhashproto field was already present but unused, and it's available the momentProfilePictureis built from the proto — no extra RPC.What
BlurHash(FlipcashUI/.../Images/BlurHash.swift) — public-domain decoder (decode(_:width:height:punch:) -> UIImage?) plus a process-wideBlurHashCache, ported from the PR'sBlurHash.kt.ProfilePicture.thumbnailBlurhash— read off the same thumbnail rendition already selected;decodeIfPresentfor JSON back-compat.profilePictureThumbnailBlurhashcolumn;SQLiteVersion25 → 26, so the DB rebuilds from server data on next launch).ContactAvatarView— renders the blurhash whileimageDatais nil (precedence: bytes → blurhash → monogram).profilePicture?.thumbnailBlurhash(conversation title + transcript profile card, tip conversations list). Address-book avatars pass nil.Tests
BlurHashTests— decoder vectors (valid decode to size, nil/blank, component-count mismatch, non-positive dims, out-of-alphabet chars).ProfilePictureTests— blurhash extracted from the selected thumbnail; nil when absent; legacy JSON (no field) decodes to nil.Notes / deviations from android #1131
renditionForSize/renditionBelow) — iOS avatars are fixed 44/80/96px and already fetch the largest thumbnail.placeholderMemoryCacheKey; iOS'sData-driven avatar view has no equivalent.