Skip to content

feat: add intent to apply icon packs externally - #6643

Merged
SuperDragonXD merged 6 commits into
LawnchairLauncher:16-devfrom
wellorbetter:feature/apply-icon-pack-intent
Apr 20, 2026
Merged

feat: add intent to apply icon packs externally#6643
SuperDragonXD merged 6 commits into
LawnchairLauncher:16-devfrom
wellorbetter:feature/apply-icon-pack-intent

Conversation

@wellorbetter

@wellorbetter wellorbetter commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements #6594 — adds support for applying icon packs via an external intent (app.lawnchair.APPLY_ICONS), allowing third-party icon pack apps to directly apply their icon pack to Lawnchair.

Changes

  • New: ApplyIconPackActivity — handles the intent, validates the icon pack, and shows a Material3 confirmation dialog
  • Modified: AndroidManifest.xml — registers the activity with exported=true and intent-filter
  • Modified: strings.xml — adds dialog title/message strings
  • Modified: PreferenceViewModel.kt — makes iconPackIntents internal for reuse

How it works

  1. Icon pack app sends: Intent("app.lawnchair.APPLY_ICONS").putExtra("packageName", pkgName)
  2. Lawnchair validates the package is a legitimate icon pack
  3. Shows confirmation dialog with icon pack name and icon
  4. User confirms → icon pack is applied; cancels → activity finishes
  5. Invalid/missing package → activity finishes silently

Testing

  • Compiled successfully against lawnWithQuickstepGithubDebug

Closes #6594

Summary by CodeRabbit

  • New Features

    • Icon pack apply confirmation: a bottom sheet shows the pack name and preview with Cancel or Apply; Apply saves the chosen icon pack to preferences.
  • UI

    • Edge-to-edge, translucent-styled confirmation for a seamless, immersive experience.
  • Localization

    • Added "Apply icon pack" title for the confirmation UI.

@wellorbetter
wellorbetter marked this pull request as draft April 15, 2026 18:24
@coderabbitai

coderabbitai Bot commented Apr 15, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Added an exported Activity (ApplyIconPackActivity) that accepts an intent with packageName, resolves the corresponding icon pack (label + icon), shows a Compose modal confirmation sheet, and persists the selected package to preferences when applied.

Changes

Cohort / File(s) Summary
Manifest & Strings
lawnchair/AndroidManifest.xml, lawnchair/res/values/strings.xml
Added exported app.lawnchair.ui.ApplyIconPackActivity with intent-filter for app.lawnchair.APPLY_ICONS; added apply_icon_pack_title string.
Apply Icon Pack UI
lawnchair/src/app/lawnchair/ui/ApplyIconPackActivity.kt
New ComponentActivity that reads EXTRA_PACKAGE_NAME, validates it, resolves matching icon-pack activity/label/icon asynchronously, displays a Compose modal bottom sheet with Cancel/Apply, and writes iconPackPackage to preferences on Apply.
Preferences ViewModel
lawnchair/src/app/lawnchair/ui/preferences/PreferenceViewModel.kt
Changed iconPackIntents visibility from private to internal to allow reuse by the new activity.

Sequence Diagram

sequenceDiagram
    participant IconPackApp as IconPackApp
    participant ApplyActivity as ApplyActivity
    participant PrefViewModel as PrefViewModel
    participant Resolver as Resolver
    participant Prefs as Prefs
    participant UI as UI

    IconPackApp->>ApplyActivity: startActivity(intent with packageName)
    ApplyActivity->>ApplyActivity: validate packageName extra
    ApplyActivity->>PrefViewModel: read iconPackIntents
    ApplyActivity->>Resolver: resolve matching activity, label, icon (async)
    Resolver-->>ApplyActivity: label + icon
    ApplyActivity->>UI: show confirmation bottom sheet with icon & name
    UI-->>ApplyActivity: user action (Apply / Cancel / Dismiss)
    alt user confirms
        ApplyActivity->>Prefs: set iconPackPackage = packageName
        Prefs-->>ApplyActivity: persisted
    end
    ApplyActivity->>ApplyActivity: finish()
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • yasanglass
  • MrSluffy
  • validcube

