Skip to content

fix: 7 core-interaction bugs (silent send loss, image/speech robustness)#130

Merged
dzianisv merged 1 commit into
mainfrom
fix/core-interaction-bugs
Jul 18, 2026
Merged

fix: 7 core-interaction bugs (silent send loss, image/speech robustness)#130
dzianisv merged 1 commit into
mainfrom
fix/core-interaction-bugs

Conversation

@dzianisv

Copy link
Copy Markdown
Owner

Seven verified correctness bugs from an adversarial review of edit/revert, image attachments, and speech input. All confirmed against the code; typecheck clean, 193 tests pass.

High impact

  1. Send failures silently discarded the message + images with no feedback. sendMessage fire-and-forgot the prompt POST, so handleSend's restore-draft + "Message not sent" alert was dead code. On a flaky network the composer cleared, the optimistic bubble vanished, and the text/photos were gone silently. Now sendMessage awaits submission (fast — /prompt_async resolves before the streamed response) and rethrows, so the draft restores and the user gets an alert.

Image attachments
2. Clipboard-pasted images skipped resize/compression (full-res PNG data URIs → huge payloads). Now routed through toJpeg.
3. Unguarded conversion dropped photos silently; one bad asset in a multi-select discarded the whole batch. Now try/catch + Promise.allSettled + a failure alert.
4. No image-count cap → OOM risk on huge selections. Added selectionLimit: 10.

Speech
5. Recognition was never stopped on unmount — mic stayed hot (privacy indicator on, battery drain). Added an unmount abort().
6. Speech errors (mic-permission-denied, recognition failures) were captured but never shown. Now alerted.

Edit/revert
7. "Undo" after an Edit left the composer prefilled → tapping Send created a duplicate. Undo now clears the composer.

i18n en+zh kept in parity (new imageFailed*/speechError* keys).

🤖 Generated with Claude Code

https://claude.ai/code/session_01T12AhSnQVrSxNnvwfCx2z6

Seven correctness bugs in the session composer:

- sessions.ts sendMessage: await the prompt submission and rethrow on
  failure instead of a fire-and-forget .catch(), so handleSend's existing
  restore-draft-and-alert catch actually runs.
- pasteFromClipboard: route pasted images through toJpeg() so they get
  the same resize/compress treatment as picked/captured photos.
- pickFromLibrary/pickFromCamera: wrap toJpeg() in try/catch (and switch
  to Promise.allSettled for the multi-select batch) so one bad asset
  doesn't silently drop the whole batch; surface a new imageFailed alert.
- pickFromLibrary: cap selection at 10 images.
- useSpeech: abort the native recognition session on unmount so the mic
  doesn't stay hot after leaving the screen.
- Surface useSpeech's error via Alert, keyed on the error value so it
  fires once per distinct error.
- Undo on the revert banner now also clears the composer, since it was
  prefilled by the edit flow and could otherwise be sent as a duplicate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T12AhSnQVrSxNnvwfCx2z6
@dzianisv
dzianisv merged commit 5b47f9e into main Jul 18, 2026
7 checks passed
@dzianisv
dzianisv deleted the fix/core-interaction-bugs branch July 18, 2026 22:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant