Skip to content

feat(library): sort options for Apps/Starred/Favourites#628

Merged
rainxchzed merged 3 commits into
mainfrom
feat/library-section-sort
May 17, 2026
Merged

feat(library): sort options for Apps/Starred/Favourites#628
rainxchzed merged 3 commits into
mainfrom
feat/library-section-sort

Conversation

@rainxchzed
Copy link
Copy Markdown
Member

@rainxchzed rainxchzed commented May 17, 2026

Summary

  • Adds sort dropdown to Starred + Favourites (Apps already had one).
  • All three persist per-section via TweaksRepository β€” choice survives restart.
  • Options: Apps (Updates first / Recently updated / Name), Starred (Recently starred / Aβ†’Z / Most stars), Favourites (Recently added / Aβ†’Z).

Test plan

  • Open Apps, change sort, kill app, reopen β€” sort preserved.
  • Open Starred, change sort, verify list reorders and persists across restart.
  • Open Favourites, same.
  • Empty list β†’ sort icon hidden.

Summary by CodeRabbit

  • New Features

    • Added customizable sorting for Installed, Starred and Favorites (name, recently added/updated, star count where applicable).
    • Each section now remembers the user's chosen sort preference and restores it when returning.
  • Documentation / Release Notes

    • Updated "What's New" text across languages to mention per-section sorting.
    • Added "Recently added" label in multiple locales.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 17, 2026

Caution

Review failed

Pull request was closed or merged during review

Walkthrough

Adds persisted per-screen sort-rule preferences (Apps, Starred, Favourites). Enums provide fromName factories; TweaksRepository exposes Flow getters and suspend setters; each feature’s ViewModel observes the stored rule, applies comparators, updates state, and persists user selections. UI top bars add conditional sort dropdowns. Localization and whatsnew texts updated.

Changes

Persistent Sort Preferences Feature