Poem

🐰 I hopped in with a package name so bright,

Peeked at the icon, gave a small delight.
A sheet asked gently if these pixels may stay,
I brushed my whiskers — Apply! — and bounced away.

🚥 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 10.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add intent to apply icon packs externally' accurately summarizes the main change: adding an intent-based mechanism for external apps to apply icon packs to Lawnchair.
Description check ✅ Passed The PR description is comprehensive, covering implementation details, how the feature works, changes made, and testing status. All key information is present and well-organized.
Linked Issues check ✅ Passed The PR successfully implements all requirements from issue #6594: intent-based API with proper validation, user confirmation, graceful error handling, and restoration of legacy functionality.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the feature requirements. The visibility change to iconPackIntents and string resource additions are necessary supporting changes for the feature implementation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

📋 Issue Planner

Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).

View plan for ticket: #6594

✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code

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.

@coderabbitai
coderabbitai Bot requested review from MrSluffy and yasanglass April 15, 2026 18:24
@wellorbetter
wellorbetter force-pushed the feature/apply-icon-pack-intent branch from a308b97 to 8014ee0 Compare April 15, 2026 18:27
@yasanglass

Copy link
Copy Markdown
Member

Thank you for the contribution.

Once this is merged, we should also do PRs on these icon pack dashboards to add support for it:

Same for lawnicons of course: https://github.com/lawnchairlauncher/lawnicons

@wellorbetter
wellorbetter force-pushed the feature/apply-icon-pack-intent branch 2 times, most recently from 475563b to 4a5e94e Compare April 17, 2026 14:14
@wellorbetter
wellorbetter marked this pull request as ready for review April 17, 2026 15:41
@coderabbitai
coderabbitai Bot requested a review from validcube April 17, 2026 15:43

@wellorbetter wellorbetter left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ApplyIconPackActivity receives the intent, validates the package against iconPackIntents, shows a confirmation dialog, and writes to iconPackPackage via PreferenceManager — same path as the Settings UI. No extra abstractions, minimal visibility change (private → internal on iconPackIntents)

@validcube
validcube requested a review from SuperDragonXD April 17, 2026 16:42

@SuperDragonXD SuperDragonXD left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Hello, and thanks for the PR! I have a few suggestions to improve the UI of this feature.

Comment thread lawnchair/src/app/lawnchair/ui/ApplyIconPackActivity.kt
Comment thread lawnchair/src/app/lawnchair/ui/ApplyIconPackActivity.kt Outdated

@coderabbitai coderabbitai Bot left a comment

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.

♻️ Duplicate comments (1)
lawnchair/src/app/lawnchair/ui/ApplyIconPackActivity.kt (1)

72-73: ⚠️ Potential issue | 🟡 Minor

Return early when the package extra is missing.

finish() only schedules the activity to end, so without a return the rest of onCreate still executes: setContent is invoked, the LaunchedEffect launches, resolveIconPackInfo("") iterates all iconPackIntents and calls queryIntentActivities, and finish() is called again. For the invalid/missing-package path the issue spec requires finishing silently, so this wastes work (and briefly composes UI) on a hostile external invocation path.

🛠️ Proposed fix
-        val packPackageName = intent.getStringExtra(EXTRA_PACKAGE_NAME).orEmpty()
-        if (packPackageName.isEmpty()) finish()
+        val packPackageName = intent.getStringExtra(EXTRA_PACKAGE_NAME).orEmpty()
+        if (packPackageName.isEmpty()) {
+            finish()
+            return
+        }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lawnchair/src/app/lawnchair/ui/ApplyIconPackActivity.kt` around lines 72 -
73, The early-exit when the package extra is missing currently calls finish()
but continues executing onCreate; update the check around
intent.getStringExtra(EXTRA_PACKAGE_NAME) (packPackageName) to immediately
return after calling finish() so the rest of onCreate (setContent,
LaunchedEffect, resolveIconPackInfo and any queryIntentActivities) does not
execute for the invalid/missing-package path; ensure the change is applied in
ApplyIconPackActivity.onCreate so no UI is composed or background work launched
when packPackageName is empty.
🧹 Nitpick comments (1)
lawnchair/src/app/lawnchair/ui/ApplyIconPackActivity.kt (1)

88-108: Redundant scrim: drop the full-screen Surface wrapper.

ModalBottomSheet already renders its own scrim (defaulting to BottomSheetDefaults.ScrimColor) over the hosting window. Wrapping it in a Surface(fillMaxSize(), color = BottomSheetDefaults.ScrimColor) stacks another scrim-colored layer beneath the sheet's scrim, producing a doubly-dimmed backdrop. Since the activity's window is translucent by virtue of being behind a ModalBottomSheet, this Surface isn't providing a needed background either.

♻️ Proposed simplification
-                LawnchairTheme {
-                    EdgeToEdge()
-                    Surface(
-                        modifier = Modifier.fillMaxSize(),
-                        color = BottomSheetDefaults.ScrimColor,
-                    ) {
-                        ApplyIconPackSheet(
-                            packName = info.first,
-                            packIcon = info.second,
-                            onConfirm = {
-                                PreferenceManager.getInstance(this@ApplyIconPackActivity)
-                                    .iconPackPackage.set(packPackageName)
-                                finish()
-                            },
-                            onDismiss = { finish() },
-                        )
-                    }
-                }
+                LawnchairTheme {
+                    EdgeToEdge()
+                    ApplyIconPackSheet(
+                        packName = info.first,
+                        packIcon = info.second,
+                        onConfirm = {
+                            PreferenceManager.getInstance(this@ApplyIconPackActivity)
+                                .iconPackPackage.set(packPackageName)
+                            finish()
+                        },
+                        onDismiss = { finish() },
+                    )
+                }

(The Surface/fillMaxSize/BottomSheetDefaults imports on lines 29, 37 and the fillMaxSize import on line 26 can be removed if nothing else depends on them.)

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

In `@lawnchair/src/app/lawnchair/ui/ApplyIconPackActivity.kt` around lines 88 -
108, The Surface(...) wrapper that fills the screen with
BottomSheetDefaults.ScrimColor is redundant because ModalBottomSheet already
provides a scrim; in ApplyIconPackActivity remove the full-screen Surface (and
its Modifier.fillMaxSize() / color = BottomSheetDefaults.ScrimColor) so
ApplyIconPackSheet is placed directly inside the LawnchairTheme/EdgeToEdge
block, and then clean up any now-unused imports (Surface, fillMaxSize,
BottomSheetDefaults) at the top of the file.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@lawnchair/src/app/lawnchair/ui/ApplyIconPackActivity.kt`:
- Around line 72-73: The early-exit when the package extra is missing currently
calls finish() but continues executing onCreate; update the check around
intent.getStringExtra(EXTRA_PACKAGE_NAME) (packPackageName) to immediately
return after calling finish() so the rest of onCreate (setContent,
LaunchedEffect, resolveIconPackInfo and any queryIntentActivities) does not
execute for the invalid/missing-package path; ensure the change is applied in
ApplyIconPackActivity.onCreate so no UI is composed or background work launched
when packPackageName is empty.

---

Nitpick comments:
In `@lawnchair/src/app/lawnchair/ui/ApplyIconPackActivity.kt`:
- Around line 88-108: The Surface(...) wrapper that fills the screen with
BottomSheetDefaults.ScrimColor is redundant because ModalBottomSheet already
provides a scrim; in ApplyIconPackActivity remove the full-screen Surface (and
its Modifier.fillMaxSize() / color = BottomSheetDefaults.ScrimColor) so
ApplyIconPackSheet is placed directly inside the LawnchairTheme/EdgeToEdge
block, and then clean up any now-unused imports (Surface, fillMaxSize,
BottomSheetDefaults) at the top of the file.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a9cb1f41-bb73-42e2-a6d4-eff40d7b9e61

📥 Commits

Reviewing files that changed from the base of the PR and between 4a5e94e and 5dfefb9.

📒 Files selected for processing (1)
  • lawnchair/src/app/lawnchair/ui/ApplyIconPackActivity.kt

