Skip to content

fix: apps screen a11y state description and pending-install button#486

Merged
rainxchzed merged 4 commits into
mainfrom
feat/470-sui-and-apps-fixes
May 2, 2026
Merged

fix: apps screen a11y state description and pending-install button#486
rainxchzed merged 4 commits into
mainfrom
feat/470-sui-and-apps-fixes

Conversation

@rainxchzed
Copy link
Copy Markdown
Member

@rainxchzed rainxchzed commented May 2, 2026

Summary

  • Localize the apps section header stateDescription so screen readers in non-English locales no longer hear English "expanded" / "collapsed". Adds apps_section_state_expanded / apps_section_state_collapsed resources.
  • Stop disabling the compact-row Install button (and overflow menu) while a parked install file exists. isPendingInstall is a quiescent "bytes parked on disk" flag, not an active-work flag — including it in isBusy blocked the very action the row is rendered to surface.

Test plan

  • TalkBack on a non-English device announces the localized expanded/collapsed state on the apps section header.
  • Apps screen: a row with a pending install file (pendingInstallFilePath != null, isPendingInstall = true) shows the Install button enabled and the overflow menu enabled.
  • Apps screen: rows in Downloading / Installing / CheckingUpdate still disable the action controls as before.

Summary by CodeRabbit

  • Bug Fixes

    • Improved Shizuku service detection to better distinguish between "not running" and "not installed" states.
  • New Features

    • Added localized labels for app section expand/collapse states.
  • Accessibility

    • Enhanced accessibility announcements for collapsible app sections.
    • Refined app installation and update status indicators for clearer user feedback.

rainxchzed added 3 commits May 2, 2026 19:36
Updates `ShizukuServiceManager` to recognize Sui as a valid service provider alongside the standard Shizuku implementation. The `computeStatus` logic is refactored to prioritize binder connectivity; if the binder is unresponsive, the manager now checks for the presence of either the Shizuku or Sui packages to accurately differentiate between `NOT_RUNNING` and `NOT_INSTALLED` states.

*   Added `com.sui` package constant.
*   Introduced `isPackageInstalled` helper to check for specific package availability.
*   Renamed `isShizukuInstalled` to `isShizukuOrSuiInstalled` to reflect broader compatibility.
*   Restructured `computeStatus` to reduce redundant checks when the service is already active.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 2, 2026

Walkthrough

This PR contains two independent changes: refactoring Shizuku service status computation to distinguish between not-installed and not-running states when the binder is dead, and updating the apps section UI with localized accessibility labels and simplified busy state logic.

Changes

Shizuku Service Status Distinction

Layer / File(s) Summary
Constants & Helpers
core/data/src/androidMain/kotlin/.../ShizukuServiceManager.kt
Added SUI_PACKAGE constant and new private methods isShizukuOrSuiInstalled() and isPackageInstalled() to check package presence via PackageManager.
Core Status Logic
core/data/src/androidMain/kotlin/.../ShizukuServiceManager.kt
Refactored computeStatus() to return NOT_INSTALLED when binder is dead but no Shizuku/SUI package is installed, vs NOT_RUNNING when either is installed. Preserves existing READY/PERMISSION_NEEDED logic and exception handling.

Apps Section UI Localization and Logic

Layer / File(s) Summary
String Resources
core/presentation/src/commonMain/composeResources/values/strings.xml
Added two new localized string entries: apps_section_state_expanded (value: "Expanded") and apps_section_state_collapsed (value: "Collapsed").
Accessibility Semantics
feature/apps/presentation/src/commonMain/kotlin/.../AppsSectionHeader.kt
Updated stateDescription labels to use the new localized string resources instead of hard-coded "expanded"/"collapsed" literals for accessibility announcements.
Busy State Logic
feature/apps/presentation/src/commonMain/kotlin/.../CompactAppRow.kt
Simplified isBusy computation to exclude app.isPendingInstall and only check appItem.updateState for Downloading, Installing, or CheckingUpdate conditions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 The binder whispers when the packages hide,
"Not running" or "gone"—we now can decide!
UI strings bloom in tongues so bright,
Accessibility sees the expanded light.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes both main changes: a11y (accessibility) fix for localized state descriptions and a pending-install button enablement logic fix.
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 feat/470-sui-and-apps-fixes
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch feat/470-sui-and-apps-fixes

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
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

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

Copy link
Copy Markdown
Contributor

