Turn photos the right way up, and lift the chat off the keyboard

Two reports from a real phone.

**A photo auto-rotated.** BitmapFactory does not apply EXIF orientation,
and every image this app sends is re-encoded to strip EXIF — which is
right, because that block carries the GPS coordinates the shot was taken
at. The same block carries the tag saying which way is up, and a phone
camera rarely writes upright pixels: it writes landscape pixels plus
"turn this 90°". Decoding ignored that, the re-encode dropped the tag,
and the only thing that knew which way was up was gone.

The tag is now read and applied to the pixels before it is discarded, on
all three paths: preparing to send, scrubbing metadata, and rendering an
image received from a peer. The mirrored tags are handled too — a front
camera writes them, and a selfie coming back flipped is the same bug
facing sideways.

🔴 iOS is NOT affected, which is why this survived: UIImage(data:)
applies orientation as it decodes, so the identical strip-and-re-encode
is safe there. Same design, opposite platform default — and the reason
"works fine on iOS" said nothing about Android.

**The keyboard covered what was being typed into.** The manifest has
said windowSoftInputMode="adjustResize" all along, and that stopped
meaning anything at targetSdk 35: Android 15 forces apps targeting it
edge-to-edge, and an edge-to-edge window does not resize for the IME. So
the line has been a no-op on every device this ships to (minSdk 33). The
root now consumes the IME inset with imePadding() — at the root rather
than per screen, because every screen with a text field has this and one
added later would too.

5 new tests, including one that fails if the manifest line ever becomes
the only thing relied on again. 1213 tests green, counted from the
result XML rather than from BUILD SUCCESSFUL.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Paul Hitt
2026-09-08 17:50:37 -04:00
co-authored by Claude Opus 5
parent 04e06452b6
commit 4a8cb64c65
5 changed files with 174 additions and 4 deletions
+4
View File
@@ -184,6 +184,10 @@ dependencies {
// module's classpath would make `:client` unable to change its own
// dependencies without breaking a screen that never mentioned it.
implementation(project(":obfs4"))
// 🔴 BitmapFactory ignores EXIF orientation, so a photo from a phone
// camera decodes on its side. This reads the tag so the rotation can be
// applied before re-encoding drops it. See ImagePrep.orientedFrom.
implementation("androidx.exifinterface:exifinterface:1.3.7")
implementation(platform("androidx.compose:compose-bom:2024.12.01"))
implementation("androidx.compose.material3:material3")
implementation("androidx.compose.material:material-icons-extended")