Skip to content

fix(mobile): show the files a bot sends — video, audio, documents (MOCA-155) - #2234

Merged
milind-soni merged 4 commits into
mainfrom
fix/moca-155-bot-file-attachments
Oct 3, 2026
Merged

milind-soni merged 4 commits into
mainfrom
fix/moca-155-bot-file-attachments

Conversation

@aivsomkar

@aivsomkar aivsomkar commented Oct 3, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes MOCA-155

Problem

Since #1552 a bot can send any file with attach_file. Documents, audio and video arrive as kind:"file" attachments with a name. Both phones only read image and audio entries, so a reply that carried only a file drew as an empty speech bubble. The roster and Updates line showed nothing for it either.

Change

  • iOS: MessageImageAttachment decodes name, and Message.attachedFiles lists the bot's file attachments (deduplicated, names basenamed). Each one renders as the existing file card, and tapping it opens the full-screen viewer through the message-scoped file route. QuickLook plays mp4/mov video and audio, and shows PDFs and Office documents.
  • Android: the same model change, with name appended so positional callers are unchanged. Each file renders as the shared file card and opens the existing file sheet. The card now uses the bubble's own text colour; it was hard-coded white, which was unreadable on a light bot bubble.
  • Both: video and audio cards get a play or waveform icon and say "Tap to play". A file-only message previews as its file name in the roster and on the Updates line. New strings carry pt-BR (iOS) and Simplified and Traditional Chinese (Android).

Not in this PR

The server side works but has limits worth a separate PR: no HTTP Range requests (long videos download in full before playing), a 25 MB cap, and m4v/mkv are rejected.

Merge note

This PR and the MOCA-191 PR (#2235) both add strings to ios/App/Localizable.xcstrings. Whichever merges second needs that catalog re-merged.

Test plan

  • iOS: swift test passes, 858 tests.
  • iOS: on the iPhone 17 Pro simulator, against a local harness seeded with a bot reply carrying demo-clip.mp4 and weekly-report.pdf, both cards render (screenshot above). Tapping each opened it: the PDF previewed and the video played.
  • Android: :core:test (763 tests) and :app:testDebugUnitTest (1129 tests) pass, and the app compiles.
  • Android: open a bot's video and PDF on a device or emulator (not run)

Platforms

Platform Applies? Status
macOS no n/a: the desktop already renders kind:"file" attachments (AttachmentGallery)
Windows no n/a: no desktop, server or electron change
iOS yes in this PR, tested on the iPhone 17 Pro simulator
Android yes in this PR; unit-tested, NOT run on an emulator
Companion no n/a: uses the existing message-scoped file route

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Chat messages now display attached documents, audio, and video as file cards. Video and audio cards show a play prompt; document cards show a preview prompt.
    • Messages containing only an attachment now use its filename in chat previews.
    • Attachment names are displayed without altering their file paths.

aivsomkar and others added 3 commits October 3, 2026 18:46
…155)

Since #1552 a bot can send any file with attach_file. Documents, audio
and video arrive as kind:"file" attachments with a name; the phone only
read kind:"image" and kind:"audio", so a file-only reply drew as an
empty speech bubble.

MessageImageAttachment now decodes `name`, and Message.attachedFiles
lists a bot's file attachments (deduplicated, names basenamed). Each
renders as the existing file card, which opens the full-screen viewer
through the message-scoped file route: QuickLook plays mp4/mov video
and audio and shows PDFs and Office documents. The card says
"Tap to play" with a play or waveform icon for video and audio. A
file-only message previews in the roster and on the Updates line as
its file name instead of nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…OCA-155)

Port of the iOS change. A bot's attach_file documents, audio and video
arrive as kind:"file" attachments with a name; Android only read image
and audio entries, so a file-only reply drew as an empty bubble.

MessageImageAttachment decodes `name` (appended, so positional callers
are unchanged) and Message.attachedFiles lists the bot's files. Each
renders as the shared file card, now drawn in the bubble's own text
colour (it was hard-coded white, unreadable on a light bot bubble) and
labelled VIDEO or AUDIO with "Tap to play" where it plays. Tapping opens
the existing file sheet through the message-scoped file route. A
file-only message previews as its file name. New strings carry
Simplified and Traditional Chinese.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
openmausbot-docs Ready Ready Preview Oct 3, 2026 6:57pm UTC

Request Review

@coderabbitai

coderabbitai Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c35287f1-ec88-4726-a50d-4a440e2b54f4
📥 Commits

Reviewing files that changed from the base of the PR and between 4c43020 and 1e28ce9.

⛔ Files ignored due to path filters (1)
  • docs/screenshots/moca-155-bot-files-ios.jpg is excluded by !**/*.jpg
📒 Files selected for processing (5)
  • android/app/src/main/kotlin/com/openmausbot/companion/ui/MessageRow.kt
  • android/core/src/main/kotlin/com/openmausbot/companion/core/ChatPreferences.kt
  • ios/App/ChatView.swift
  • ios/App/Localizable.xcstrings
  • ios/Sources/CompanionCore/ChatPreferences.swift
 _________________________________________________
< Keeping your code so clean, you can eat off it. >
 -------------------------------------------------
  \
   \   (\__/)
       (•ㅅ•)
       /   づ

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 850bb574-e334-48d5-b414-e532ee8a8f3e
📥 Commits

Reviewing files that changed from the base of the PR and between 17cc1f9 and 4c43020.

⛔ Files ignored due to path filters (1)
  • docs/screenshots/moca-155-bot-files-ios.jpg is excluded by !**/*.jpg
