Closer/app
null 5151698d56 fix(avatar): harden the cropper's error handling; unify with the codebase
Checking error handling on the crop sheet surfaced three real problems, two of
which I had introduced.

1. Crash on a high-megapixel photo. The picked image was decoded at full size
   and handed to a hardware Canvas. An 8000x8000 photo decodes to 256MB, which
   Android allocates but the canvas refuses to draw ("trying to draw too large
   bitmap") — thrown inside Compose's draw phase, where the runCatching around
   the decode can't see it. Proven live: an 8000x8000 pick killed the app.
   Fixed by subsampling at decode (inSampleSize from a bounds-only pass) so the
   working bitmap is capped at ~2048px / ~16MB. Native heap on that pick went
   256MB(attempted) -> 46MB.

2. The subsample fix then broke decoding for EVERY image. decodeStream returns
   null by design in inJustDecodeBounds mode, and I had `?: return null` on it —
   so loadOriented bailed right after the bounds pass, for all inputs. It only
   looked like "the huge photo failed"; a normal photo would have failed too. I
   never re-tested a small image after the change. The new AvatarCropSheetTest
   caught it. The stream is now what's guarded; the real check is the header size.

3. Errors were swallowed and off-standard. runCatching{}.getOrNull() dropped the
   cause and a failure silently dismissed the sheet — indistinguishable from a
   save that did nothing. Now unified with the screen's own pattern
   (EditProfileViewModel.save): the sheet reports the Throwable up via a new
   onError, the VM records it through the injected CrashReporter and surfaces
   the message through uiState.error -> the existing snackbar. The crop also
   moved off the main thread (withContext(IO)); inline, `saving` flipped within
   one frame and never showed.

Adds AvatarCropSheetTest (androidTest, 4 tests, on-device BitmapFactory/Canvas):
subsample math for 8000+/oversized, oversized decode stays bounded, garbage
returns null instead of throwing, crop output is square and bounded. All green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 23:58:38 -05:00
..
schemas fix: use sex column for Desire Sync question filtering instead of fragile ID pattern 2026-06-18 00:32:39 -05:00
src fix(avatar): harden the cropper's error handling; unify with the codebase 2026-07-14 23:58:38 -05:00
build.gradle.kts feat(avatar): frame a picked photo, and fall back to initials not a heart 2026-07-14 23:19:37 -05:00
proguard-rules.pro feat: settings polish, privacy strings, home partner state, proguard rules 2026-06-21 09:49:02 -05:00