Commit Graph

4 Commits

Author SHA1 Message Date
Peter Steinberger
b978dcc63b feat(ios): record and send voice notes from the chat composer (#100946)
* feat(ios): record and send voice notes from the chat composer

Adds tap-to-record voice notes to the shared chat composer: m4a/AAC mono
capture with a 3-minute cap, lazy mic permission, cancel/finish controls,
audio attachment chips with duration, and a voice-note transcript row.
Voice-wake suppression becomes reason-scoped so recording and Talk cannot
clobber each other. Attachments stay online-only per the outbox contract.

Related: #100709

* fix(ios): harden voice note attachment staging

* chore(ios): keep voice note changelog release-owned

* fix(ios): gate voice notes with attachment availability

* chore(ios): refresh native localization inventory
2026-07-07 00:14:05 +01:00
Peter Steinberger
06789ca4c2 fix(ios): keep offline chat sends on their original route (#100942) 2026-07-06 17:53:05 +01:00
Peter Steinberger
4b7661e9a0 feat(ios): durable offline command outbox for chat sends (#100331)
* feat(ios): durable offline command outbox for chat sends

Text messages sent while the gateway is unreachable queue in a durable
per-gateway outbox (new outbox_commands table in the per-gateway chat
cache SQLite store, schema v2) instead of failing. Queued bubbles render
with visible Queued/Sending/Not sent states and flush strictly in
createdAt order once transport health recovers; each command's client
UUID rides as the send idempotency key, so at-least-once delivery plus
gateway dedupe keeps the transcript exact.

Contract summary:
- Bounds: 50 queued commands per gateway; refused enqueues keep the
  draft. Queued rows older than 48h expire to failed("expired") rather
  than silently sending stale commands; tap-to-retry refreshes
  createdAt so an expired row can resend as new intent.
- Failure taxonomy: transport-level failures keep rows queued without
  burning retry attempts (backoff ladder, then health drops so the
  reconnect machinery owns pacing); gateway rejections burn attempts
  and fail terminally after 3, with context-menu retry/delete.
- Deletes are tombstoned synchronously and rechecked after the claim
  await so an active flush can never send a removed command; Delete is
  hidden while a bubble is already in flight; offline enqueue is
  guarded against double submit during the health probe.
- Post-reconnect live sends route behind draining outbox rows (FIFO),
  and a cold open assumes a backlog until restore adopts durable rows.
- Crash safety: 'sending' rows revert to 'queued' at startup; flushed
  turns are spliced into the session's cached transcript before their
  outbox row is deleted, and stale history snapshots cannot evict a
  just-flushed turn until a snapshot confirms it.
- Per-gateway scoping and purge ride the transcript cache: one SQLite
  file per gateway; reset/forget drops the queue with the cache.
  Fixture/unpaired transports get no outbox.

Part of #46664

* chore(ios): sync native i18n inventory

* style(chat-ui): satisfy strict SwiftFormat lint (doc comment, scope blank line)
2026-07-06 05:23:46 +01:00
Peter Steinberger
5d8293c1fe feat(ios): read-only offline cache for chat sessions and transcripts (#100219)
* feat(ios): read-only offline cache for chat sessions and transcripts

Cache-first cold open for the iOS chat tab: the last known transcript and
session list render immediately from a local SQLite cache, then live gateway
history replaces them wholesale through the existing reconciliation path.
When the gateway is unreachable, recent sessions and transcripts stay
browsable read-only; sending remains gated by the existing connection state.

- New OpenClawChatTranscriptCache protocol seam plus SQLite-backed store in
  OpenClawChatUI (raw SQLite3, no new dependencies), scoped per gateway
  stableID so transcripts never leak across paired gateways.
- Bounds: 50 sessions, 50 transcripts, 200 messages per session; text rows
  only (attachment/binary payloads and tool arguments are stripped).
- Disposable cache: schema versioned via user_version; any open/schema/decode
  mismatch drops and rebuilds silently. File protection
  completeUntilFirstUserAuthentication on iOS.
- View model pre-paints from cache only until a live response applies
  (hasAppliedLiveHistory/hasAppliedLiveSessions guards); write-through is
  chained and off the render path.
- iOS wiring keys the chat view model identity on transport mode plus cache
  gateway ID so switching paired gateways rebuilds the view model.

Part of #100194

* fix(ios): harden offline transcript cache

* fix(ios): expose offline cached sessions

* fix(ios): isolate transcript caches by gateway

* chore(i18n): sync native inventory

* fix(ios): allow cache extension to replace messages
2026-07-06 01:02:15 +01:00