|
| 1 | +# Android Question Chat polish pass v3 report |
| 2 | + |
| 3 | +## Scope completed |
| 4 | + |
| 5 | +Completed on the current branch after inspecting the interrupted diff first and keeping only the useful production/test work: |
| 6 | +- While generating, the composer action now swaps in-place from Send/Steer to a Stop icon button in the same circular slot, with accessible label `Stop` and no separate Stop button. |
| 7 | +- The chat transcript is now a bounded weighted `LazyColumn` history above a bottom composer, with one production IME inset ownership path on the composer. |
| 8 | +- Starter answers are now compact visual pills with preserved button semantics and 48dp minimum interactive height. |
| 9 | +- The Question action row now uses web-matching copy and hierarchy: `Submit` + icon and `Add note` + icon on one responsive row, with `Cancel` below. |
| 10 | +- Added focused Compose/instrumentation coverage for: |
| 11 | + - send/stop action swapping in one slot |
| 12 | + - compact starter semantics vs visual size |
| 13 | + - one-row Submit/Add note copy and layout |
| 14 | + - bounded real-IME probe/geometry seam with bounded skip instead of hanging the emulator |
| 15 | +- Preserved the useful screenshot/evidence harness, removed the unused `TestComposeImeActivity` / androidTest manifest experiment, and kept the minimal debug host activity actually used by the committed instrumentation. |
| 16 | + |
| 17 | +## Library rationale |
| 18 | + |
| 19 | +Researched maintained chat UI kits before editing. |
| 20 | + |
| 21 | +Not adopted: |
| 22 | +- GetStream `stream-chat-android-ai-compose` / `ChatComposer` |
| 23 | + |
| 24 | +Reason: |
| 25 | +- it is maintained and does cover keyboard/composer/chat concerns, |
| 26 | +- but it pulls in Stream-specific licensing/ecosystem assumptions plus attachment/voice/message abstractions and a visual/state model this app would mostly override, |
| 27 | +- while backend-neutral maintained Compose chat kits remain sparse for this narrow app-owned Question Chat. |
| 28 | + |
| 29 | +Decision: |
| 30 | +- keep the app-owned UI, |
| 31 | +- use the standard bounded `LazyColumn` + anchored composer pattern from current Compose inset guidance, |
| 32 | +- preserve the existing deep owner / safe renderer architecture. |
| 33 | + |
| 34 | +Compose insets reference consulted before editing: |
| 35 | +- fetched Compose inset-consumption guidance under `/tmp/rpiv-fetch-S93HR6/content.txt` (nested `imePadding` / inset consumption behavior) |
| 36 | +- accepted workspace contract in `docs/prototypes/2026-07-29-android-question-chat-workspace.md` |
| 37 | +- current interrupted task brief in `/tmp/android-chat-polish3.md` |
| 38 | +- rereview findings in `/tmp/android-chat-t1-rereview-report.md` |
| 39 | + |
| 40 | +## Diff inspection performed first |
| 41 | + |
| 42 | +Inspected the full interrupted working tree before changing anything: |
| 43 | +- `git status --short` |
| 44 | +- `git diff --stat` |
| 45 | +- full diffs for all modified tracked files |
| 46 | +- contents of the new androidTest/debug harness files |
| 47 | +- current production/test files and the web action row source |
| 48 | + |
| 49 | +## Changed files |
| 50 | + |
| 51 | +Production: |
| 52 | +- `apps/android/app/src/main/java/dev/pi/postbox/question/QuestionChatUi.kt` |
| 53 | +- `apps/android/app/src/main/java/dev/pi/postbox/question/QuestionWorkflowScreen.kt` |
| 54 | +- `apps/android/app/src/main/java/dev/pi/postbox/ui/theme/PostalDecorations.kt` |
| 55 | + |
| 56 | +Compose/instrumentation tests: |
| 57 | +- `apps/android/app/src/androidTest/java/dev/pi/postbox/question/QuestionChatUiTest.kt` |
| 58 | +- `apps/android/app/src/androidTest/java/dev/pi/postbox/question/QuestionWorkflowScreenTest.kt` |
| 59 | +- `apps/android/app/src/androidTest/java/dev/pi/postbox/question/QuestionChatImeGeometryTest.kt` |
| 60 | +- `apps/android/app/src/androidTest/java/dev/pi/postbox/question/QuestionChatEvidenceCaptureTest.kt` |
| 61 | +- `apps/android/app/src/debug/AndroidManifest.xml` |
| 62 | +- `apps/android/app/src/debug/java/dev/pi/postbox/question/QuestionTestHostActivity.kt` |
| 63 | + |
| 64 | +Docs: |
| 65 | +- `IMPLEMENTATION_REPORT.md` |
| 66 | + |
| 67 | +## Evidence |
| 68 | + |
| 69 | +Evidence directory: |
| 70 | +- `/tmp/android-chat-ui-evidence-v3/` |
| 71 | + |
| 72 | +Captured after screenshots: |
| 73 | +- `after-idle-composer.png` |
| 74 | +- `after-generating-stop-composer.png` |
| 75 | +- `after-starter-pills.png` |
| 76 | +- `after-question-action-row.png` |
| 77 | + |
| 78 | +Retained before screenshots: |
| 79 | +- `before-idle-composer.png` |
| 80 | +- `before-generating-stop-composer.png` |
| 81 | +- `before-starter-pills.png` |
| 82 | +- `before-question-action-row.png` |
| 83 | +- `before-keyboard-visible.png` |
| 84 | + |
| 85 | +Important IME note: |
| 86 | +- The committed `QuestionChatImeGeometryTest` performs a bounded real-IME probe on `emulator-5554` and skips instead of hanging when this API-26 headless emulator never surfaces a software keyboard. |
| 87 | +- I did **not** fabricate an `after-keyboard-visible.png` screenshot on this runner. |
| 88 | +- See `/tmp/android-chat-ui-evidence-v3/NOTES.md`. |
| 89 | + |
| 90 | +## Commands run |
| 91 | + |
| 92 | +Environment / repo inspection: |
| 93 | +- `env | sort | grep '^PI_'` |
| 94 | +- `git status --short` |
| 95 | +- `git diff --stat` |
| 96 | +- full `git diff ...` over the interrupted file set |
| 97 | +- `read`, `grep`, `find`, `ls` |
| 98 | + |
| 99 | +Focused verification: |
| 100 | +- `cd apps/android && ./gradlew testDebugUnitTest --tests 'dev.pi.postbox.question.QuestionWorkflowQuestionChatTest' --tests 'dev.pi.postbox.questionchat.QuestionChatWorkspaceShellTest'` |
| 101 | +- `cd apps/android && ./gradlew connectedDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class='dev.pi.postbox.question.QuestionChatUiTest,dev.pi.postbox.question.QuestionWorkflowScreenTest,dev.pi.postbox.question.QuestionChatImeGeometryTest'` |
| 102 | + |
| 103 | +Evidence capture: |
| 104 | +- `cd apps/android && ./gradlew installDebug installDebugAndroidTest` |
| 105 | +- `adb -s emulator-5554 shell am instrument -w -e class dev.pi.postbox.question.QuestionChatEvidenceCaptureTest -e prefix after dev.pi.postbox.test/androidx.test.runner.AndroidJUnitRunner` |
| 106 | +- `adb -s emulator-5554 exec-out run-as dev.pi.postbox cat /data/user/0/dev.pi.postbox/files/android-chat-ui-evidence-v3/<file> > /tmp/android-chat-ui-evidence-v3/<file>` |
| 107 | + |
| 108 | +Emulator recovery / bounded retry work: |
| 109 | +- restarted the API-26 emulator with bounded waits after System UI ANR loops during IME experiments: |
| 110 | + - `/home/dev/Android/Sdk/emulator/emulator @postbox_api26_tcg -no-window -no-snapshot-load -no-snapshot-save -gpu swiftshader_indirect -accel off` |
| 111 | + |
| 112 | +Final Android gates: |
| 113 | +- `cd apps/android && ./gradlew testDebugUnitTest connectedDebugAndroidTest lintDebug assembleDebug assembleDebugAndroidTest` |
| 114 | + |
| 115 | +Diff hygiene: |
| 116 | +- `git diff --check` |
| 117 | + |
| 118 | +## Validation status |
| 119 | + |
| 120 | +Passed: |
| 121 | +- focused JVM tests for `QuestionWorkflowQuestionChatTest` and `QuestionChatWorkspaceShellTest` |
| 122 | +- focused connected tests for `QuestionChatUiTest` and `QuestionWorkflowScreenTest` |
| 123 | +- full Android gates: |
| 124 | + - `testDebugUnitTest` |
| 125 | + - `connectedDebugAndroidTest` |
| 126 | + - `lintDebug` |
| 127 | + - `assembleDebug` |
| 128 | + - `assembleDebugAndroidTest` |
| 129 | + |
| 130 | +Skipped by design after bounded probing: |
| 131 | +- `QuestionChatImeGeometryTest` |
| 132 | +- `QuestionChatEvidenceCaptureTest` cases in the default full suite (they require explicit evidence prefix) |
| 133 | + |
| 134 | +## Residual notes |
| 135 | + |
| 136 | +- The API-26 headless emulator on this runner never surfaced a real IME under bounded automation, even after switching soft keyboards and restarting the emulator without snapshots. The committed IME probe now skips rather than hanging the suite or fabricating proof. |
| 137 | +- `LocalClipboardManager` deprecation warnings remain outside this polish slice. |
| 138 | +- No push performed. |
| 139 | +- No PR opened. |
0 commit comments