Skip to content

Disambiguate composer attachment remove buttons for TalkBack#6433

Open
andremion wants to merge 2 commits into
developfrom
fix/composer-remove-attachment-a11y
Open

Disambiguate composer attachment remove buttons for TalkBack#6433
andremion wants to merge 2 commits into
developfrom
fix/composer-remove-attachment-a11y

Conversation

@andremion
Copy link
Copy Markdown
Contributor

@andremion andremion commented May 11, 2026

Goal

Resolve Accessibility issue 88 — Attachment Picker

The (x) remove button on each queued attachment in the Compose composer is announced as the same generic "Remove attachment" for every item. With multiple attachments queued, TalkBack users could not tell the remove buttons apart and had no way to confirm which attachment they were about to delete.

Implementation

Replace the single R.string.stream_compose_remove_attachment with per-type, name-aware labels resolved locally inside each composer attachment item:

  • Photos / videos (MessageComposerAttachmentMediaItem) — "Remove photo IMG_0023" / "Remove video clip.mp4", falling back to "Remove photo" / "Remove video" when the attachment exposes no title or name. Type comes from attachment.type == AttachmentType.VIDEO.
  • Other files (MessageComposerAttachmentFileItem) — "Remove file report.pdf", falling back to "Remove file".
  • Voice recordings (MessageComposerAttachmentAudioRecordItem) — "Remove voice message" (recordings have no useful filename to surface).

Display name follows the codebase's standard pick attachment.title ?: attachment.name. The new string resources are added with translations for all 7 supported locales (es, fr, hi, in, it, ja, ko). The previously generic stream_compose_remove_attachment resource has no remaining callers and is dropped from all locales — same cleanup pattern as #6404, which removed stream_compose_attachments after the picker-button a11y refactor.

No public API surface changes (these composables are routed through ChatTheme.componentFactory.MessageComposerAttachment{File,Media,AudioRecord}Item and apiDump produces no diff).

Testing

Manual steps on the Compose sample with TalkBack enabled:

  1. Open a 1:1 channel and tap the attachments button.
  2. Pick two photos with distinct filenames (e.g. from the device gallery). Wait for them to appear in the composer tray.
  3. Swipe through the tray with TalkBack. Each (x) button should announce as "Remove photo <filename>" — the two announcements must differ.
  4. Pick a video instead and confirm "Remove video <filename>".
  5. Switch to the Files tab in the picker, pick a PDF, and confirm "Remove file <filename>".
  6. Record a voice message (hold-to-record). The remove (x) should announce as "Remove voice message".
  7. Repeat steps 2–6 with the device language set to one of: Spanish, French, Hindi, Indonesian, Italian, Japanese, Korean — labels should be translated.
  8. Edge case: if you have a way to inject an attachment with no title and no name (e.g. via a custom MessageComposerController plug-in), confirm the fallback "Remove photo" / "Remove video" / "Remove file" is announced.

Summary by CodeRabbit

Release Notes

  • Improvements
    • Enhanced accessibility descriptions for removing attachments with type-specific labels (photo, video, file, voice message).
    • Updated attachment removal labels to include the attachment name when available.
    • Improved localization support across multiple languages with context-aware messaging.

Review Change Stack

The (x) remove button on each queued attachment in the Compose composer
announced as "Remove attachment" for every item, so TalkBack users could
not distinguish between multiple remove buttons. Replace the single
contentDescription with per-type, name-aware labels:

- Photos / videos: "Remove photo IMG_0023" / "Remove video clip.mp4"
  (fallback "Remove photo" / "Remove video" when the attachment has no
  title or name)
- Other files: "Remove file report.pdf" (fallback "Remove file")
- Voice recordings: "Remove voice message"

Adds matching translations for the 7 supported locales. The previously
generic stream_compose_remove_attachment resource has no remaining
callers and is dropped from all locales, mirroring the cleanup done in
PR #6404 for stream_compose_attachments.
@andremion andremion requested a review from a team as a code owner May 11, 2026 12:49
@andremion andremion added the pr:improvement Improvement label May 11, 2026
@andremion
Copy link
Copy Markdown
Contributor Author

@CodeRabbit review

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 11, 2026

PR checklist ✅

All required conditions are satisfied:

  • Title length is OK (or ignored by label).
  • At least one pr: label exists.
  • Sections ### Goal, ### Implementation, and ### Testing are filled (or ignored for dependabot PRs).

🎉 Great job! This PR is ready for review.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 11, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 11, 2026

Walkthrough

