Skip to content

Add TalkBack accessibility support for links in chat messages#110

Closed
Copilot wants to merge 8 commits intomainfrom
copilot/fix-chat-links-accessibility
Closed

Add TalkBack accessibility support for links in chat messages#110
Copilot wants to merge 8 commits intomainfrom
copilot/fix-chat-links-accessibility

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Feb 11, 2026

  • Diagnose: AccessibilityDelegateCompat was only set when isTouchExplorationEnabled() returned true at bind time (timing bug), and did not reliably produce an "Actions" submenu in TalkBack on Android 14+
  • Replace with ViewCompat.addAccessibilityAction() — the modern, guaranteed API that TalkBack always shows under "Actions"
  • Track action IDs in a List<Integer> per view and call ViewCompat.removeAccessibilityAction() on rebind to clear stale entries
  • Remove isTouchExplorationEnabled() guard (not needed — registration is unconditional)
  • Delete LinkAccessibilityDelegate.java (no longer needed)
Original prompt

This section details on the original issue you should resolve

<issue_title>[Accessibility] Chat links are not available for Talkback</issue_title>
<issue_description>- Android version: 16

  • Talkback version: 16.2

  • Expected behavior:
    When a message element is focused and activated via a double-tap, the link within it should be triggered.

    However, since a message may contain multiple links, providing distinct child elements for each link is the preferred approach to ensure clarity and precise selection.

    Alternatively, instead of child elements, the message object should implement Custom Actions. These actions allow TalkBack to perform specific functions on the current object and are accessible via the TalkBack menu or the Reading controls menu.

  • Actual behavior:
    The message element does not respond to the activation gesture (double-tap), and no Custom Actions are available for the URLs within the message.

  • Steps to reproduce the problem:

    1. Open any chat.
    2. Locate or send a message containing one or more URLs.
    3. Move the TalkBack focus to the message element.
    4. Attempt to double-tap to activate the link.
    5. Open TalkBack menu (L-swipe or multi-finger tap) and check for Actions.
      </issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 4 commits February 11, 2026 23:11
- Created LinkAccessibilityDelegate to expose links as custom actions
- Updated ConversationItem to use delegate when TalkBack is enabled
- Each link becomes a separate accessible action with clear label

Co-authored-by: adbenitez <24558636+adbenitez@users.noreply.github.com>
- Added accessibility_link_action string resource
- Updated LinkAccessibilityDelegate to accept Context and use resource
- Updated ConversationItem to pass context to delegate

Co-authored-by: adbenitez <24558636+adbenitez@users.noreply.github.com>
- Reuse LinkAccessibilityDelegate instance instead of creating new one each time
- Add detailed comment explaining the magic number for action IDs
- Improves performance by avoiding unnecessary object allocations

Co-authored-by: adbenitez <24558636+adbenitez@users.noreply.github.com>
- Explain why accessibility delegate is not set during batch selection
- Explain why map is cleared and rebuilt on each accessibility update
- Improves code maintainability and readability

Co-authored-by: adbenitez <24558636+adbenitez@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix chat links not available for Talkback users Add TalkBack accessibility support for links in chat messages Feb 11, 2026
Copilot AI requested a review from adbenitez February 11, 2026 23:20
@pvagner
Copy link
Copy Markdown

pvagner commented Mar 31, 2026

@adbenitez
Huge thanks for working on this. I haven't yet tested it but it looks good to me from reading the code.

I have a few little suggestions though:

  • Reconsider changing the string for the accessibility action names please to make it less verbose.
    Currently it says
    Open link: %1$s
    
    The %1$s placeholder will contain the URL most of the times thus it'll be obvious it's a link. Therefore let's change it to:
    %1$s Link
    
  • Consider renaming the AccessibilityDelegate class to something else like MessageViewDelegate and consider adding other accessibility actions as needed.
    For example there is an ability to start a reply on swipe. This is a feature that's used frequently and it's difficult to perform with talkback running. As a workaround we can tap and hold the item, then press three dots menu and then the reply in the popup menu. Having the reply exposed as another accessibility action would be welcome enhancement.

Huge thanks for such dedication and preserving screen reader accessibility during Arcanechat and deltachat development.

@adbenitez
Copy link
Copy Markdown
Collaborator

hi @pvagner thanks a lot for the feedback, about other actions: one step at a time, this will be about solving the specific issue of links, once that is in place then it should be easier to add other actions, we should have a dedicated issue for that one and make then a fix for that other problem (thanks for bringing it up btw! your feedback is very usefull)

bodyText has importantForAccessibility="no" in the XML layout, so
TalkBack focuses the parent ConversationItem. The delegate must be
set on `this` and must read spans from a bodyText reference, not
from the view it's attached to.

Agent-Logs-Url: https://github.com/ArcaneChat/android/sessions/598a695d-a5cd-4948-85e9-edce5e10c67c

Co-authored-by: adbenitez <24558636+adbenitez@users.noreply.github.com>
…mpat

The previous code used View.AccessibilityDelegate (raw framework) and
AccessibilityNodeInfoCompat.wrap() which is deprecated and does not
reliably propagate addAction() to the real AccessibilityNodeInfo that
TalkBack reads.

Switch to AccessibilityDelegateCompat (AndroidX) set via
ViewCompat.setAccessibilityDelegate(). Its onInitializeAccessibilityNodeInfo
callback receives a properly-backed AccessibilityNodeInfoCompat so
info.addAction() reliably surfaces custom actions in the TalkBack
context menu (L-gesture) on all Android versions including API 36.

Also clear the delegate in the CALL/empty-text branch to prevent a
stale delegate remaining on a recycled view.

Agent-Logs-Url: https://github.com/ArcaneChat/android/sessions/87aa7735-a87e-473d-b80c-67e697cd4fa7

Co-authored-by: adbenitez <24558636+adbenitez@users.noreply.github.com>
…ction for link actions

The previous AccessibilityDelegateCompat approach had two fatal flaws:
1. The delegate was only set when isTouchExplorationEnabled() returned
   true AT BIND TIME — a timing bug that caused TalkBack to see no
   actions if the view was bound before TalkBack fully initialised.
2. Even when set, the delegate/custom-action-ID approach did not
   reliably produce an "Actions" submenu in the TalkBack local context
   menu on Android 14+.

Replace the entire mechanism with ViewCompat.addAccessibilityAction(),
the modern API (androidx.core 1.5.0+) that TalkBack always surfaces
under "Actions". Actions are registered unconditionally at bind time;
stale actions from recycled views are removed via
ViewCompat.removeAccessibilityAction() before re-registration.

Delete the now-unused LinkAccessibilityDelegate class.

Agent-Logs-Url: https://github.com/ArcaneChat/android/sessions/95854760-c8e5-43d8-b7b4-55879a7c5dea

Co-authored-by: adbenitez <24558636+adbenitez@users.noreply.github.com>
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.

[Accessibility] Chat links are not available for Talkback

3 participants