Comment thread lawnchair/src/app/lawnchair/ui/ApplyIconPackActivity.kt Outdated
Comment thread lawnchair/res/values/strings.xml Outdated
@x9136

x9136 commented Apr 19, 2026

Copy link
Copy Markdown
  1. Shows confirmation dialog with icon pack name and icon

I'd like to suggest make this optional. When people open an icon pack app, they're usually want to look at the icons or make an icon request—not to close a pop-up they didn't ask for. A simple fix would be to make this toggleable (either by the developer or the end user) and to include a dedicated 'Apply icon pack' button within the icon pack app ui.

I don't want people opening Lawnicons to deal with unnecessary sheet.

@wellorbetter

Copy link
Copy Markdown
Contributor Author
  1. Shows confirmation dialog with icon pack name and icon

I'd like to suggest make this optional. When people open an icon pack app, they're usually want to look at the icons or make an icon request—not to close a pop-up they didn't ask for. A simple fix would be to make this toggleable (either by the developer or the end user) and to include a dedicated 'Apply icon pack' button within the icon pack app ui.

I don't want people opening Lawnicons to deal with unnecessary sheet.

Thanks for the concern! This doesn't show any pop-up on app launch. The implementation adds a button in the toolbar that
users tap intentionally — nothing automatic.

See the Lawnicons side implementation here: LawnchairLauncher/lawnicons#3602

@wellorbetter
wellorbetter force-pushed the feature/apply-icon-pack-intent branch from c685fba to 2e07ebd Compare April 19, 2026 07:57
wellorbetter and others added 5 commits April 19, 2026 15:59
Add ApplyIconPackActivity that handles app.lawnchair.APPLY_ICONS intent,
allowing third-party icon pack apps to directly apply their icon pack
to Lawnchair without requiring users to navigate to settings.

- Register activity with intent-filter in AndroidManifest
- Validate icon pack before showing confirmation dialog
- Reuse iconPackIntents from PreferenceViewModel
- Move resolveIconPackInfo() into LaunchedEffect with Dispatchers.Default
  to avoid PM queries and loadIcon() on the main thread
- Replace non-null assertions with smart cast
- Remove early return after finish()
- Replace AlertDialog with ModalBottomSheet + ModalBottomSheetContent
- Use PreferenceGroup + PreferenceTemplate for icon pack display
- Align button style with existing bottom sheet patterns
ModalBottomSheet already renders its own scrim, the extra Surface
with ScrimColor produced a doubly-dimmed backdrop.
@wellorbetter
wellorbetter force-pushed the feature/apply-icon-pack-intent branch from 2e07ebd to 7cea544 Compare April 19, 2026 07:59

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (2)
lawnchair/src/app/lawnchair/ui/ApplyIconPackActivity.kt (2)

79-86: Use Dispatchers.IO for PackageManager queries.

