fix: Remove hidden and uninstalled apps from drawer folders - #7107
fix: Remove hidden and uninstalled apps from drawer folders#7107pvolkov wants to merge 3 commits into
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (4)
📝 WalkthroughWalkthroughThis PR adds folder membership cleanup for hidden apps, removed packages, and malformed folder entries. It extends the folder DAO and service, wires cleanup into preference and package-removal flows, and prunes stale entries during All Apps folder loading and rendering. ChangesFolder membership cleanup
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant HiddenAppsPreference
participant PackageUpdatedTask
participant LawnchairAlphabeticalAppsList
participant FolderService
participant FolderDao
HiddenAppsPreference->>FolderService: removeItemsByComponentKeys(hidden component keys)
PackageUpdatedTask->>FolderService: removePackagesBlocking(context, packages)
LawnchairAlphabeticalAppsList->>FolderService: removeItemsByComponentKeys(stale keys)
FolderService->>FolderDao: Delete matching folder items
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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 `@lawnchair/src/app/lawnchair/allapps/LawnchairAlphabeticalAppsList.kt`:
- Around line 99-112: Update the stale-key filtering in the folder cleanup logic
around ComponentKey.fromString and appsStore.getApp so a missing appsStore entry
is removed only when the package/component is confirmed permanently removed for
that component user. Preserve folder membership for temporarily unavailable
apps, such as those removed during external-media unmount, while retaining
cleanup for explicitly hidden or invalid entries.
In `@lawnchair/src/app/lawnchair/data/folder/service/FolderDao.kt`:
- Around line 34-35: Update FolderDao.deleteFolderItemsByPackagePattern and its
FolderService caller to use a literal package-prefix comparison rather than LIKE
pattern matching, passing packageName directly so underscores and other package
characters remain literal.
🪄 Autofix
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: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 2edbebc8-5ca6-4d1c-a84e-53cac5232f3a
📒 Files selected for processing (5)
lawnchair/src/app/lawnchair/allapps/LawnchairAlphabeticalAppsList.ktlawnchair/src/app/lawnchair/data/folder/service/FolderDao.ktlawnchair/src/app/lawnchair/data/folder/service/FolderService.ktlawnchair/src/app/lawnchair/preferences2/PreferenceManager2.ktsrc/com/android/launcher3/model/PackageUpdatedTask.java
| @Query("DELETE FROM FolderItems WHERE item_info LIKE :packagePattern") | ||
| suspend fun deleteFolderItemsByPackagePattern(packagePattern: String) |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Use a literal package-prefix comparison.
At Line 34, LIKE interprets _ in a package name as a wildcard. Removing com.example_a can also remove folder membership for a matching package such as com.exampleXa. Use a literal prefix comparison instead of a pattern match.
Proposed fix
- `@Query`("DELETE FROM FolderItems WHERE item_info LIKE :packagePattern")
- suspend fun deleteFolderItemsByPackagePattern(packagePattern: String)
+ `@Query`(
+ """
+ DELETE FROM FolderItems
+ WHERE substr(item_info, 1, length(:packageName) + 1) = :packageName || '/'
+ """,
+ )
+ suspend fun deleteFolderItemsByPackageName(packageName: String)Update FolderService to pass packageName directly.
📝 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.
| @Query("DELETE FROM FolderItems WHERE item_info LIKE :packagePattern") | |
| suspend fun deleteFolderItemsByPackagePattern(packagePattern: String) | |
| `@Query`( | |
| """ | |
| DELETE FROM FolderItems | |
| WHERE substr(item_info, 1, length(:packageName) + 1) = :packageName || '/' | |
| """, | |
| ) | |
| suspend fun deleteFolderItemsByPackageName(packageName: String) |
🤖 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 `@lawnchair/src/app/lawnchair/data/folder/service/FolderDao.kt` around lines 34
- 35, Update FolderDao.deleteFolderItemsByPackagePattern and its FolderService
caller to use a literal package-prefix comparison rather than LIKE pattern
matching, passing packageName directly so underscores and other package
characters remain literal.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
lawnchair/src/app/lawnchair/allapps/LawnchairAlphabeticalAppsList.kt (1)
106-109: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winSerialize stale-folder cleanup with folder membership writes.
staleKeysis a snapshot, and the delete runs onDispatchers.IO. A folder membership written after this snapshot can be deleted becauseremoveItemsByComponentKeysonly matches component keys. Revalidate the current hidden state before deletion, or perform cleanup in the same serialized update path that writes membership rows.🤖 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 `@lawnchair/src/app/lawnchair/allapps/LawnchairAlphabeticalAppsList.kt` around lines 106 - 109, Update the stale-folder cleanup in LawnchairAlphabeticalAppsList so it does not delete membership rows based only on the earlier staleKeys snapshot. Recheck the current hidden/membership state at delete time, or move the cleanup into the same serialized update path used by the folder membership writer in FolderService.INSTANCE.get(context).removeItemsByComponentKeys. Keep the scope limited to the launch/withContext(Dispatchers.IO) cleanup path and preserve existing deletion behavior for entries that are still truly stale.
🤖 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.
Outside diff comments:
In `@lawnchair/src/app/lawnchair/allapps/LawnchairAlphabeticalAppsList.kt`:
- Around line 106-109: Update the stale-folder cleanup in
LawnchairAlphabeticalAppsList so it does not delete membership rows based only
on the earlier staleKeys snapshot. Recheck the current hidden/membership state
at delete time, or move the cleanup into the same serialized update path used by
the folder membership writer in
FolderService.INSTANCE.get(context).removeItemsByComponentKeys. Keep the scope
limited to the launch/withContext(Dispatchers.IO) cleanup path and preserve
existing deletion behavior for entries that are still truly stale.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 7ee19d50-1732-466a-8f4a-271245ddcc9c
📒 Files selected for processing (3)
lawnchair/src/app/lawnchair/allapps/LawnchairAlphabeticalAppsList.ktlawnchair/src/app/lawnchair/data/folder/service/FolderDao.ktlawnchair/src/app/lawnchair/data/folder/service/FolderService.kt
🚧 Files skipped from review as they are similar to previous changes (1)
- lawnchair/src/app/lawnchair/data/folder/service/FolderService.kt
Keep folder membership and counts accurate when apps are hidden or uninstalled. Co-authored-by: Cursor <cursoragent@cursor.com>
Avoid pruning temporarily unavailable apps from drawer folders, and delete by literal package prefix instead of LIKE. Co-authored-by: Cursor <cursoragent@cursor.com>
Avoid deleting apps that were unhidden or re-added after the staleKeys snapshot was taken. Co-authored-by: Cursor <cursoragent@cursor.com>
236d8c6 to
6298d59
Compare
Description
Drawer folder membership stayed in Room after apps were hidden or uninstalled, so folder counts and contents could show stale entries until the folder was edited manually. This PR prunes folder items when apps are hidden or removed, filters hidden apps out of folder resolution, and cleans up leftover membership when the All Apps list updates.
Reasoning
Folder membership is stored separately from the apps store and was never pruned on hide/uninstall. Hidden apps also bypassed filtering when building drawer folders, so they could still appear inside a folder. Cleaning membership on those events (and as a safety net when the apps list refreshes) keeps counts and picker state consistent without requiring a manual folder edit.
Testing
Type of change
✅ Bug fix (A non-breaking change that fixes an issue)
❌ New feature (A non-breaking change that adds functionality)
❌ Breaking change (A fix or feature that would cause existing functionality to not work as expected)
❌ Refactor (A code change that neither fixes a bug nor adds a feature)
❌ Performance (A code change that improves performance)
❌ Style (Code style changes)
❌ Docs (Changes to documentation)
❌ Chore (Changes to the build process or other tooling)
Summary by CodeRabbit