📒 Files selected for processing (15)
  • android/app/src/main/kotlin/com/openmausbot/companion/ui/MessageRow.kt
  • android/app/src/main/res/values-b+zh+Hans/strings.xml
  • android/app/src/main/res/values-b+zh+Hant/strings.xml
  • android/app/src/main/res/values/strings.xml
  • android/core/src/main/kotlin/com/openmausbot/companion/core/AttachedMessageContent.kt
  • android/core/src/main/kotlin/com/openmausbot/companion/core/ChatPreferences.kt
  • android/core/src/main/kotlin/com/openmausbot/companion/core/Models.kt
  • android/core/src/test/kotlin/com/openmausbot/companion/core/GeneratedImageTest.kt
  • ios/App/AttachmentViews.swift
  • ios/App/ChatView.swift
  • ios/App/Localizable.xcstrings
  • ios/Sources/CompanionCore/AttachedMessageContent.swift
  • ios/Sources/CompanionCore/ChatPreferences.swift
  • ios/Sources/CompanionCore/Models.swift
  • ios/Tests/CompanionCoreTests/GeneratedImageTests.swift

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

Android and iOS now expose file attachments from messages, classify them as video, audio, or documents, and render them as transcript cards. Message previews use the first attached file’s name when no webhook task or nonempty message text is available.

Changes

File attachments

Layer / File(s) Summary
Attachment data and classification
android/core/.../Models.kt, ios/Sources/CompanionCore/Models.swift, android/core/.../AttachedMessageContent.kt, ios/Sources/CompanionCore/AttachedMessageContent.swift, android/core/src/test/.../GeneratedImageTest.kt, ios/Tests/CompanionCoreTests/GeneratedImageTests.swift
Both platforms add an optional attachment name and derive ordered file attachment lists. Blank paths and duplicate paths are excluded. File families are classified from lowercased extensions. Tests cover filtering, name handling, serialization, and family classification.
Transcript attachment cards
android/app/.../MessageRow.kt, ios/App/ChatView.swift, ios/App/AttachmentViews.swift, android/app/src/main/res/values*/strings.xml, ios/App/Localizable.xcstrings
Transcript bubbles render file attachments. Video and audio cards use play labels or icons; document cards retain preview labels. Android adds video and audio labels and a playback prompt, and iOS adds a Brazilian Portuguese playback translation.
Message previews
android/core/.../ChatPreferences.kt, ios/Sources/CompanionCore/ChatPreferences.swift, android/core/src/test/.../GeneratedImageTest.kt, ios/Tests/CompanionCoreTests/GeneratedImageTests.swift
When a text message has no webhook task or nonempty text, its preview uses the first attached file’s name. Tests cover this fallback and text precedence.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix

Suggested reviewers: milind-soni

Merge Risk: ⚪ Minimal · up to 4c430

The attachment changes are mergeable after normal checks; Android video and PDF behavior remains untested on a device or emulator.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 4c430

Bot files become easier to open, but they continue through message-scoped delivery with file containment and private preview controls. No authorization bypass was established. Remaining uncertainty concerns the complete baseline comparison and deployed enforcement, rather than a demonstrated vulnerability.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The newly clickable source is bot-supplied attachment metadata. Its effective file access is bounded by the caller's server access, thread visibility, exact stored message attachment and canonical attachment-root containment. On Android, external applications receive user-selected read grants to cached files, not server credentials or general filesystem authority.

Trust Boundaries and Controls

  • observed — The server rejects requests without resolved authorization, applies hosted-workspace and visibility checks, and finds the requested message within the specified thread. Bot attachment downloads require exact path equality with that message's stored metadata. The resolver checks canonical roots, regular-file status, size and post-open identity before streaming bytes.

Resilience and Maintainability Implications

  • observed — Android cache keys include connection, thread, message and path, and download results are rejected after a computer switch. Preview generations prevent superseded requests from replacing newer files, while dismissal and screen disposal remove owned preview directories. These controls address cross-request identity confusion in the expanded file flow.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 11 files. (4 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: mobile apps now show files sent by bots. It is specific and includes the relevant issue identifier.
Description check ✅ Passed The description explains the problem, changes, and verification, includes a screenshot, and identifies platform coverage. It does not use the template’s exact section headings or include its checklist…
Full details: Docstring Coverage

Explanation

Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 11 files. (4 skipped: 4 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@milind-soni
milind-soni merged commit 40ee88c into main Oct 3, 2026
4 of 6 checks passed

This branch was successfully deployed

1 active deployment
Preview — 1e28ce9d Deployed Oct 3, 2026 by vercel[bot]
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.

2 participants