Layer / File(s) Summary
Persistence API (TweaksRepository)
core/domain/src/commonMain/.../TweaksRepository.kt, core/data/src/commonMain/.../TweaksRepositoryImpl.kt
TweaksRepository interface defines three getter/setter pairs for apps, starred, and favourites sort rules; implementation uses stringPreferencesKey constants and Preference flows/edits for reactive reads and suspending writes.
Sort rule enums with factory methods
feature/apps/.../model/AppSortRule.kt, feature/favourites/.../model/FavouritesSortRule.kt, feature/starred/.../model/StarredSortRule.kt
AppSortRule, FavouritesSortRule, StarredSortRule add companion object.fromName(String?) to map stored names to enum values with safe defaults.
Apps feature sort integration
feature/apps/presentation/.../AppsViewModel.kt
AppsViewModel observes tweaksRepository.getAppsSortRule(), derives AppSortRule, updates _state.sortRule and re-filters; persists user selections via setAppsSortRule().
Starred repos feature sort integration
feature/starred/presentation/.../*
StarredReposViewModel observes/persists starred sort rule, applies starredComparator, updates state.sortRule; UI renders sort dropdown (StarredSortRule.entries) and dispatches OnSortRuleSelected.
Favourites feature sort integration
feature/favourites/presentation/.../*
FavouritesViewModel observes/persists favourites sort rule, applies favouritesComparator, updates state.sortRule (default RecentlyAdded); UI shows conditional sort icon and dropdown, dispatching OnSortRuleSelected.
Localization and release notes
core/presentation/src/commonMain/composeResources/values*/strings-*.xml, core/presentation/src/commonMain/composeResources/files/whatsnew/*/18.json
Adds sort_recently_added translations and updates version-18 whatsnew bullets across locales documenting per-section remembered sorting.
sequenceDiagram
  participant Screen
  participant ViewModel
  participant TweaksRepository
  participant Preferences
  Screen->>ViewModel: load/initialize
  ViewModel->>TweaksRepository: get*SortRule() (Flow<String?>)
  TweaksRepository->>Preferences: preferences.data.map -> emit stored name
  TweaksRepository-->>ViewModel: Flow emits String? (rule name)
  ViewModel->>ViewModel: fromName(name) -> SortRule
  ViewModel->>ViewModel: sort items using comparator
  ViewModel-->>Screen: update state (items, sortRule)
  Screen->>ViewModel: OnSortRuleSelected(rule)
  ViewModel->>TweaksRepository: set*SortRule(rule.name)
  TweaksRepository->>Preferences: preferences.edit { putString(key, name) }
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 A rabbit hums while keys are set,

Sorts remembered β€” no regret.
Apps, starred, favourites align,
Saved by name, by date, by shine.
Hooray β€” preferences hop in time!

πŸš₯ 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 summarizes the main feature: adding sort options to three library sections (Apps, Starred, Favourites).
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/library-section-sort

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

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: 3

🧹 Nitpick comments (2)
feature/favourites/presentation/src/commonMain/kotlin/zed/rainxch/favourites/presentation/FavouritesRoot.kt (1)

219-244: ⚑ Quick win

Render selected state for the current sort option.

The menu currently doesn’t indicate the active sortRule, which makes persisted state less discoverable. Add selected styling/checkmark for the current rule.

♻️ Proposed tweak
                     DropdownMenu(
                         expanded = showSortMenu,
                         onDismissRequest = { showSortMenu = false },
                     ) {
                         FavouritesSortRule.entries.forEach { rule ->
                             DropdownMenuItem(
-                                text = { Text(stringResource(rule.labelRes())) },
+                                text = {
+                                    Text(
+                                        text = stringResource(rule.labelRes()),
+                                        fontWeight = if (rule == sortRule) FontWeight.SemiBold else FontWeight.Normal,
+                                    )
+                                },
                                 onClick = {
                                     showSortMenu = false
                                     onAction(FavouritesAction.OnSortRuleSelected(rule))
                                 },
                             )
                         }
                     }
πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/favourites/presentation/src/commonMain/kotlin/zed/rainxch/favourites/presentation/FavouritesRoot.kt`
around lines 219 - 244, The sort DropdownMenu doesn't indicate which rule is
currently selected: update the DropdownMenuItem rendering inside FavouritesRoot
so each item reflects the active sortRule (e.g., use the DropdownMenuItem
parameter or trailing icon to show a check/selected state when rule ==
sortRule); locate the loop over FavouritesSortRule.entries and modify
DropdownMenuItem to pass a selected flag or show an Icon for the selected rule,
keeping the existing onClick that sets showSortMenu = false and calls
onAction(FavouritesAction.OnSortRuleSelected(rule)).
feature/starred/presentation/src/commonMain/kotlin/zed/rainxch/starred/presentation/StarredReposRoot.kt (1)

333-355: ⚑ Quick win

Show the currently selected sort rule in the dropdown.

sortRule is already passed in, but menu items render identically. Add a selected affordance (e.g., checkmark/typography) so users can confirm the active persisted sort quickly.

♻️ Proposed tweak
                         DropdownMenu(
                             expanded = showSortMenu,
                             onDismissRequest = { showSortMenu = false },
                         ) {
                             StarredSortRule.entries.forEach { rule ->
                                 DropdownMenuItem(
-                                    text = { Text(stringResource(rule.labelRes())) },
+                                    text = {
+                                        Text(
+                                            text = stringResource(rule.labelRes()),
+                                            fontWeight = if (rule == sortRule) FontWeight.SemiBold else FontWeight.Normal,
+                                        )
+                                    },
                                     onClick = {
                                         showSortMenu = false
                                         onAction(StarredReposAction.OnSortRuleSelected(rule))
                                     },
                                 )
                             }
                         }
πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/starred/presentation/src/commonMain/kotlin/zed/rainxch/starred/presentation/StarredReposRoot.kt`
around lines 333 - 355, The dropdown menu always renders identical items even
though the current sortRule is passed in; update the DropdownMenuItem rendering
in StarredReposRoot (where StarredSortRule.entries.forEach and onClick create
items) to visually mark the active rule by comparing each rule to the current
sortRule and adding a selected affordance (for example add a leading Icon(check)
or change Text style/weight for the matching rule) and ensure accessibility by
including appropriate contentDescription or semantics for the selected state.
πŸ€– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/presentation/src/commonMain/composeResources/files/whatsnew/18.json`:
- Line 41: Replace the current sentence "Sort Installed, Starred, and Favourites
β€” pick by name, recency, or stars; your choice is remembered per section." with
a line that clarifies these are section-specific sort options, e.g.
"Section-specific sort options β€” Installed (name, recency), Starred (name,
stars), and Favourites (name, recency); your choice is remembered per section."
Update the string in 18.json accordingly so release notes reflect the actual
implemented options.

In
`@feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/AppsViewModel.kt`:
- Around line 283-285: The runCatching blocks that call tweaksRepository
persistence methods (e.g., tweaksRepository.setAppsSortRule(...) and the
setExternalImportBannerDismissedAtCount calls) are swallowing
CancellationException; replace each runCatching { ... } inside
viewModelScope.launch with a try { tweaksRepository.<method>(...) } catch (e:
CancellationException) { throw e } catch (t: Throwable) { /* swallow or log as
other similar methods do (see toggleUpdateCheck/skipReleaseTag) */ } so
cancellation can propagate while other errors remain handled consistently.

In
`@feature/starred/presentation/src/commonMain/kotlin/zed/rainxch/starred/presentation/StarredReposViewModel.kt`:
- Around line 194-196: The current use of runCatching in the
viewModelScope.launch block around
tweaksRepository.setStarredSortRule(action.sortRule.name) swallows
CancellationException and prevents proper coroutine cancellation; update the
block to explicitly rethrow CancellationException (or check and throw if caught)
while still handling other exceptions (e.g., log or ignore non-cancellation
errors) so cancellation propagates correctly from viewModelScope.

---

Nitpick comments:
In
`@feature/favourites/presentation/src/commonMain/kotlin/zed/rainxch/favourites/presentation/FavouritesRoot.kt`:
- Around line 219-244: The sort DropdownMenu doesn't indicate which rule is
currently selected: update the DropdownMenuItem rendering inside FavouritesRoot
so each item reflects the active sortRule (e.g., use the DropdownMenuItem
parameter or trailing icon to show a check/selected state when rule ==
sortRule); locate the loop over FavouritesSortRule.entries and modify
DropdownMenuItem to pass a selected flag or show an Icon for the selected rule,
keeping the existing onClick that sets showSortMenu = false and calls
onAction(FavouritesAction.OnSortRuleSelected(rule)).

In
`@feature/starred/presentation/src/commonMain/kotlin/zed/rainxch/starred/presentation/StarredReposRoot.kt`:
- Around line 333-355: The dropdown menu always renders identical items even
though the current sortRule is passed in; update the DropdownMenuItem rendering
in StarredReposRoot (where StarredSortRule.entries.forEach and onClick create
items) to visually mark the active rule by comparing each rule to the current
sortRule and adding a selected affordance (for example add a leading Icon(check)
or change Text style/weight for the matching rule) and ensure accessibility by
including appropriate contentDescription or semantics for the selected state.
πŸͺ„ 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: 7f5f79ea-4faa-411d-a365-17ded9f3f6ba

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between ec94daf and b2e5ffe.

πŸ“’ Files selected for processing (40)
  • core/data/src/commonMain/kotlin/zed/rainxch/core/data/repository/TweaksRepositoryImpl.kt
  • core/domain/src/commonMain/kotlin/zed/rainxch/core/domain/repository/TweaksRepository.kt
  • core/presentation/src/commonMain/composeResources/files/whatsnew/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/ar/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/bn/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/es/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/fr/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/hi/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/it/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/ja/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/ko/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/pl/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/ru/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/tr/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/zh-CN/18.json
  • core/presentation/src/commonMain/composeResources/values-ar/strings-ar.xml
  • core/presentation/src/commonMain/composeResources/values-bn/strings-bn.xml
  • core/presentation/src/commonMain/composeResources/values-es/strings-es.xml
  • core/presentation/src/commonMain/composeResources/values-fr/strings-fr.xml
  • core/presentation/src/commonMain/composeResources/values-hi/strings-hi.xml
  • core/presentation/src/commonMain/composeResources/values-it/strings-it.xml
  • core/presentation/src/commonMain/composeResources/values-ja/strings-ja.xml
  • core/presentation/src/commonMain/composeResources/values-ko/strings-ko.xml
  • core/presentation/src/commonMain/composeResources/values-pl/strings-pl.xml
  • core/presentation/src/commonMain/composeResources/values-ru/strings-ru.xml
  • core/presentation/src/commonMain/composeResources/values-tr/strings-tr.xml
  • core/presentation/src/commonMain/composeResources/values-zh-rCN/strings-zh-rCN.xml
  • core/presentation/src/commonMain/composeResources/values/strings.xml
  • feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/AppsViewModel.kt
  • feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/model/AppSortRule.kt
  • feature/favourites/presentation/src/commonMain/kotlin/zed/rainxch/favourites/presentation/FavouritesAction.kt
  • feature/favourites/presentation/src/commonMain/kotlin/zed/rainxch/favourites/presentation/FavouritesRoot.kt
  • feature/favourites/presentation/src/commonMain/kotlin/zed/rainxch/favourites/presentation/FavouritesState.kt
  • feature/favourites/presentation/src/commonMain/kotlin/zed/rainxch/favourites/presentation/FavouritesViewModel.kt
  • feature/favourites/presentation/src/commonMain/kotlin/zed/rainxch/favourites/presentation/model/FavouritesSortRule.kt
  • feature/starred/presentation/src/commonMain/kotlin/zed/rainxch/starred/presentation/StarredReposAction.kt
  • feature/starred/presentation/src/commonMain/kotlin/zed/rainxch/starred/presentation/StarredReposRoot.kt
  • feature/starred/presentation/src/commonMain/kotlin/zed/rainxch/starred/presentation/StarredReposState.kt
  • feature/starred/presentation/src/commonMain/kotlin/zed/rainxch/starred/presentation/StarredReposViewModel.kt
  • feature/starred/presentation/src/commonMain/kotlin/zed/rainxch/starred/presentation/model/StarredSortRule.kt

