* fix: clean up Android camera clips on cancellation
* fix(android): own camera clip cleanup lifecycle
---------
Co-authored-by: NianJiuZst <180004567+users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(android): strip ws scheme prefix from manual gateway host input
Reject bare ws:// in the Host field and normalize pasted ws:// LAN URLs
so manual onboarding resolves the real hostname instead of host ws.
Fixes#87216.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(android): preserve complete manual gateway endpoints
* fix(android): preserve gateway i18n inventory
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(android): ignore chat events with missing assistant role in voice text extraction
Voice chat event parsing now rejects messages without an explicit assistant role,
matching ChatController fail-closed behavior and preventing accidental TTS playback.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(android): require canonical assistant role for voice events
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(android): distinguish gateway auth-recovery reasons instead of one generic label
gatewaySummary()/gatewayStatusLabel() collapsed every auth failure (expired
setup QR, missing/invalid token, missing/invalid password, stale device
identity) into "Authentication needed", discarding the already-computed
MainViewModel.gatewayConnectionProblem signal consumed elsewhere in the app
(OnboardingFlow's recoveryGatewayAuthDetail). Thread it into both status
labels via a shared gatewayAuthNeededSummary() helper so the Overview and
Settings screens tell the user which recovery action applies.
Fixes#98046
* test(android): lock gateway auth-needed labels to the real unauthorized message format
Verified against src/gateway/server/ws-connection/auth-messages.ts:
formatGatewayAuthFailureMessage always returns strings starting with
"unauthorized", which contains the "auth" substring the status-text gate
checks for. Add tests using the exact real-world message text (not just
synthetic "auth failed" strings) so this stays regression-locked.
* fix(android): widen the auth-needed status gate to cover device-identity failures
CONTROL_UI_DEVICE_IDENTITY_REQUIRED/DEVICE_IDENTITY_REQUIRED real gateway
messages ("device identity required", "control ui requires device
identity...") don't contain "auth", so the status.contains("auth") gate
never reached their specific label. Add "device identity" as an additional
substring the gate checks for those two codes, with regression tests using
the exact real message text (message-handler.ts).
Verified via GitHub-style codex review round 2 (round 1's "unauthorized
doesn't contain auth" claim was checked against source and rejected as
false — "unauthorized" does contain "auth" — but this second, narrower
finding about device-identity codes held up under the same source check).
* fix(android): centralize gateway auth status labels
* fix(android): correlate gateway connection diagnostics
* chore(android): align native i18n inventory after rebase
* fix(android): preserve retryable pairing guidance
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix: release Android camera snap use case
* fix(android): release one-shot camera capture promptly
---------
Co-authored-by: NianJiuZst <180004567+users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* chore(release): close out 2026.6.10 on main
* chore(release): align native app metadata for 2026.6.10
* chore(release): sync Android 2026.6.10 notes
* docs(changelog): preserve 2026.6.9 history
* docs(changelog): preserve 2026.6.9 history
Restores Android CI to a publicly installable SDK platform and keeps Gradle compileSdk aligned with the workflow install/cache key. Rolls back the API-37-only AndroidX core slice until Android 37 is available to hosted CI, while preserving the unrelated Kotlin dependency bump.
Verification:
- Google SDK repository index check: android-36 exists; android-37/android-37.0 do not.
- git diff --check
- Testbox changed gate: tbx_01kvs3r1bc925pxya94zey23c8
- PR CI: 68 successful, 12 skipped, 0 failing, 0 pending; Android build/play and both Android unit-test lanes passed.