Skip to content

Add dynamic accessibility labels to app-list Internet toggle (#231)#625

Merged
kasnder merged 2 commits into
masterfrom
claude/a11y-toggle-labels-231
Jul 11, 2026
Merged

Add dynamic accessibility labels to app-list Internet toggle (#231)#625
kasnder merged 2 commits into
masterfrom
claude/a11y-toggle-labels-231

Conversation

@kasnder

@kasnder kasnder commented Jul 11, 2026

Copy link
Copy Markdown
Member

What changed

Fixes the accessibility gap reported in #231: the app icon in the main app list is actually a button that blocks/allows Internet access for that app, but TalkBack had nothing meaningful to announce beyond a static, non-state-aware contentDescription added years ago (tracked_app_icon, still present as an inert XML default).

  • app/src/main/java/eu/faircode/netguard/AdapterRule.java: added updateToggleContentDescription(), called on bind and again right after each tap, that sets the icon's contentDescription to reflect the app name and current state:
    • "Block internet access for {name}" when currently allowed
    • "Allow internet access for {name}" when currently blocked
    • "{name} has no internet access" when the app has no Internet permission at all (tapping is a no-op)
  • app/src/main/res/values/strings.xml: added the three new string resources above, plus one more (see below), in the base (English) file only — translations are expected to follow via the usual localization process.
  • app/src/main/java/net/kollnig/missioncontrol/details/TrackersListAdapter.java and app/src/main/res/layout/list_item_trackers_header.xml: extended the same fix to the per-tracker details screen, which has the same class of unlabeled-toggle problem:
    • the per-category "Block" MaterialSwitch now gets a dynamic content description naming its tracker category (toggle_block_category_description)
    • the header's Tracker Protection / Internet Access / Exclude from VPN switches (previously no accessible name at all beyond adjacency to a nearby TextView) now get their existing visible label text as contentDescription

No behavior/blocking-logic changes — this is purely accessibility labeling, per the issue's scope.

Verification

  • ./gradlew compileGithubDebugJavaWithJavacBUILD SUCCESSFUL.
  • Not yet spot-checked on-device with TalkBack — please verify the announced text and that state updates correctly after a tap before merging.

Part of #231 (kept open as a tracking issue)

🤖 Generated with Claude Code

The app icon in the main list doubles as a button that blocks/allows
Internet access for that app, but had no meaningful contentDescription
for screen readers beyond a static, non-state-aware label added years
ago. Set a dynamic contentDescription in AdapterRule reflecting the
app name and current state ("Block/Allow internet access for X", or
a no-op description when the app has no Internet permission),
updated both on bind and immediately after each tap.

Also label the previously-unlabeled MaterialSwitch toggles in the
per-app tracker details screen (TrackersListAdapter / rule.xml),
which suffer the same class of issue: the per-category "Block"
switch gets a dynamic description naming its category, and the
Tracker Protection / Internet Access / Exclude from VPN switches in
the header get their existing visible labels as contentDescription.

Closes #231

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@kasnder

kasnder commented Jul 11, 2026

Copy link
Copy Markdown
Member Author

Thanks—this addresses a real gap and CI is green. One correctness issue remains before merge: the app-icon description ignores active. If a UID is stored as blocked while tracker protection/apply is inactive, the UI renders it unblocked and tapping cannot toggle it (only bypass_vpn_error), but TalkBack announces “Allow internet access…”. Please derive the description from the effective/actionable state and announce the inactive case as unavailable (or disable that accessibility action). I would also prefer a neutral per-category label such as “Tracker blocking for %s” so the switch state communicates on/off. After that, spot-check with TalkBack and this should be ready.

@kasnder

kasnder commented Jul 11, 2026

Copy link
Copy Markdown
Member Author

Implemented in 7b8cd6c: inactive Internet controls now announce as unavailable instead of exposing a false “Allow…” action, and category switches use neutral labels so TalkBack can communicate their checked state. testGithubDebugUnitTest and assembleGithubDebug pass locally. Remaining validation is an on-device TalkBack spot-check.

@kasnder kasnder marked this pull request as ready for review July 11, 2026 21:39
@kasnder kasnder merged commit fb18f9f into master Jul 11, 2026
1 check passed
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