mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-27 23:36:47 +00:00
Merge branch '15-dev' into 16-dev-qpr1
Signed-off-by: Pun Butrach <pun.butrach@gmail.com>
This commit is contained in:
@@ -166,6 +166,8 @@
|
||||
<string name="home_screen_label">Home screen</string>
|
||||
<string name="home_screen_description">Feed, grid, icons</string>
|
||||
|
||||
<string name="home_screen_actions">Home screen actions</string>
|
||||
|
||||
<string name="dock_label">Dock</string>
|
||||
<string name="dock_description">Search bar, icon count</string>
|
||||
|
||||
@@ -277,6 +279,9 @@
|
||||
<string name="reset_custom_icons">Reset custom icons</string>
|
||||
<string name="reset_custom_icons_confirmation">All custom icons will be reset. Do you want to continue?</string>
|
||||
|
||||
<string name="remove_all_views_from_home_screen">Clear home screen</string>
|
||||
<string name="remove_all_views_from_home_screen_desc">Home screen will be cleared. Do you want to continue?</string>
|
||||
|
||||
<!-- Icon picker -->
|
||||
<string name="icon_picker_default_category">Icons</string>
|
||||
<string name="icon_picker_reset_to_default">Reset to default</string>
|
||||
@@ -777,7 +782,7 @@
|
||||
|
||||
-->
|
||||
<!-- Launcher strings used -->
|
||||
<string name="all_apps_device_search_hint">Search apps, web, and more</string>
|
||||
<string name="all_apps_device_search_hint">Search web and more</string>
|
||||
<string name="all_apps_search_bar_hint">Search apps</string>
|
||||
<string name="all_apps_no_search_results">No apps found matching \"<xliff:g example="Android" id="query">%1$s</xliff:g>\"</string>
|
||||
|
||||
@@ -909,4 +914,6 @@
|
||||
<string name="grant_requested_permissions">Grant permissions</string>
|
||||
<string name="permissions_needed">Permissions needed</string>
|
||||
<string name="grant_requested_permissions_tap">Tap to grant permissions</string>
|
||||
<!-- Message shown when all home screen views are removed -->
|
||||
<string name="home_screen_all_views_removed_msg">Home screen cleared</string>
|
||||
</resources>
|
||||
|
||||
@@ -7,10 +7,10 @@ import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import app.lawnchair.data.folder.model.FolderOrderUtils
|
||||
import app.lawnchair.data.folder.model.FolderViewModel
|
||||
import app.lawnchair.flowerpot.Flowerpot
|
||||
import app.lawnchair.launcher
|
||||
import app.lawnchair.preferences.PreferenceManager
|
||||
import app.lawnchair.preferences2.PreferenceManager2
|
||||
import app.lawnchair.util.categorizeAppsWithSystemAndGoogle
|
||||
import com.android.launcher3.InvariantDeviceProfile.OnIDPChangeListener
|
||||
import com.android.launcher3.allapps.AllAppsStore
|
||||
import com.android.launcher3.allapps.AlphabeticalAppsList
|
||||
@@ -45,7 +45,6 @@ class LawnchairAlphabeticalAppsList<T>(
|
||||
private val filteredList = mutableListOf<AppInfo>()
|
||||
|
||||
private val folderOrder = FolderOrderUtils.stringToIntList(prefs.drawerListOrder.get())
|
||||
private val potsManager = Flowerpot.Manager.getInstance(context)
|
||||
|
||||
init {
|
||||
context.launcher.deviceProfile.inv.addOnChangeListener(this)
|
||||
@@ -88,8 +87,10 @@ class LawnchairAlphabeticalAppsList<T>(
|
||||
if (isWorkOrPrivateSpace(appList)) return super.addAppsWithSections(appList, position)
|
||||
|
||||
if (!drawerListDefault) {
|
||||
val categorizedApps = potsManager.categorizeApps(appList)
|
||||
categorizedApps.forEach { (category, apps) ->
|
||||
val validApps = appList.mapNotNull { it }
|
||||
val finalCategorizedApps = categorizeAppsWithSystemAndGoogle(validApps, context)
|
||||
|
||||
finalCategorizedApps.forEach { (category, apps) ->
|
||||
if (apps.size == 1) {
|
||||
mAdapterItems.add(AdapterItem.asApp(apps.first()))
|
||||
} else {
|
||||
|
||||
@@ -6,6 +6,7 @@ import app.lawnchair.LawnchairLauncher
|
||||
import app.lawnchair.flowerpot.Flowerpot
|
||||
import app.lawnchair.launcher
|
||||
import app.lawnchair.launcherNullable
|
||||
import app.lawnchair.util.categorizeAppsWithSystemAndGoogle
|
||||
import app.lawnchair.util.restartLauncher
|
||||
import com.android.launcher3.InvariantDeviceProfile
|
||||
import com.android.launcher3.LauncherAppState
|
||||
@@ -17,6 +18,7 @@ import com.android.launcher3.model.data.FolderInfo
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo
|
||||
import com.android.launcher3.provider.RestoreDbTask
|
||||
import com.android.launcher3.util.ComponentKey
|
||||
import com.android.launcher3.util.PackageManagerHelper
|
||||
import java.io.File
|
||||
import java.util.Locale
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
@@ -101,9 +103,8 @@ class LawndeckManager(private val context: Context) {
|
||||
|
||||
onProgress?.invoke("Categorizing apps...")
|
||||
|
||||
// Use flowerpot to categorize apps
|
||||
val potsManager = Flowerpot.Manager.getInstance(context)
|
||||
val categorizedApps = potsManager.categorizeApps(apps.map { it as? AppInfo })
|
||||
val validApps = apps.mapNotNull { it as? AppInfo }
|
||||
val finalCategorizedApps = categorizeAppsWithSystemAndGoogle(validApps, context)
|
||||
|
||||
onProgress?.invoke("Adding apps to workspace...")
|
||||
|
||||
@@ -115,7 +116,7 @@ class LawndeckManager(private val context: Context) {
|
||||
var singleAppCount = 0
|
||||
|
||||
// Process each category
|
||||
categorizedApps.forEach { (category, categoryApps) ->
|
||||
finalCategorizedApps.forEach { (category, categoryApps) ->
|
||||
if (categoryApps.isEmpty()) return@forEach
|
||||
|
||||
if (categoryApps.size == 1) {
|
||||
@@ -188,22 +189,32 @@ class LawndeckManager(private val context: Context) {
|
||||
val activityInfo = activities[0]
|
||||
val appInfo = AppInfo(context, activityInfo, user)
|
||||
|
||||
// Use flowerpot to categorize the app
|
||||
val potsManager = Flowerpot.Manager.getInstance(context)
|
||||
val categorizedApps = potsManager.categorizeApps(listOf(appInfo))
|
||||
val intent = appInfo.intent
|
||||
|
||||
if (categorizedApps.isEmpty()) {
|
||||
// No category found, add directly to workspace
|
||||
ItemInstallQueue.INSTANCE.get(context).queueItem(packageName, user)
|
||||
return
|
||||
}
|
||||
// Determine category: Google Apps > System Apps > Flowerpot categories
|
||||
val category = when {
|
||||
packageName.startsWith("com.google.") -> "Google Apps"
|
||||
|
||||
// Get the category for this app (categorizedApps is a Map<String, List<AppInfo>>)
|
||||
val categoryEntry = categorizedApps.entries.firstOrNull() ?: run {
|
||||
ItemInstallQueue.INSTANCE.get(context).queueItem(packageName, user)
|
||||
return
|
||||
intent != null && PackageManagerHelper.isSystemApp(context, intent) -> "System Apps"
|
||||
|
||||
else -> {
|
||||
// Use flowerpot to categorize the app
|
||||
val potsManager = Flowerpot.Manager.getInstance(context)
|
||||
val categorizedApps = potsManager.categorizeApps(listOf(appInfo))
|
||||
|
||||
if (categorizedApps.isEmpty()) {
|
||||
// No category found, add directly to workspace
|
||||
ItemInstallQueue.INSTANCE.get(context).queueItem(packageName, user)
|
||||
return
|
||||
}
|
||||
|
||||
// Get the category from flowerpot
|
||||
categorizedApps.entries.firstOrNull()?.key ?: run {
|
||||
ItemInstallQueue.INSTANCE.get(context).queueItem(packageName, user)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
val category = categoryEntry.key
|
||||
|
||||
// Check if there's already a folder for this category on workspace
|
||||
val existingFolder = findFolderByCategory(category, dataModel)
|
||||
|
||||
@@ -44,6 +44,7 @@ import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
|
||||
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
|
||||
import app.lawnchair.ui.preferences.navigation.HomeScreenGrid
|
||||
import app.lawnchair.util.collectAsStateBlocking
|
||||
import com.android.launcher3.LauncherAppState
|
||||
import com.android.launcher3.R
|
||||
import com.android.launcher3.Utilities
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -67,6 +68,7 @@ fun HomeScreenPreferences(
|
||||
) {
|
||||
val lockHomeScreenAdapter = prefs2.lockHomeScreen.getAdapter()
|
||||
val showDeckLayout = prefs2.showDeckLayout.getAdapter().state.value
|
||||
val context = LocalContext.current
|
||||
|
||||
if (showDeckLayout) {
|
||||
HomeLayoutSettings()
|
||||
@@ -101,6 +103,20 @@ fun HomeScreenPreferences(
|
||||
)
|
||||
}
|
||||
}
|
||||
PreferenceGroup(heading = stringResource(id = R.string.home_screen_actions)) {
|
||||
Item {
|
||||
ClickablePreference(
|
||||
label = stringResource(id = R.string.remove_all_views_from_home_screen),
|
||||
confirmationText = stringResource(id = R.string.remove_all_views_from_home_screen_desc),
|
||||
onClick = {
|
||||
scope.launch {
|
||||
LauncherAppState.getInstance(context).clearAllViewsFromHomeScreen()
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
PreferenceGroup(heading = stringResource(id = R.string.minus_one)) {
|
||||
val feedAvailable = OverlayCallbackImpl.minusOneAvailable(LocalContext.current)
|
||||
val enableFeedAdapter = prefs2.enableFeed.getAdapter()
|
||||
PreferenceGroup(heading = stringResource(id = R.string.minus_one)) {
|
||||
|
||||
54
lawnchair/src/app/lawnchair/util/AppCategorizationUtils.kt
Normal file
54
lawnchair/src/app/lawnchair/util/AppCategorizationUtils.kt
Normal file
@@ -0,0 +1,54 @@
|
||||
package app.lawnchair.util
|
||||
|
||||
import android.content.Context
|
||||
import app.lawnchair.flowerpot.Flowerpot
|
||||
import com.android.launcher3.model.data.AppInfo
|
||||
import com.android.launcher3.util.PackageManagerHelper
|
||||
|
||||
/**
|
||||
* Categorizes apps into System Apps, Google Apps, and Flowerpot categories.
|
||||
*
|
||||
* @param apps List of apps to categorize
|
||||
* @param context Context for checking system apps and accessing Flowerpot
|
||||
* @return Map of category names to lists of apps in that category
|
||||
*/
|
||||
fun categorizeAppsWithSystemAndGoogle(
|
||||
apps: List<AppInfo>,
|
||||
context: Context,
|
||||
): Map<String, List<AppInfo>> {
|
||||
val systemApps = mutableListOf<AppInfo>()
|
||||
val googleApps = mutableListOf<AppInfo>()
|
||||
val otherApps = mutableListOf<AppInfo>()
|
||||
|
||||
apps.forEach { app ->
|
||||
val packageName = app.targetPackage ?: return@forEach
|
||||
val intent = app.intent
|
||||
|
||||
// Check if it's a Google app first (Google apps can also be system apps)
|
||||
when {
|
||||
packageName.startsWith("com.google.") -> googleApps.add(app)
|
||||
intent != null && PackageManagerHelper.isSystemApp(context, intent) -> systemApps.add(app)
|
||||
else -> otherApps.add(app)
|
||||
}
|
||||
}
|
||||
|
||||
// Use flowerpot to categorize other apps (non-system, non-Google)
|
||||
val potsManager = Flowerpot.Manager.getInstance(context)
|
||||
val categorizedApps = potsManager.categorizeApps(otherApps)
|
||||
|
||||
// Build final categorized apps map
|
||||
val finalCategorizedApps = mutableMapOf<String, List<AppInfo>>()
|
||||
|
||||
if (systemApps.isNotEmpty()) {
|
||||
finalCategorizedApps["System Apps"] = systemApps
|
||||
}
|
||||
|
||||
if (googleApps.isNotEmpty()) {
|
||||
finalCategorizedApps["Google Apps"] = googleApps
|
||||
}
|
||||
|
||||
// Add flowerpot categorized apps
|
||||
finalCategorizedApps.putAll(categorizedApps)
|
||||
|
||||
return finalCategorizedApps
|
||||
}
|
||||
0
src/com/android/launcher3/LauncherAppState.java
Normal file
0
src/com/android/launcher3/LauncherAppState.java
Normal file
@@ -153,6 +153,35 @@ public class ModelWriter {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all views from the home screen.
|
||||
*/
|
||||
public boolean clearAllHomeScreenViewsByType(int type) {
|
||||
final ArrayList<ItemInfo> itemsToRemove = new ArrayList<>();
|
||||
|
||||
for (ItemInfo item : mBgDataModel.itemsIdMap) {
|
||||
if (item.container == type) {
|
||||
itemsToRemove.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
if (itemsToRemove.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
enqueueDeleteRunnable(newModelTask(() -> {
|
||||
final ModelDbController db = mModel.getModelDbController();
|
||||
|
||||
for (ItemInfo item : itemsToRemove) {
|
||||
db.delete(TABLE_NAME, itemIdMatch(item.id), null);
|
||||
mBgDataModel.removeItem(mContext, item);
|
||||
}
|
||||
}));
|
||||
|
||||
mModel.forceReload();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move an item in the DB to a new <container, screen, cellX, cellY>
|
||||
|
||||
Reference in New Issue
Block a user