Skip to content

feat: sectioned compact rows on installed apps screen (#463)#484

Merged
rainxchzed merged 2 commits into
mainfrom
feat/463-apps-section-density
May 2, 2026
Merged

feat: sectioned compact rows on installed apps screen (#463)#484
rainxchzed merged 2 commits into
mainfrom
feat/463-apps-section-density

Conversation

@rainxchzed
Copy link
Copy Markdown
Member

@rainxchzed rainxchzed commented May 2, 2026

Summary

Closes #463. Splits the installed apps list into two sections to reduce vertical footprint without losing update-triage glanceability:

  • Updates available — current rich AppItemCard preserved (icon, name, version delta, Update CTA, in-row controls).
  • Up to date — new 64dp compact row (icon 48dp + name + installed version + status dots + overflow menu). Per-app filter / variant / pre-release controls move to the overflow menu, which routes to the existing AdvancedAppSettingsBottomSheet and VariantPickerDialog.

Density target: ~3 apps/viewport → ~9-10 apps/viewport on a Pixel 6-class device.

The "Up to date" section header is collapsible (default expanded, count visible). The "Updates available" header is static so the triage workflow always stays in view.

Accessibility

  • Compact row uses Modifier.semantics(mergeDescendants = true) with a merged accessible name that surfaces every "hidden" flag (filter active / variant pinned / variant stale / pre-release on / pending install / ready to install).
  • StatusDotCluster encodes each flag with a unique shape AND color (circle / square / triangle / diamond / ring / chevron) — passes WCAG 1.4.1.
  • Section header carries Role.Button + heading() + stateDescription + count in name.
  • Overflow IconButton 40dp visual / 48dp hit zone.

Adjacent perf fix

AppsViewModel.updateAppProgress no longer calls filterApps() on every download-progress tick. Download progress doesn't affect sort order or search match, so it now maps apps + filteredApps in place. At 50+ installed apps with one downloading, this avoided a full re-sort + immutable-list rebuild on every tick.

Out of scope

  • View-mode toggle (list ↔ grid).
  • Pure grid layout.
  • Search/filter UI changes.
  • Telemetry instrumentation.

Test plan

  • Empty state — no apps installed
  • All apps need updates (only Updates available section visible)
  • No apps need updates (only Up to date section visible, collapsible)
  • Mixed state (both sections visible, header counts correct)
  • Sort by Name / Updates First / Recently Updated — sort applies inside each section
  • Search filters across both sections
  • Compact row tap → navigates to repo
  • Compact row overflow → advanced settings / variant picker / pre-release toggle / uninstall all wired
  • Pending-install state shows Install button in compact row
  • TalkBack: row reads merged name with all active flags; section headers announce as headings with count + state
  • Download progress on a row in updates section does NOT cause the up-to-date section to re-render
  • Visual QA on Android + Desktop

Summary by CodeRabbit

  • New Features

    • Apps screen split into "Updates available" and "Up to date" sections; "Up to date" is collapsible.
    • Compact app row for up-to-date apps with one-tap install/open and overflow actions.
    • Visual status dots indicating filter active, pinned/stale variants, pre-release, pending/ready-to-install.
  • Accessibility / Localization

    • Added localized strings and enhanced accessibility semantics for section headers, counts, states, and compact status descriptions.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 2, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 96c99505-cddc-4d71-8032-bf421aa12ae3

📥 Commits

Reviewing files that changed from the base of the PR and between 6880dc1 and 830f8f8.

📒 Files selected for processing (3)
  • 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
✅ Files skipped from review due to trivial changes (1)
  • feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/components/AppsSectionHeader.kt
🚧 Files skipped from review as they are similar to previous changes (2)
  • core/presentation/src/commonMain/composeResources/values/strings.xml
  • feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/components/CompactAppRow.kt

Walkthrough

Apps list split into two sections: an always-visible "Updates available" rendered with rich cards and a collapsible "Up to date" rendered with compact rows. New composables, state, action, VM handling, and string resources support section headers, compact rows with status dots, and accessibility semantics.

Changes

Installed Apps List Restructuring

Layer / File(s) Summary
Strings & Resources / State
core/presentation/src/commonMain/composeResources/values/strings.xml, feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/AppsState.kt
Added localized strings for section titles, count suffix, expand/collapse labels, and compact status fragments. Added AppsState.isUpToDateSectionExpanded: Boolean = true.
Action Definition
feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/AppsAction.kt
Added data object OnToggleUpToDateSection : AppsAction to represent header toggle intent.
ViewModel Logic
feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/AppsViewModel.kt
Handle OnToggleUpToDateSection by toggling _state.isUpToDateSectionExpanded. Optimized updateAppProgress to update downloadProgress in both apps and filteredApps without re-filtering.
New UI Components
feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/components/AppsSectionHeader.kt, .../CompactAppRow.kt, .../StatusDotCluster.kt
Added AppsSectionHeader (collapsible header with accessibility/animated chevron), CompactAppRow (64dp single-line row with icon, name, version, status cluster, install/open actions, overflow menu), and StatusDotCluster (CompactStatusFlags, drawing shapes, and semantics builder).
Screen Layout / Wiring
feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/AppsRoot.kt
Refactored list rendering: split state.filteredApps into updatesGroup and idleGroup; render "Updates available" section with AppItemCard (always expanded) and "Up to date" section with AppsSectionHeader + CompactAppRow items (collapsible, controlled by state).

Sequence Diagram

sequenceDiagram
    actor User
    participant AppsScreen
    participant AppsSectionHeader
    participant AppsViewModel
    participant AppsState
    participant AppsRoot

    User->>AppsSectionHeader: Tap "Up to date" header
    AppsSectionHeader->>AppsScreen: onToggle()
    AppsScreen->>AppsViewModel: onAction(OnToggleUpToDateSection)
    AppsViewModel->>AppsState: toggle isUpToDateSectionExpanded
    AppsState-->>AppsViewModel: new state emitted
    AppsViewModel-->>AppsScreen: state update
    AppsScreen->>AppsRoot: recompose with new state
    AppsRoot->>AppsRoot: conditionally render CompactAppRow items
    AppsRoot-->>User: section expanded/collapsed (animated)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Possibly related PRs

Poem

🐰 Hop hop, the list divides with care,

Cards for updates, rows compact and spare,
Dots that whisper statuses small,
Headers that toggle at your call,
A rabbit cheers — the view grows fair!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.27% 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 'feat: sectioned compact rows on installed apps screen' accurately describes the main change—introducing two-section layout with compact rows for up-to-date apps.
Linked Issues check ✅ Passed The PR directly addresses issue #463's objective to reduce vertical footprint per app by implementing compact 64dp rows in an 'up to date' section, improving app discoverability as requested.
Out of Scope Changes check ✅ Passed All changes align with stated objectives: sectioned layout, compact rows, accessibility enhancements, and performance optimization. No extraneous modifications detected.

✏️ 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/463-apps-section-density

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: 6/8 reviews remaining, refill in 13 minutes and 13 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
`@feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/components/AppsSectionHeader.kt`:
- Around line 61-77: The current accessibility label in AppsSectionHeader (the
semantics block that sets contentDescription and stateDescription when
collapsible and clickable) composes English text inline ("$title, $count,
$rowSemantic" and "expanded"/"collapsed"); move these strings into localized
string resources and use formatted resource lookups instead of concatenation so
TalkBack uses localized, reorderable text. Replace the inline contentDescription
and stateDescription with calls that fetch two string resources (one for the
full header label with placeholders for title/count/rowSemantic, and one or two
for the state description or a single state formatted resource taking
isExpanded) and pass those localized strings into the semantics block (where
role = Role.Button and heading() is set) so onToggle/collapsible behavior
remains unchanged but accessibility text is localized.

In
`@feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/components/CompactAppRow.kt`:
- Around line 94-98: The isBusy computation incorrectly treats any
app.isPendingInstall as busy; change it to treat the row as busy only when
pendingInstallFilePath is null (i.e., a true background install), e.g. replace
uses of app.isPendingInstall with (app.isPendingInstall &&
pendingInstallFilePath == null) in the isBusy expression (which also checks
appItem.updateState against UpdateState.Downloading/Installing/CheckingUpdate);
apply the same change to the other isBusy calculations in this component file
(the other two occurrences) so the parked-download "ready to install" CTA and
menu remain enabled.
🪄 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: d349e626-06d3-4af5-9c45-f20701fb4328

📥 Commits

Reviewing files that changed from the base of the PR and between fc421d0 and 6880dc1.

📒 Files selected for processing (8)
  • core/presentation/src/commonMain/composeResources/values/strings.xml
  • feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/AppsAction.kt
  • feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/AppsRoot.kt
  • feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/AppsState.kt
  • feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/AppsViewModel.kt
  • 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
  • feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/components/StatusDotCluster.kt

@rainxchzed rainxchzed merged commit c0311b3 into main May 2, 2026
1 check passed
@rainxchzed rainxchzed deleted the feat/463-apps-section-density branch May 2, 2026 14:46
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