Attachment removal actions now display context-specific accessibility descriptions. Voice messages use a dedicated label, file and media attachments use helper functions that choose between generic and named descriptions based on attachment metadata, and string resources are updated across English and seven localized variants.

Changes

Attachment Removal Accessibility Descriptions

Layer / File(s) Summary
Voice Message Accessibility
MessageComposerAttachmentAudioRecordItem.kt
Voice message removal uses stream_compose_remove_attachment_voice_message instead of the generic attachment removal string.
File Attachment Helper
MessageComposerAttachmentFileItem.kt
New fileAttachmentRemoveDescription() helper function selects between generic and named file removal strings based on the attachment's title/name field.
Media Attachment Helper
MessageComposerAttachmentMediaItem.kt
New mediaAttachmentRemoveDescription() helper function returns photo or video removal descriptions, choosing between generic and named variants depending on whether title/name is present.
Default String Resources
src/main/res/values/strings.xml
Generic stream_compose_remove_attachment string is replaced with type-specific strings: stream_compose_remove_attachment_photo, stream_compose_remove_attachment_photo_named, stream_compose_remove_attachment_video, stream_compose_remove_attachment_video_named, stream_compose_remove_attachment_file, stream_compose_remove_attachment_file_named, and stream_compose_remove_attachment_voice_message.
Localized Strings
src/main/res/values-*/strings.xml (es, fr, hi, in, it, ja, ko)
Type-specific attachment removal strings are translated across all supported locales, with each locale either removing and replacing the generic string or adding new type-specific variants.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

Suggested reviewers

  • gpunto

Poem

🐰 Hop along, dear attachment,
Your goodbye's now more specific—
No more generic farewells,
Photos, files, and voices distinct!
Accessibility hops forward. 🎙️📎

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and clearly describes the main change: making TalkBack announcements for composer attachment remove buttons more specific and distinguishable by including attachment type and name.
Description check ✅ Passed The description comprehensively covers all required sections: Goal (accessibility issue context), Implementation (detailed per-type label strategy and string resource changes), Testing (extensive manual TalkBack verification steps for all attachment types and locales), and includes checklists.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/composer-remove-attachment-a11y

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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@stream-chat-android-compose/src/main/res/values-ja/strings.xml`:
- Around line 240-246: The Japanese strings.xml still contains the deprecated
generic resource stream_compose_remove_attachment which was removed from other
locales; delete the <string name="stream_compose_remove_attachment"> entry from
this file so the locale matches others, and verify there are no remaining
references to stream_compose_remove_attachment in code or other resource files
(if found, update them to use the corresponding specific keys like
stream_compose_remove_attachment_photo/video/file/voice_message or remove the
references).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 68b9ab51-a35c-432c-83dc-4a95140bbefa

📥 Commits

Reviewing files that changed from the base of the PR and between 8891e22 and 31c1d17.

📒 Files selected for processing (11)
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/composer/internal/attachments/MessageComposerAttachmentAudioRecordItem.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/composer/internal/attachments/MessageComposerAttachmentFileItem.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/composer/internal/attachments/MessageComposerAttachmentMediaItem.kt
  • stream-chat-android-compose/src/main/res/values-es/strings.xml
  • stream-chat-android-compose/src/main/res/values-fr/strings.xml
  • stream-chat-android-compose/src/main/res/values-hi/strings.xml
  • stream-chat-android-compose/src/main/res/values-in/strings.xml
  • stream-chat-android-compose/src/main/res/values-it/strings.xml
  • stream-chat-android-compose/src/main/res/values-ja/strings.xml
  • stream-chat-android-compose/src/main/res/values-ko/strings.xml
  • stream-chat-android-compose/src/main/res/values/strings.xml

Comment thread stream-chat-android-compose/src/main/res/values-ja/strings.xml
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 11, 2026

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 5.82 MB 5.82 MB 0.00 MB 🟢
stream-chat-android-ui-components 11.02 MB 11.02 MB 0.00 MB 🟢
stream-chat-android-compose 12.39 MB 12.39 MB 0.01 MB 🟢

Add three Paparazzi snapshot tests rendering each composer attachment
item (image, video, file) with a copy of the existing preview data that
clears the title and name, exercising the previously uncovered fallback
arms of fileAttachmentRemoveDescription and mediaAttachmentRemoveDescription.
Extract a shared MessageComposerAttachmentItem helper to dedupe the
preview-handler wiring across the four media-item previews.
@andremion andremion enabled auto-merge (squash) May 11, 2026 13:46
@sonarqubecloud
Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:improvement Improvement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant