Skip to content

TalkBack, 4 of 10: Improve routing rule accessibility - #6160

Draft
eliotcougar wants to merge 13 commits into
2dust:masterfrom
eliotcougar:fix/accessibility-routing-rules
Draft

eliotcougar wants to merge 13 commits into
2dust:masterfrom
eliotcougar:fix/accessibility-routing-rules

Conversation

@eliotcougar

@eliotcougar eliotcougar commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Part 4 of the TalkBack series makes routing rules one accessible toggle per row. The row exposes its name and routing destination, its observable enabled state, and named custom actions. Visible Edit/Delete buttons remain usable by touch and keyboard but do not create separate TalkBack action targets; the visual switch is controlled by the row.

Interaction

  • Preserve native toggle semantics and checked-state events. The row's activation label changes between Enable rule and Disable rule.
  • Expose Edit [name] first, Delete [name] second, followed by the currently valid Move to top / Move up / Move down / Move to bottom actions.
  • Use the shared polite live-region feedback for successful move actions. Toggle feedback comes from native checked-state changes, without an unconditional announcement after each tap.
  • Describe built-in block and direct routes using localized text. Other tags retain their actual case-sensitive identity; Direct, for example, is not the built-in direct tag.
  • Omit the raw matching conditions from row speech and include a localized locked marker where applicable.
  • Both the row custom Delete action and the visible Delete button open the same named confirmation. The editor's confirmation is named as well.

State and scope

  • Use rule IDs for pending deletion, row actions and reorder identity. Keep the pending delete ID with rememberSaveable so recreation preserves the target. Do not show a nameless confirmation when its target no longer exists.
  • Resolve an editor position immediately before navigation to fit current upstream's position-based editor contract. This PR does not reintroduce the separate routing-storage/API migration.
  • Resolve list deletion against freshly loaded persisted rules by ID, perform its storage work on Dispatchers.IO, and remove that ID from the observable list after completion. Failures are logged and use the existing error feedback.
  • Remove the obsolete deletion result wrapper and its wrapper-only tests. Keep the routing row private and require real reorder callbacks instead of test-only defaults.
  • Remove the old isolated Android test harness. No new Android test source set or test folder is introduced.
  • Keep shared feedback/reorder code and catalog entries aligned with the companion accessibility PRs, including the existing selected/select translations and Bakhtiari corrections. Do not split XML catalogs.

The branch includes the shared live-region renderer needed for move feedback, not the complete toast/service-notification layer from Part 1. It does not include the subscription, asset, per-app, settings, navigation or server-list feature changes from the other parts.

Localization

Routing summaries, enabled/disabled states, action labels, named confirmations and move feedback are covered in English, Arabic, Bengali, Bakhtiari, Persian, Russian, Vietnamese, Simplified Chinese and Traditional Chinese. Russian uses the pinned/preserved sense, «Закреплено», for the lock marker to distinguish it from blocked traffic. Actual outbound tags are configuration identities and are not translated.

TalkBack controls the precise ordering and wording of native role/state output; this PR does not suppress those semantics or force accessibility focus.

Validation

  • Play Store debug JVM suite: 78 tests, no failures or errors.
  • Kotlin compilation and Play Store debug x86_64 APK assembly pass.
  • All nine locale catalogs contain the 17 routing/reorder keys with matching placeholders.
  • Non-checkout merge checks against each of the other nine focused branches pass in both orders and produce equal result trees.
  • Android 17 / Pixel 9 Pro emulator: native checked state and Enable/Disable labels update on the same focused row; custom Edit opens the named rule; Move down retains row focus and persists after reopening; custom Delete shows the correct name after reordering and rotation. Exact Direct remains a custom destination while built-in direct and block retain their localized summaries.
  • The device checks use the real application screen and an external temporary native-node probe, not setContent replacement screens. The probe is not part of the PR.

Not run

  • Recorded TalkBack audio and every locale's speech-engine pronunciation. Native node state, actions and focus were inspected with TalkBack bound; that is not an audio transcript.
  • Exhaustive keyboard/D-pad action traversal, storage-failure injection and concurrent storage-writer stress scenarios. No dedicated JVM persistence test seam was added solely for this cleanup.

Validation above was performed on the reviewed code ending at 67cbe2ac4 on 2026-09-05. The emulator's original APK and settings were restored, the temporary rule and external probe were removed, and the existing lab subscription was preserved.

