From 1d2798ba4fd1a40836999db57a4646824a0cf8de Mon Sep 17 00:00:00 2001 From: MM20 <15646950+MM2-0@users.noreply.github.com> Date: Fri, 24 Oct 2025 19:59:15 +0200 Subject: [PATCH] Add cloned profile support Close #1364 --- .../src/main/java/de/mm20/launcher2/profiles/Profile.kt | 5 +++++ .../main/java/de/mm20/launcher2/profiles/ProfileManager.kt | 7 +++++-- .../launcher2/badges/providers/ProfileBadgeProvider.kt | 6 ++++++ .../main/java/de/mm20/launcher2/search/SearchService.kt | 4 ++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/core/base/src/main/java/de/mm20/launcher2/profiles/Profile.kt b/core/base/src/main/java/de/mm20/launcher2/profiles/Profile.kt index 4f74a618d..eadd4d686 100644 --- a/core/base/src/main/java/de/mm20/launcher2/profiles/Profile.kt +++ b/core/base/src/main/java/de/mm20/launcher2/profiles/Profile.kt @@ -37,6 +37,11 @@ data class Profile( * The private space profile (Android 15+) */ Private, + + /** + * Cloned apps profile + */ + Cloned, } data class State( diff --git a/core/profiles/src/main/java/de/mm20/launcher2/profiles/ProfileManager.kt b/core/profiles/src/main/java/de/mm20/launcher2/profiles/ProfileManager.kt index a692f0fe5..2e5044826 100644 --- a/core/profiles/src/main/java/de/mm20/launcher2/profiles/ProfileManager.kt +++ b/core/profiles/src/main/java/de/mm20/launcher2/profiles/ProfileManager.kt @@ -43,15 +43,16 @@ class ProfileManager( private val scope = CoroutineScope(Dispatchers.Default + Job()) /** - * An array of exactly 3 profiles with their states. + * An array of exactly 4 profiles with their states. * - Index 0: Personal profile * - Index 1: Work profile * - Index 2: Private profile + * - Index 3: Cloned profile * * Profiles that don't exist are null. */ private val profileStates: MutableStateFlow> = - MutableStateFlow(arrayOf(null, null, null)) + MutableStateFlow(arrayOf(null, null, null, null)) /** * List of profiles that are active and unlocked. @@ -116,6 +117,7 @@ class ProfileManager( Profile.Type.Personal -> 0 Profile.Type.Work -> 1 Profile.Type.Private -> 2 + Profile.Type.Cloned -> 3 } if (profiles[index] == null) { @@ -151,6 +153,7 @@ class ProfileManager( return when (launcherUserInfo?.userType) { UserManager.USER_TYPE_PROFILE_PRIVATE -> Profile.Type.Private UserManager.USER_TYPE_PROFILE_MANAGED -> Profile.Type.Work + UserManager.USER_TYPE_PROFILE_CLONE -> Profile.Type.Cloned else -> Profile.Type.Personal } diff --git a/services/badges/src/main/java/de/mm20/launcher2/badges/providers/ProfileBadgeProvider.kt b/services/badges/src/main/java/de/mm20/launcher2/badges/providers/ProfileBadgeProvider.kt index 1417a1de7..a45f6e0bb 100644 --- a/services/badges/src/main/java/de/mm20/launcher2/badges/providers/ProfileBadgeProvider.kt +++ b/services/badges/src/main/java/de/mm20/launcher2/badges/providers/ProfileBadgeProvider.kt @@ -1,6 +1,7 @@ package de.mm20.launcher2.badges.providers import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.ContentCopy import androidx.compose.material.icons.rounded.Lock import androidx.compose.material.icons.rounded.Work import de.mm20.launcher2.badges.Badge @@ -33,6 +34,7 @@ class ProfileBadgeProvider : BadgeProvider, KoinComponent { when(it?.type) { Profile.Type.Work -> WorkProfile Profile.Type.Private -> PrivateProfile + Profile.Type.Cloned -> ClonedProfile else -> null } } @@ -50,5 +52,9 @@ class ProfileBadgeProvider : BadgeProvider, KoinComponent { private val PrivateProfile = Badge( icon = BadgeIcon(Icons.Rounded.PrivateSpace) ) + + private val ClonedProfile = Badge( + icon = BadgeIcon(Icons.Rounded.ContentCopy) + ) } } \ No newline at end of file diff --git a/services/search/src/main/java/de/mm20/launcher2/search/SearchService.kt b/services/search/src/main/java/de/mm20/launcher2/search/SearchService.kt index e20ba980c..3937558d8 100644 --- a/services/search/src/main/java/de/mm20/launcher2/search/SearchService.kt +++ b/services/search/src/main/java/de/mm20/launcher2/search/SearchService.kt @@ -276,6 +276,7 @@ internal class SearchServiceImpl( val standardProfile = profiles.find { it.type == Profile.Type.Personal } val workProfile = profiles.find { it.type == Profile.Type.Work } val privateSpace = profiles.find { it.type == Profile.Type.Private } + val clonedProfile = profiles.find { it.type == Profile.Type.Cloned } appRepository.search("", false) .withCustomLabels(customAttributesRepository) .map { apps -> @@ -287,6 +288,9 @@ internal class SearchServiceImpl( standardProfile != null && app.user == standardProfile.userHandle -> standardProfileApps.add( app ) + clonedProfile != null && app.user == clonedProfile.userHandle -> standardProfileApps.add( + app + ) workProfile != null && app.user == workProfile.userHandle -> workProfileApps.add( app