TacTile›Launch TacTile›Android›Android — Tablet support·14 in this wave
Wave

Android — Tablet support

CORRECTED 2026-09-22 — THE "WORSE THAN ZERO" FRAMING IS OBSOLETE. Do not plan from it. The old goal read: "Starting from zero, and worse than zero — the manifest hard-locks portrait orientation, so the app cannot even rotate. 0 of ~53 screens are size-aware. This is a from-scratch initiative, not a tuning pass." THE ORIENTATION LOCK WAS REMOVED IN PR #232 (commit 6ad3c1fa), to iOS PARITY rather than a blanket unlock — Matthew's call, 2026-08-06. Phones stay portrait via a runtime compact-width gate (MainActivity.applyOrientationPosture, COMPACT_WIDTH_DP = 600); tablets and unfolded foldables rotate freely. Three choices there are load-bearing and should not be "simplified": it reads WINDOW width not smallestScreenWidthDp (so a split-screen phone-narrow window locks, matching what the user sees); it uses SCREEN_ORIENTATION_USER not _FULL_SENSOR (so the user's own rotation lock is honoured); and onConfigurationChanged was deliberately NOT overridden, because the activity declares no android:configChanges and is recreated on every configuration change, making onCreate the only live path. Both per-screen audits are done (t_703bf3a8): round 3 over ~53 screens, round 4 over the remaining ~39 — 75 rows, 5 MAJOR, 13 MINOR, 57 PASS. Dashboard, Assets and Settings are adapted AND measured. THE REAL SUBJECT OF THIS WAVE NOW IS GUARD COVERAGE, not adaptation. ContentWidth's kdoc documents THREE ways to get a width cap wrong, and they are not equally catchable: · shape 1 — fillMaxSize() with the widthIn left in place, so the cap never applies; · shape 2 — a correct cap that is not centred; · shape 3 — a CORRECT cap with the page background painted INSIDE it. Bounds assertions provably cannot see this one; verified by a mutation that leaves the whole JVM suite green. Shape 3 is now catchable, and the ceiling recorded in earlier rounds is GONE: PR #308 (merged fb047ce9) added app/src/androidTest/.../ContentWidthPaintTest, which renders on a real device, calls captureToImage() and asserts the left margin carries the grouped background colour. WHAT REMAINS: extend the bounds assertions (and, where it matters, the paint assertion) to the screens still unmeasured — Analytics (t_a6987e98), the destination creation flow (t_7fa318f2), the QR editor (t_25a6ca4d), the AI agent screen (t_1cdd2afa) — plus the MINOR rows in t_aa3a8453 listed with file:line in docs/proposals/android-tablet-adaptation.md §"Still open". TWO TRAPS THAT COST REAL TIME, both now in apps/android/AGENTS.md: the paint tier runs under com.tactile.app.HiltTestRunner (the real @HiltAndroidApp Application never finishes starting on a device, and Gradle reports that only as "Process crashed"); and espresso-core must stay pinned to 3.7.0, because the version compose-ui-test-junit4 pulls calls InputManager.getInstance, removed in API 35+. RUNNING THE PAINT TIER IS NOT AUTOMATED and green-by-omission is the failure mode: at a stock 411dp the 600dp cap never engages, so the test assumes its way out and `./gradlew :app:connectedDebugAndroidTest` exits 0 with skipped=1. Use scripts/android/run-paint-tier.sh (PR #320), which sets density 160, resets it in a trap, and fails on zero-tests / any-skip. Whether it becomes a REQUIRED gate is Matthew's spend decision — t_7dff6480, recommendation (a) leave it developer-run until the Actions billing question is settled; do NOT wire it into gate.sh, which would make an emulator a prerequisite for every TypeScript change in the monorepo.

TacTile › Launch TacTile › Android › Android — Tablet support
12/14 done2 open1 open blocker
Selected taskclear

Adapt QR editor for tablet

DoneOwner · Vivt_25a6ca4d
Show the prompt
To doIn progressDoneBlockedPick a wave on the left · tap a task to expand it