@eliotcougar eliotcougar changed the title TalkBack, 4 of N: Improve routing rule accessibility TalkBack, 4 of 10: Improve routing rule accessibility Aug 30, 2026
Merge each rule's meaningful text into a concise row summary while preserving native button and switch semantics. Add contextual edit and delete actions, named confirmation dialogs, and stable-ID deletion with localized resources and reducer coverage.
@eliotcougar
eliotcougar force-pushed the fix/accessibility-routing-rules branch from 19cd74a to de8dc2d Compare August 30, 2026 13:41
@eliotcougar
eliotcougar marked this pull request as ready for review August 30, 2026 17:50
Append a localized lock suffix to the existing name, route and enabled-state summary only when the rule is locked. Keep the decorative lock icon inert and preserve the native switch and independent actions. Russian uses the pinned/preserved meaning to distinguish a locked rule from blocked traffic.

Cover all nine supported resource locales. Play Store debug unit tests, Kotlin compilation, assembly and XML placeholder checks pass.
Move the rule's switch action and observable checked state onto the whole
row. Keep the child Switch passive and Edit/Delete as independent actions.

Retain the rule name, route and locked context in a stable accessible
label. Put the changing rule on/off phrase in stateDescription so Compose
emits native state-change feedback instead of requiring users to revisit
the row. This addresses the missing feedback reproduced with Compose UI
1.11.4 and TalkBack 17 without manual announcements or focus requests.

Remove the redundant child-switch label and update the summary format in
all nine locale catalogs. The rule identity and persistence path are
unchanged.

Validation: 60 Play Store debug unit tests passed; app and androidTest APKs
assembled; RoutingToggleFeedbackTest passed on the Android 37.1 Pixel 9 Pro
emulator with TalkBack 17 enabled. It covers same-row state-description
events in both directions, a single toggle target, pointer/keyboard/D-pad
activation and independent Edit/Delete callbacks. Physical-device gestures
and the full supported Android-version matrix were not tested.
@eliotcougar
eliotcougar marked this pull request as draft August 31, 2026 19:29
Keep each rule as one native switch target, place Edit and Delete first in its accessibility action menu, and append position-aware reorder commands that resolve the rule by ID.
Reuse 2dust#6167's reviewed Selected translations in the shared locale catalogs. This removes the remaining English fallback and keeps focused accessibility branches conflict-free when merged in either order.
Adopt the overlapping terminology corrections from PR 2dust#6169 and carry them into branch-only plural and accessibility resources. This keeps later merge resolution from restoring stale Bakhtiari wording.
@eliotcougar
eliotcougar marked this pull request as ready for review September 2, 2026 00:40
Expose Enable rule or Disable rule as the native click label based on the rule's next state. Preserve the row's switch role, checked state, stable identity and existing touch/keyboard activation.

Send successful custom move results to a window-hosted polite live region with a short localized Moved message. Keep identical consecutive moves observable, hide the idle host, and leave rejected moves silent. Update all nine existing locale catalogs.

Validation: 65 Play Store debug JVM tests, Kotlin compilation, app/test assembly, two focused emulator tests for toggle labels/state and repeatable reorder feedback, plus combined integration checks. Not run: listening verification in every locale.
@eliotcougar
eliotcougar marked this pull request as draft September 5, 2026 11:12
Give the host a single explicit owner instead of combining a supplied SnackbarHostState with a composition-local controller. Remove the unused LocalAppSnackbar provider. Keep this behavior-preserving wiring change shared by the notification, subscription, routing and server-row PRs so they remain independently mergeable.
Apply the shared two-file controller/host refactor without importing Part 1 notification behavior. Pass the controller directly and remove the unused composition-local provider, keeping this focused PR independently mergeable with the notification PR in either order. Preserve the existing custom-action feedback rendering and collection order.

Validation: Play Store debug Kotlin compilation and the complete branch JVM test suite passed. Temporary merge-tree checks against the final Part 1 tree succeeded in both orders with identical results. No feature, resource, native-library or instruction changes are included.
Synchronize the shared renderer, window-owned feedback state, and JVM regression tests with Part 2. Hold each message until publication, retain ordered feedback, and discard stale messages on pause. Align the neighboring Select resource in all locales for conflict-free shared catalog merges. Routing-specific actions and persistence are unchanged.
Retain row-owned Edit/Delete/reorder actions, native toggle semantics, and accessibility-inert child buttons. Match built-in routing tags exactly, preserve the pending deletion ID across recreation, and hide confirmations for missing targets.

Remove the test-only deletion result wrapper and resolve deletion against the latest stored rules by ID on Dispatchers.IO, without restoring the reverted SettingsManager ID API. Resolve row editing to the current position at the upstream editor boundary. Dismiss confirmations before starting deletion.

Remove the obsolete Android-test harness, its production-only test hooks, redundant icon descriptions, and the unused server-selection action resource. Keep shared feedback/reorder primitives and existing translation corrections unchanged.
Keep the existing Select action translations aligned with the companion subscription and server-row PRs. Removing these shared catalog entries in isolation caused delete/modify conflicts without simplifying the routing implementation.
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