@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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@core/presentation/src/commonMain/composeResources/values/strings.xml`:
- Around line 961-962: The new accessibility string keys
apps_section_state_expanded and apps_section_state_collapsed were only added to
the default values/strings.xml; update every existing locale-specific strings
file (e.g., values-es, values-fr, values-ja, values-zh-rCN, etc.) to include
these two keys with correct translated text so non-English TalkBack announces
localized “expanded”/“collapsed” instead of falling back to English — add the
same string names (apps_section_state_expanded, apps_section_state_collapsed)
with appropriate translations in each locale file.

In
`@feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/components/CompactAppRow.kt`:
- Around line 94-97: Update the busy/interaction model to be consistent: make
AppsRoot.kt use the same isBusy logic as CompactAppRow.kt (remove
app.isPendingInstall from its isBusy calculation) OR revert CompactAppRow.kt
change so both files match; then explicitly guard the "Open" shortcut rendering
by checking the pending-install substate (use both isPendingInstall and
pendingInstallFilePath) instead of relying only on !isBusy — adjust the
conditional that currently shows Open when !isBusy to also require
pendingInstallFilePath != null (or explicitly permit Open only when not in the
pending-install-without-path state), and update StatusDotCluster-related checks
if needed so StatusDotCluster, CompactAppRow (isBusy), and AppsRoot (isBusy)
share the same semantics for isPendingInstall and pendingInstallFilePath.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d1b8aa7a-d565-471b-939d-ff8ba113d003

📥 Commits

Reviewing files that changed from the base of the PR and between c0311b3 and 7c4e98f.

📒 Files selected for processing (4)
  • core/data/src/androidMain/kotlin/zed/rainxch/core/data/services/shizuku/ShizukuServiceManager.kt
  • core/presentation/src/commonMain/composeResources/values/strings.xml
  • feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/components/AppsSectionHeader.kt
  • feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/components/CompactAppRow.kt

Comment on lines +961 to +962
<string name="apps_section_state_expanded">Expanded</string>
<string name="apps_section_state_collapsed">Collapsed</string>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

New a11y strings are absent from all language-specific resource files — non-English TalkBack still announces English text

The PR's stated goal is that "screen readers in non-English locales no longer announce English 'expanded' / 'collapsed'". Adding keys only to the default values/strings.xml enables future translation without a code change, but until the entries are also added to the locale-specific files (values-es, values-fr, values-ja, values-zh-rCN, etc.), those locales fall back to the default English values — the same outcome as the old hard-coded strings.

The two entries need to be added (with appropriate translations) to every existing language-specific strings file to actually fulfill the PR objective.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/presentation/src/commonMain/composeResources/values/strings.xml` around
lines 961 - 962, The new accessibility string keys apps_section_state_expanded
and apps_section_state_collapsed were only added to the default
values/strings.xml; update every existing locale-specific strings file (e.g.,
values-es, values-fr, values-ja, values-zh-rCN, etc.) to include these two keys
with correct translated text so non-English TalkBack announces localized
“expanded”/“collapsed” instead of falling back to English — add the same string
names (apps_section_state_expanded, apps_section_state_collapsed) with
appropriate translations in each locale file.

Comment on lines 94 to 97
val isBusy =
app.isPendingInstall ||
appItem.updateState is UpdateState.Downloading ||
appItem.updateState is UpdateState.Downloading ||
appItem.updateState is UpdateState.Installing ||
appItem.updateState is UpdateState.CheckingUpdate
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

isBusy is now inconsistent with AppsRoot.kt, and the "Open" shortcut silently appears for isPendingInstall=true, pendingInstallFilePath=null

The intended fix (enable the Install button when pendingInstallFilePath != null) is correct — the Install button only renders inside if (app.pendingInstallFilePath != null), so removing isPendingInstall from isBusy is safe for that branch.

However, two knock-on effects need attention:

  1. Inconsistency with AppsRoot.kt:762-765, which still reads:

    val isBusy =
        app.isPendingInstall ||
            appItem.updateState is UpdateState.Downloading || ...

    The same app entry in the full card disables interactions when isPendingInstall=true, but the compact row now enables them. If removing isPendingInstall from isBusy is the correct model, AppsRoot.kt should be updated to match.

  2. "Open" shortcut appears for isPendingInstall=true, pendingInstallFilePath=null — the sub-state where the system installer was triggered but no file path is present (see StatusDotCluster.kt snippet: pendingInstall = isPendingInstall && pendingInstallFilePath == null). With isBusy=false, else if (!isBusy) at line 175 now fires, surfacing the Open shortcut in a state it was previously hidden for. This may be intentional (the current app version is still openable), but it should be explicitly verified since it's an undocumented behavior change.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/components/CompactAppRow.kt`
around lines 94 - 97, Update the busy/interaction model to be consistent: make
AppsRoot.kt use the same isBusy logic as CompactAppRow.kt (remove
app.isPendingInstall from its isBusy calculation) OR revert CompactAppRow.kt
change so both files match; then explicitly guard the "Open" shortcut rendering
by checking the pending-install substate (use both isPendingInstall and
pendingInstallFilePath) instead of relying only on !isBusy — adjust the
conditional that currently shows Open when !isBusy to also require
pendingInstallFilePath != null (or explicitly permit Open only when not in the
pending-install-without-path state), and update StatusDotCluster-related checks
if needed so StatusDotCluster, CompactAppRow (isBusy), and AppsRoot (isBusy)
share the same semantics for isPendingInstall and pendingInstallFilePath.

…-fixes

# Conflicts:
#	core/presentation/src/commonMain/composeResources/values/strings.xml
#	feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/components/AppsSectionHeader.kt
#	feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/components/CompactAppRow.kt
@rainxchzed rainxchzed merged commit 25a848f into main May 2, 2026
1 check was pending
@rainxchzed rainxchzed deleted the feat/470-sui-and-apps-fixes branch May 2, 2026 16:12
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