PackageManager.queryIntentActivities, loadLabel, and loadIcon are I/O-bound (IPC + potential resource loading from the other app's APK). Prefer Dispatchers.IO over Dispatchers.Default to avoid tying up CPU-bound workers.

♻️ Proposed change
-            LaunchedEffect(packPackageName) {
-                val result = withContext(Dispatchers.Default) {
-                    resolveIconPackInfo(packPackageName)
-                }
+            LaunchedEffect(packPackageName) {
+                val result = withContext(Dispatchers.IO) {
+                    resolveIconPackInfo(packPackageName)
+                }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lawnchair/src/app/lawnchair/ui/ApplyIconPackActivity.kt` around lines 79 -
86, The coroutine dispatched inside the LaunchedEffect uses Dispatchers.Default
for PackageManager work; change it to Dispatchers.IO so I/O-bound operations in
resolveIconPackInfo (and any calls to PackageManager.queryIntentActivities,
loadLabel, loadIcon) run on the IO dispatcher: update the withContext call in
the LaunchedEffect that references packPackageName / resolveIconPackInfo to use
Dispatchers.IO, leaving the rest of the logic (assigning packInfo, setting
resolved, calling finish()) unchanged.

95-101: Animate the sheet away before finishing on confirm.

onConfirm calls finish() synchronously, so the bottom sheet pops out abruptly without the dismissal animation. Consider hiding the sheet state first (or deferring finish() via a coroutine tied to sheetState.hide()) so Confirm and Cancel behave consistently in terms of UX.

Also worth noting: once the preference write completes, there's no user-visible feedback (toast/snackbar) that the pack was applied — minor, but could feel opaque since the activity simply vanishes.

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

In `@lawnchair/src/app/lawnchair/ui/ApplyIconPackActivity.kt` around lines 95 -
101, The onConfirm lambda currently writes the preference then calls finish()
immediately, causing the bottom sheet to close abruptly; instead launch a
coroutine (e.g., using lifecycleScope) to first call sheetState.hide() and await
its completion, then perform
PreferenceManager.getInstance(this@ApplyIconPackActivity).iconPackPackage.set(packPackageName)
and finally call finish(); also consider showing a short user-visible
confirmation (Toast or Snackbar) after the hide completes and before finish to
indicate the pack was applied.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@lawnchair/src/app/lawnchair/ui/ApplyIconPackActivity.kt`:
- Around line 79-86: The coroutine dispatched inside the LaunchedEffect uses
Dispatchers.Default for PackageManager work; change it to Dispatchers.IO so
I/O-bound operations in resolveIconPackInfo (and any calls to
PackageManager.queryIntentActivities, loadLabel, loadIcon) run on the IO
dispatcher: update the withContext call in the LaunchedEffect that references
packPackageName / resolveIconPackInfo to use Dispatchers.IO, leaving the rest of
the logic (assigning packInfo, setting resolved, calling finish()) unchanged.
- Around line 95-101: The onConfirm lambda currently writes the preference then
calls finish() immediately, causing the bottom sheet to close abruptly; instead
launch a coroutine (e.g., using lifecycleScope) to first call sheetState.hide()
and await its completion, then perform
PreferenceManager.getInstance(this@ApplyIconPackActivity).iconPackPackage.set(packPackageName)
and finally call finish(); also consider showing a short user-visible
confirmation (Toast or Snackbar) after the hide completes and before finish to
indicate the pack was applied.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b6e6fb7e-8a5e-44d5-b415-800421307834

📥 Commits

Reviewing files that changed from the base of the PR and between 0927958 and 7cea544.

📒 Files selected for processing (4)
  • lawnchair/AndroidManifest.xml
  • lawnchair/res/values/strings.xml
  • lawnchair/src/app/lawnchair/ui/ApplyIconPackActivity.kt
  • lawnchair/src/app/lawnchair/ui/preferences/PreferenceViewModel.kt
✅ Files skipped from review due to trivial changes (2)
  • lawnchair/res/values/strings.xml
  • lawnchair/AndroidManifest.xml
🚧 Files skipped from review as they are similar to previous changes (1)
  • lawnchair/src/app/lawnchair/ui/preferences/PreferenceViewModel.kt

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (2)
lawnchair/src/app/lawnchair/ui/ApplyIconPackActivity.kt (2)

65-105: Consider calling setResult() before finish() for external callers.

Since the activity is exported=true and can be launched with startActivityForResult, third-party icon pack apps have no way to distinguish apply vs. cancel vs. invalid-package. Calling setResult(RESULT_OK) on confirm and setResult(RESULT_CANCELED) on dismiss/invalid package is a small improvement that makes the public intent contract more useful.

♻️ Suggested change
         val packPackageName = intent.getStringExtra(EXTRA_PACKAGE_NAME).orEmpty()
         if (packPackageName.isEmpty()) {
+            setResult(RESULT_CANCELED)
             finish()
             return
         }
@@
                 packInfo = result
                 resolved = true
-                if (result == null) finish()
+                if (result == null) {
+                    setResult(RESULT_CANCELED)
+                    finish()
+                }
             }
@@
                         onConfirm = {
                             PreferenceManager.getInstance(this@ApplyIconPackActivity)
                                 .iconPackPackage.set(packPackageName)
+                            setResult(RESULT_OK)
                             finish()
                         },
-                        onDismiss = { finish() },
+                        onDismiss = {
+                            setResult(RESULT_CANCELED)
+                            finish()
+                        },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lawnchair/src/app/lawnchair/ui/ApplyIconPackActivity.kt` around lines 65 -
105, The activity currently just calls finish() for
confirm/dismiss/invalid-package; update ApplyIconPackActivity so it calls
setResult(RESULT_OK) before finish() when the user confirms (inside the
onConfirm handler where PreferenceManager.iconPackPackage is set) and call
setResult(RESULT_CANCELED) before finish() both in the onDismiss handler and
where you early-return when EXTRA_PACKAGE_NAME is empty or
resolveIconPackInfo(packPackageName) returns null (use the same spot after
LaunchedEffect resolves). This ensures callers using startActivityForResult can
distinguish confirm vs cancel/invalid while keeping existing behavior.

95-99: Move preference write to background thread for consistency with this PR's pattern.

The onConfirm callback invokes iconPackPackage.set(packPackageName) directly on the main thread. While SharedPreferences.apply() is asynchronous (non-blocking), this PR already establishes a pattern of moving I/O operations like PackageManager.queryIntentActivities() to Dispatchers.IO (line 80). Applying the same pattern here would be more consistent with the codebase intent.

♻️ Suggested change
-                        onConfirm = {
-                            PreferenceManager.getInstance(this@ApplyIconPackActivity)
-                                .iconPackPackage.set(packPackageName)
-                            finish()
-                        },
+                        onConfirm = {
+                            lifecycleScope.launch {
+                                withContext(Dispatchers.IO) {
+                                    PreferenceManager.getInstance(this@ApplyIconPackActivity)
+                                        .iconPackPackage.set(packPackageName)
+                                }
+                                finish()
+                            }
+                        },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lawnchair/src/app/lawnchair/ui/ApplyIconPackActivity.kt` around lines 95 -
99, The onConfirm callback in ApplyIconPackActivity currently calls
PreferenceManager.getInstance(this@ApplyIconPackActivity).iconPackPackage.set(packPackageName)
on the main thread; move the preference write to a background coroutine using
Dispatchers.IO (e.g., launch(Dispatchers.IO) or withContext(Dispatchers.IO)) so
the set call runs off the UI thread, then return to the main thread to call
finish() if needed; update the onConfirm block to perform the
iconPackPackage.set(packPackageName) inside an IO coroutine and ensure finish()
executes on the main dispatcher afterwards.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@lawnchair/src/app/lawnchair/ui/ApplyIconPackActivity.kt`:
- Around line 65-105: The activity currently just calls finish() for
confirm/dismiss/invalid-package; update ApplyIconPackActivity so it calls
setResult(RESULT_OK) before finish() when the user confirms (inside the
onConfirm handler where PreferenceManager.iconPackPackage is set) and call
setResult(RESULT_CANCELED) before finish() both in the onDismiss handler and
where you early-return when EXTRA_PACKAGE_NAME is empty or
resolveIconPackInfo(packPackageName) returns null (use the same spot after
LaunchedEffect resolves). This ensures callers using startActivityForResult can
distinguish confirm vs cancel/invalid while keeping existing behavior.
- Around line 95-99: The onConfirm callback in ApplyIconPackActivity currently
calls
PreferenceManager.getInstance(this@ApplyIconPackActivity).iconPackPackage.set(packPackageName)
on the main thread; move the preference write to a background coroutine using
Dispatchers.IO (e.g., launch(Dispatchers.IO) or withContext(Dispatchers.IO)) so
the set call runs off the UI thread, then return to the main thread to call
finish() if needed; update the onConfirm block to perform the
iconPackPackage.set(packPackageName) inside an IO coroutine and ensure finish()
executes on the main dispatcher afterwards.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0ad6d95e-f561-4d23-87e1-ddeecf88b3b1

📥 Commits

Reviewing files that changed from the base of the PR and between 7cea544 and 4bc9137.

📒 Files selected for processing (1)
  • lawnchair/src/app/lawnchair/ui/ApplyIconPackActivity.kt

@SuperDragonXD SuperDragonXD left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks! Merging this now.

@SuperDragonXD
SuperDragonXD merged commit 604c42f into LawnchairLauncher:16-dev Apr 20, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Add intent to apply icon packs

5 participants