Comment thread core/presentation/src/commonMain/composeResources/files/whatsnew/18.json Outdated
Comment on lines +283 to +285
viewModelScope.launch {
runCatching { tweaksRepository.setAppsSortRule(action.sortRule.name) }
}
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

🧩 Analysis chain

🏁 Script executed:

# First, let's locate and examine the AppsViewModel.kt file
fd -t f "AppsViewModel.kt" | head -20

Repository: OpenHub-Store/GitHub-Store

Length of output: 165


🏁 Script executed:

# Check the specific lines mentioned in the review
rg "viewModelScope.launch" --context=5 -g "*AppsViewModel.kt"

Repository: OpenHub-Store/GitHub-Store

Length of output: 50382


🏁 Script executed:

# Read the exact section at lines 283-285
sed -n '280,290p' feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/AppsViewModel.kt

Repository: OpenHub-Store/GitHub-Store

Length of output: 356


🏁 Script executed:

# Search for all runCatching patterns in the AppsViewModel file
rg "runCatching" feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/AppsViewModel.kt -B 2 -A 2

Repository: OpenHub-Store/GitHub-Store

Length of output: 1871


🏁 Script executed:

# Check for CancellationException handling patterns in the same file
rg "CancellationException" feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/AppsViewModel.kt -B 2 -A 2

Repository: OpenHub-Store/GitHub-Store

Length of output: 4156


🏁 Script executed:

# Let's check the tweaksRepository.setAppsSortRule method signature to see if it's a suspend function
fd -t f "TweaksRepository" | head -20

Repository: OpenHub-Store/GitHub-Store

Length of output: 248


🏁 Script executed:

# Search for the definition of setAppsSortRule
rg "fun setAppsSortRule" --context=3

Repository: OpenHub-Store/GitHub-Store

Length of output: 1710


🏁 Script executed:

# Let me check all instances of runCatching in launch blocks to see the pattern
rg "viewModelScope.launch" --context=1 | rg -A 1 "viewModelScope.launch" | rg "runCatching" -B 1

Repository: OpenHub-Store/GitHub-Store

Length of output: 6527


🏁 Script executed:

# Check if there's a pattern where runCatching is used to silently ignore failures
rg "runCatching.*tweaksRepository" feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/AppsViewModel.kt

Repository: OpenHub-Store/GitHub-Store

Length of output: 461


🏁 Script executed:

# Let me verify all the instances that need fixing by looking at the exact lines
rg "runCatching.*tweaksRepository" feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/AppsViewModel.kt -n

Repository: OpenHub-Store/GitHub-Store

Length of output: 477


🏁 Script executed:

# Check how other ViewModels in the codebase handle this (e.g., StarredReposViewModel)
cat feature/starred/presentation/src/commonMain/kotlin/zed/rainxch/starred/presentation/StarredReposViewModel.kt | grep -A 2 "setStarredSortRule"

Repository: OpenHub-Store/GitHub-Store

Length of output: 196


🏁 Script executed:

# Let's verify the Kotlin documentation about runCatching and CancellationException behavior
# by checking how runCatching is imported and used
rg "import.*runCatching|fun runCatching" feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/AppsViewModel.kt

Repository: OpenHub-Store/GitHub-Store

Length of output: 52


