* 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>
Summary:
- The PR removes macOS runtime reads and writes of `logs/config-health.json`, keeps config-health observation in process memory, and adds Swift tests for ignoring and not recreating the retired sidecar.
- PR surface: Other +22. Total +22 across 2 files.
- Reproducibility: yes. Current main still writes `logs/config-health.json` from the macOS config observation path, and the PR body includes before/after terminal output for that same Swift path.
Automerge notes:
- No ClawSweeper repair was needed after automerge opt-in.
Validation:
- ClawSweeper review passed for head 8cbc4e10d3.
- Required merge gates passed before the squash merge.
Prepared head SHA: 8cbc4e10d3
Review: https://github.com/openclaw/openclaw/pull/99039#issuecomment-4864550335
Co-authored-by: momothemage <niuzhengnan@163.com>
Approved-by: momothemage
* 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>
* fix(ios): show gateway errors once as a swipeable animated toast
Gateway connection errors on the Settings > Gateway page appeared twice:
as the app-wide toast and again as an embedded banner section. Remove the
embedded banner (and its now-dead sheet/action helpers) so problems surface
only via the root toast, animate the toast in smoothly from the top, and
support swipe-up to dismiss with re-arm on new problems.
* fix(ios): re-surface gateway toast on repeated problem reports
A swiped-away toast stayed hidden when a retry failed with an identical
problem, because value equality alone produces no observable change. The
model now counts every problem report; a report while hidden re-shows the
toast, and a report while visible shakes it instead of stacking a new one.
* fix(ios): keep reset-onboarding action on the gateway toast and sync i18n inventory
The root toast is now the only gateway problem surface outside covers, so it
must keep the reset-onboarding primary action the removed settings banner had:
auth-token-mismatch problems now show Reset onboarding and run the full
GatewayOnboardingReset flow. Also refreshes the native i18n inventory for the
changed Swift strings.
* fix(ios): preserve gateway problem recovery state
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(ios): back from settings details returns to the originating screen
Detail views reachable from multiple places (gateway, voice, notifications
settings) previously opened by switching to the canonical Settings tab, so
Back landed on the Settings root instead of the screen the user came from.
Phone tabs now push SettingsRoute details on their own NavigationStack via
PhoneTabSettingsHost, the Control hub pushes the gateway detail onto its own
stack, and the Approvals->Notifications shortcut appends instead of replacing
the path (phone and iPad). Global flows (deep links, onboarding, problem
banner, notification dialog) still jump to the canonical Settings tab.
* chore(i18n): sync native app i18n inventory line references
* test(ios): prove settings back navigation
* test(ios): prove settings back navigation
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Adds an `on-exit` cron schedule kind: a job fires once when a watched command/process
exits, via gateway ProcessSupervisor exit watchers. Covers CLI (`--on-exit`/`--on-exit-cwd`),
tool/protocol schema, RPC list-filter, Control UI + macOS read-only display, SQLite
round-trip, and origin-aware wake routing. Restart-safe one-shot (persists completion
before firing); platform-aware shell; bounded watched-command execution.
Squashed from 22 iterative commits for a clean rebase onto current main.