🏁 Script executed:

# Check the other tweaksRepository calls in the same file to see the pattern
sed -n '605,635p' feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/AppsViewModel.kt

Repository: OpenHub-Store/GitHub-Store

Length of output: 1700


🏁 Script executed:

# Let me verify the Kotlin behavior of runCatching with CancellationException by checking documentation and imports
rg "runCatching" core/domain/src/commonMain/kotlin -A 2 | head -20

Repository: OpenHub-Store/GitHub-Store

Length of output: 447


🏁 Script executed:

# Check how many similar patterns exist in AppsViewModel that need the same fix
grep -n "runCatching.*tweaksRepository\|runCatching.*downloaderOrchestrator\|runCatching.*externalImportRepository" feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/AppsViewModel.kt

Repository: OpenHub-Store/GitHub-Store

Length of output: 477


Fix cancellation semantics in all runCatching blocks persisting preferences.

The runCatching blocks on lines 284, 610, 620, and 631 swallow CancellationException, preventing coroutine cancellation from propagating. Replace with try/catch that explicitly re-throws CancellationException, matching the pattern already used elsewhere in this file (e.g., toggleUpdateCheck, skipReleaseTag).

Suggested fix for line 284
                viewModelScope.launch {
-                    runCatching { tweaksRepository.setAppsSortRule(action.sortRule.name) }
+                    try {
+                        tweaksRepository.setAppsSortRule(action.sortRule.name)
+                    } catch (e: CancellationException) {
+                        throw e
+                    } catch (e: Exception) {
+                        logger.warn("Failed to persist apps sort rule: ${e.message}")
+                    }
                 }

Apply the same pattern to lines 610, 620, and 631 for setExternalImportBannerDismissedAtCount.

πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
viewModelScope.launch {
runCatching { tweaksRepository.setAppsSortRule(action.sortRule.name) }
}
viewModelScope.launch {
try {
tweaksRepository.setAppsSortRule(action.sortRule.name)
} catch (e: CancellationException) {
throw e
} catch (e: Exception) {
logger.warn("Failed to persist apps sort rule: ${e.message}")
}
}
πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/AppsViewModel.kt`
around lines 283 - 285, The runCatching blocks that call tweaksRepository
persistence methods (e.g., tweaksRepository.setAppsSortRule(...) and the
setExternalImportBannerDismissedAtCount calls) are swallowing
CancellationException; replace each runCatching { ... } inside
viewModelScope.launch with a try { tweaksRepository.<method>(...) } catch (e:
CancellationException) { throw e } catch (t: Throwable) { /* swallow or log as
other similar methods do (see toggleUpdateCheck/skipReleaseTag) */ } so
cancellation can propagate while other errors remain handled consistently.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 17, 2026

Greptile Summary

This PR adds sort options to the Starred and Favourites screens (which already existed on Apps), with each section persisting its sort preference via TweaksRepository to DataStore so the chosen order survives restarts.

  • Starred gains three sort options (Recently starred, Aβ†’Z, Most stars) and Favourites gains two (Recently added, Aβ†’Z), both following the same combine-based pattern used after the Apps race-condition fix.
  • The FavouritesViewModel and StarredReposViewModel constructors each gain a TweaksRepository parameter; because both VMs are registered with Koin's viewModelOf, the new dependency is resolved automatically from the existing graph without any module change needed.
  • Localization strings are added across 13 locale files and the "What's New" entry is bumped to version 18.

Confidence Score: 5/5

Safe to merge. Sort logic, persistence, and UI wiring are all correct; no data is lost or corrupted regardless of sort selection.

The core changes are functionally correct. Koin's viewModelOf automatically resolves the new TweaksRepository constructor parameter. Both findings are observability and UX quality issues that do not affect correctness.

StarredReposViewModel and FavouritesViewModel have minor inconsistencies with AppsViewModel in how sort selection is handled, but no correctness issues.

Important Files Changed

Filename Overview
feature/starred/presentation/src/commonMain/kotlin/zed/rainxch/starred/presentation/StarredReposViewModel.kt Adds TweaksRepository dependency and sort logic via combine; sort selection only triggers a DataStore write with no immediate state update, causing a brief visual lag compared to AppsViewModel; errors are silently discarded.
feature/favourites/presentation/src/commonMain/kotlin/zed/rainxch/favourites/presentation/FavouritesViewModel.kt Adds TweaksRepository + sort rule into the existing combine; same latency and silent-swallow patterns as StarredReposViewModel.
feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/AppsViewModel.kt Moves app list loading into a combine with getAppsSortRule(), eliminating the previous flash race; OnSortRuleSelected correctly updates state immediately before the async DataStore write.
core/data/src/commonMain/kotlin/zed/rainxch/core/data/repository/TweaksRepositoryImpl.kt Adds three new DataStore keys and the corresponding get/set implementations; consistent with existing patterns.
feature/starred/presentation/src/commonMain/kotlin/zed/rainxch/starred/presentation/StarredReposRoot.kt Adds sort dropdown to StarredTopBar; icon hidden when list is empty; selected item shown with a leading check icon.
feature/favourites/presentation/src/commonMain/kotlin/zed/rainxch/favourites/presentation/FavouritesRoot.kt Adds sort dropdown to FavouritesTopbar; addresses the previously flagged active-sort-not-shown issue via leadingIcon checkmark.
feature/starred/presentation/src/commonMain/kotlin/zed/rainxch/starred/presentation/model/StarredSortRule.kt New enum with three options and a safe fromName() fallback; clean and correct.
feature/favourites/presentation/src/commonMain/kotlin/zed/rainxch/favourites/presentation/model/FavouritesSortRule.kt New enum with two options and a safe fromName() fallback; clean and correct.

Sequence Diagram

sequenceDiagram
    participant UI as UI (Root)
    participant VM as ViewModel
    participant DS as DataStore
    participant Combine as combine() flow

    Note over UI,Combine: Apps - immediate update
    UI->>VM: OnSortRuleSelected(rule)
    VM->>VM: "_state.update(sortRule = rule)"
    VM->>VM: filterApps() reorders filteredApps
    UI-->>UI: List reorders instantly
    VM->>DS: setAppsSortRule(rule) async
    DS-->>Combine: emits new rule
    Combine-->>VM: (apps, rule) _state.update + filterApps()

    Note over UI,Combine: Starred / Favourites - round-trip delay
    UI->>VM: OnSortRuleSelected(rule)
    VM->>DS: setSortRule(rule) async
    Note right of VM: state unchanged until DS emits
    DS-->>Combine: emits new rule
    Combine-->>VM: (items, rule) _state.update
    VM-->>UI: List reorders after DataStore round-trip
Loading

Fix All in Claude Code

Reviews (2): Last reviewed commit: "fix(apps): apply persisted sort before f..." | Re-trigger Greptile

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.

♻️ Duplicate comments (1)
feature/starred/presentation/src/commonMain/kotlin/zed/rainxch/starred/presentation/StarredReposViewModel.kt (1)

194-201: ⚠️ Potential issue | 🟠 Major | ⚑ Quick win

Narrow the exception catch in sort persistence.

At line 200, catching Throwable can swallow fatal runtime errors like OutOfMemoryError and StackOverflowError. Keep the CancellationException rethrow, but catch Exception instead for non-fatal failures.

Proposed fix
             is StarredReposAction.OnSortRuleSelected -> {
                 viewModelScope.launch {
                     try {
                         tweaksRepository.setStarredSortRule(action.sortRule.name)
                     } catch (e: CancellationException) {
                         throw e
-                    } catch (_: Throwable) {
+                    } catch (_: Exception) {
                     }
                 }
             }
πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/starred/presentation/src/commonMain/kotlin/zed/rainxch/starred/presentation/StarredReposViewModel.kt`
around lines 194 - 201, The catch-all Throwable in the OnSortRuleSelected
handler should be narrowed so fatal errors aren't swallowed; inside the
viewModelScope.launch block around
tweaksRepository.setStarredSortRule(action.sortRule.name) keep the existing
catch (e: CancellationException) { throw e } but replace catch (_: Throwable) {
} with catch (_: Exception) { } so only non-fatal exceptions are
suppressed/handled.
πŸ€– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In
`@feature/starred/presentation/src/commonMain/kotlin/zed/rainxch/starred/presentation/StarredReposViewModel.kt`:
- Around line 194-201: The catch-all Throwable in the OnSortRuleSelected handler
should be narrowed so fatal errors aren't swallowed; inside the
viewModelScope.launch block around
tweaksRepository.setStarredSortRule(action.sortRule.name) keep the existing
catch (e: CancellationException) { throw e } but replace catch (_: Throwable) {
} with catch (_: Exception) { } so only non-fatal exceptions are
suppressed/handled.

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ed74aedf-d3b0-4348-8eca-848a5cc684e9

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between b2e5ffe and 5f14105.

πŸ“’ Files selected for processing (31)
  • core/presentation/src/commonMain/composeResources/files/whatsnew/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/ar/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/bn/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/es/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/fr/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/hi/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/it/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/ja/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/ko/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/pl/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/ru/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/tr/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/zh-CN/18.json
  • core/presentation/src/commonMain/composeResources/values-ar/strings-ar.xml
  • core/presentation/src/commonMain/composeResources/values-bn/strings-bn.xml
  • core/presentation/src/commonMain/composeResources/values-es/strings-es.xml
  • core/presentation/src/commonMain/composeResources/values-fr/strings-fr.xml
  • core/presentation/src/commonMain/composeResources/values-hi/strings-hi.xml
  • core/presentation/src/commonMain/composeResources/values-it/strings-it.xml
  • core/presentation/src/commonMain/composeResources/values-ja/strings-ja.xml
  • core/presentation/src/commonMain/composeResources/values-ko/strings-ko.xml
  • core/presentation/src/commonMain/composeResources/values-pl/strings-pl.xml
  • core/presentation/src/commonMain/composeResources/values-ru/strings-ru.xml
  • core/presentation/src/commonMain/composeResources/values-tr/strings-tr.xml
  • core/presentation/src/commonMain/composeResources/values-zh-rCN/strings-zh-rCN.xml
  • core/presentation/src/commonMain/composeResources/values/strings.xml
  • feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/AppsViewModel.kt
  • feature/favourites/presentation/src/commonMain/kotlin/zed/rainxch/favourites/presentation/FavouritesRoot.kt
  • feature/favourites/presentation/src/commonMain/kotlin/zed/rainxch/favourites/presentation/FavouritesViewModel.kt
  • feature/starred/presentation/src/commonMain/kotlin/zed/rainxch/starred/presentation/StarredReposRoot.kt
  • feature/starred/presentation/src/commonMain/kotlin/zed/rainxch/starred/presentation/StarredReposViewModel.kt
βœ… Files skipped from review due to trivial changes (15)
  • core/presentation/src/commonMain/composeResources/files/whatsnew/hi/18.json
  • core/presentation/src/commonMain/composeResources/values-ar/strings-ar.xml
  • core/presentation/src/commonMain/composeResources/files/whatsnew/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/ru/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/bn/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/zh-CN/18.json
  • core/presentation/src/commonMain/composeResources/values-tr/strings-tr.xml
  • core/presentation/src/commonMain/composeResources/files/whatsnew/ja/18.json
  • core/presentation/src/commonMain/composeResources/values-hi/strings-hi.xml
  • core/presentation/src/commonMain/composeResources/values-zh-rCN/strings-zh-rCN.xml
  • core/presentation/src/commonMain/composeResources/files/whatsnew/it/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/fr/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/tr/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/es/18.json
  • core/presentation/src/commonMain/composeResources/files/whatsnew/pl/18.json
🚧 Files skipped from review as they are similar to previous changes (11)
  • core/presentation/src/commonMain/composeResources/values/strings.xml
  • core/presentation/src/commonMain/composeResources/values-ru/strings-ru.xml
  • core/presentation/src/commonMain/composeResources/values-ko/strings-ko.xml
  • core/presentation/src/commonMain/composeResources/values-ja/strings-ja.xml
  • core/presentation/src/commonMain/composeResources/values-bn/strings-bn.xml
  • core/presentation/src/commonMain/composeResources/values-es/strings-es.xml
  • feature/apps/presentation/src/commonMain/kotlin/zed/rainxch/apps/presentation/AppsViewModel.kt
  • core/presentation/src/commonMain/composeResources/files/whatsnew/ar/18.json
  • feature/favourites/presentation/src/commonMain/kotlin/zed/rainxch/favourites/presentation/FavouritesViewModel.kt
  • feature/favourites/presentation/src/commonMain/kotlin/zed/rainxch/favourites/presentation/FavouritesRoot.kt
  • feature/starred/presentation/src/commonMain/kotlin/zed/rainxch/starred/presentation/StarredReposRoot.kt

@rainxchzed rainxchzed merged commit 4112426 into main May 17, 2026
1 check was pending
@rainxchzed rainxchzed deleted the feat/library-section-sort branch May 17, 2026 04:53
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