diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 209b346..9a671f0 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,3 +1,3 @@ -# How you can support jrpie/Launcher +# How you can support finnmglas/Launcher -custom: https://s.jrpie.de/launcher-donate +custom: sponsor.finnmglas.com diff --git a/app/src/main/java/de/jrpie/android/launcher/Application.kt b/app/src/main/java/de/jrpie/android/launcher/Application.kt index 09229ab..810fceb 100644 --- a/app/src/main/java/de/jrpie/android/launcher/Application.kt +++ b/app/src/main/java/de/jrpie/android/launcher/Application.kt @@ -15,15 +15,15 @@ import androidx.core.content.ContextCompat import androidx.lifecycle.MutableLiveData import androidx.preference.PreferenceManager import de.jrpie.android.launcher.actions.TorchManager -import de.jrpie.android.launcher.apps.AbstractAppInfo -import de.jrpie.android.launcher.apps.AbstractDetailedAppInfo +import de.jrpie.android.launcher.apps.AppInfo +import de.jrpie.android.launcher.apps.DetailedAppInfo import de.jrpie.android.launcher.apps.isPrivateSpaceLocked import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.preferences.migratePreferencesToNewVersion import de.jrpie.android.launcher.preferences.resetPreferences class Application : android.app.Application() { - val apps = MutableLiveData>() + val apps = MutableLiveData>() val privateSpaceLocked = MutableLiveData() private val profileAvailabilityBroadcastReceiver = object : BroadcastReceiver() { @@ -82,12 +82,10 @@ class Application : android.app.Application() { } var torchManager: TorchManager? = null - private var customAppNames: HashMap? = null + private var customAppNames: HashMap? = null private val listener = SharedPreferences.OnSharedPreferenceChangeListener { _, pref -> if (pref == getString(R.string.settings_apps_custom_names_key)) { customAppNames = LauncherPreferences.apps().customNames() - } else if (pref == LauncherPreferences.apps().keys().pinnedShortcuts()) { - loadApps() } } @@ -145,7 +143,7 @@ class Application : android.app.Application() { loadApps() } - fun getCustomAppNames(): HashMap { + fun getCustomAppNames(): HashMap { return (customAppNames ?: LauncherPreferences.apps().customNames() ?: HashMap()) .also { customAppNames = it } } diff --git a/app/src/main/java/de/jrpie/android/launcher/Functions.kt b/app/src/main/java/de/jrpie/android/launcher/Functions.kt index 8f5e08d..8fc95a3 100644 --- a/app/src/main/java/de/jrpie/android/launcher/Functions.kt +++ b/app/src/main/java/de/jrpie/android/launcher/Functions.kt @@ -24,12 +24,9 @@ import androidx.annotation.RequiresApi import de.jrpie.android.launcher.actions.Action import de.jrpie.android.launcher.actions.Gesture import de.jrpie.android.launcher.actions.ShortcutAction -import de.jrpie.android.launcher.apps.AbstractAppInfo.Companion.INVALID_USER -import de.jrpie.android.launcher.apps.AbstractDetailedAppInfo +import de.jrpie.android.launcher.actions.shortcuts.PinnedShortcutInfo import de.jrpie.android.launcher.apps.AppInfo import de.jrpie.android.launcher.apps.DetailedAppInfo -import de.jrpie.android.launcher.apps.DetailedPinnedShortcutInfo -import de.jrpie.android.launcher.apps.PinnedShortcutInfo import de.jrpie.android.launcher.apps.getPrivateSpaceUser import de.jrpie.android.launcher.apps.isPrivateSpaceSupported import de.jrpie.android.launcher.preferences.LauncherPreferences @@ -102,10 +99,9 @@ fun removeUnusedShortcuts(context: Context) { } val userManager = context.getSystemService(Service.USER_SERVICE) as UserManager - val boundActions: MutableSet = + val boundActions: Set = Gesture.entries.mapNotNull { Action.forGesture(it) as? ShortcutAction }.map { it.shortcut } - .toMutableSet() - LauncherPreferences.apps().pinnedShortcuts()?.let { boundActions.addAll(it) } + .toSet() try { userManager.userProfiles.filter { !userManager.isQuietModeEnabled(it) }.forEach { profile -> getShortcuts(profile)?.groupBy { it.`package` }?.forEach { (p, shortcuts) -> @@ -139,12 +135,9 @@ fun openTutorial(context: Context) { /** * Load all apps. */ -fun getApps( - packageManager: PackageManager, - context: Context -): MutableList { - var start = System.currentTimeMillis() - val loadList = mutableListOf() +fun getApps(packageManager: PackageManager, context: Context): MutableList { + val start = System.currentTimeMillis() + val loadList = mutableListOf() val launcherApps = context.getSystemService(Service.LAUNCHER_APPS_SERVICE) as LauncherApps val userManager = context.getSystemService(Service.USER_SERVICE) as UserManager @@ -181,7 +174,7 @@ fun getApps( i.addCategory(Intent.CATEGORY_LAUNCHER) val allApps = packageManager.queryIntentActivities(i, 0) for (ri in allApps) { - val app = AppInfo(ri.activityInfo.packageName, null, INVALID_USER) + val app = AppInfo(ri.activityInfo.packageName, null, AppInfo.INVALID_USER) val detailedAppInfo = DetailedAppInfo( app, ri.loadLabel(packageManager), @@ -193,18 +186,8 @@ fun getApps( } loadList.sortBy { it.getCustomLabel(context).toString() } - var end = System.currentTimeMillis() + val end = System.currentTimeMillis() Log.i(LOG_TAG, "${loadList.size} apps loaded (${end - start}ms)") - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { - start = System.currentTimeMillis() - LauncherPreferences.apps().pinnedShortcuts() - ?.mapNotNull { DetailedPinnedShortcutInfo.fromPinnedShortcutInfo(it, context) } - ?.let { - end = System.currentTimeMillis() - Log.i(LOG_TAG, "${it.size} shortcuts loaded (${end - start}ms)") - loadList.addAll(it) - } - } return loadList } diff --git a/app/src/main/java/de/jrpie/android/launcher/actions/AppAction.kt b/app/src/main/java/de/jrpie/android/launcher/actions/AppAction.kt index 1446b13..90145aa 100644 --- a/app/src/main/java/de/jrpie/android/launcher/actions/AppAction.kt +++ b/app/src/main/java/de/jrpie/android/launcher/actions/AppAction.kt @@ -11,7 +11,7 @@ import android.graphics.drawable.Drawable import android.util.Log import de.jrpie.android.launcher.R import de.jrpie.android.launcher.apps.AppInfo -import de.jrpie.android.launcher.apps.AbstractAppInfo.Companion.INVALID_USER +import de.jrpie.android.launcher.apps.AppInfo.Companion.INVALID_USER import de.jrpie.android.launcher.apps.DetailedAppInfo import de.jrpie.android.launcher.ui.list.apps.openSettings import kotlinx.serialization.SerialName @@ -67,7 +67,7 @@ class AppAction(val app: AppInfo) : Action { } override fun getIcon(context: Context): Drawable? { - return DetailedAppInfo.fromAppInfo(app, context)?.getIcon(context) + return DetailedAppInfo.fromAppInfo(app, context)?.icon } override fun isAvailable(context: Context): Boolean { diff --git a/app/src/main/java/de/jrpie/android/launcher/actions/ShortcutAction.kt b/app/src/main/java/de/jrpie/android/launcher/actions/ShortcutAction.kt index a89f9e2..8517b1a 100644 --- a/app/src/main/java/de/jrpie/android/launcher/actions/ShortcutAction.kt +++ b/app/src/main/java/de/jrpie/android/launcher/actions/ShortcutAction.kt @@ -6,7 +6,7 @@ import android.content.pm.LauncherApps import android.graphics.Rect import android.graphics.drawable.Drawable import android.os.Build -import de.jrpie.android.launcher.apps.PinnedShortcutInfo +import de.jrpie.android.launcher.actions.shortcuts.PinnedShortcutInfo import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/app/src/main/java/de/jrpie/android/launcher/apps/PinnedShortcutInfo.kt b/app/src/main/java/de/jrpie/android/launcher/actions/shortcuts/PinnedShortcutInfo.kt similarity index 93% rename from app/src/main/java/de/jrpie/android/launcher/apps/PinnedShortcutInfo.kt rename to app/src/main/java/de/jrpie/android/launcher/actions/shortcuts/PinnedShortcutInfo.kt index a2815e5..796c737 100644 --- a/app/src/main/java/de/jrpie/android/launcher/apps/PinnedShortcutInfo.kt +++ b/app/src/main/java/de/jrpie/android/launcher/actions/shortcuts/PinnedShortcutInfo.kt @@ -1,4 +1,4 @@ -package de.jrpie.android.launcher.apps +package de.jrpie.android.launcher.actions.shortcuts import android.app.Service import android.content.ComponentName @@ -9,19 +9,17 @@ import android.content.pm.ShortcutInfo import android.os.Build import androidx.annotation.RequiresApi import de.jrpie.android.launcher.getUserFromId -import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @RequiresApi(Build.VERSION_CODES.N_MR1) @Serializable -@SerialName("shortcut") class PinnedShortcutInfo( val id: String, val packageName: String, val activityName: String, val user: Int -): AbstractAppInfo { +) { constructor(info: ShortcutInfo) : this(info.id, info.`package`, info.activity?.className ?: "", info.userHandle.hashCode()) diff --git a/app/src/main/java/de/jrpie/android/launcher/apps/AbstractAppInfo.kt b/app/src/main/java/de/jrpie/android/launcher/apps/AbstractAppInfo.kt deleted file mode 100644 index dd60752..0000000 --- a/app/src/main/java/de/jrpie/android/launcher/apps/AbstractAppInfo.kt +++ /dev/null @@ -1,22 +0,0 @@ -package de.jrpie.android.launcher.apps - -import kotlinx.serialization.Serializable -import kotlinx.serialization.encodeToString -import kotlinx.serialization.json.Json - -/** - * This interface is implemented by [AppInfo] and [PinnedShortcutInfo]. - */ -@Serializable -sealed interface AbstractAppInfo { - fun serialize(): String { - return Json.encodeToString(this) - } - companion object { - const val INVALID_USER = -1 - - fun deserialize(serialized: String): AbstractAppInfo { - return Json.decodeFromString(serialized) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/apps/AbstractDetailedAppInfo.kt b/app/src/main/java/de/jrpie/android/launcher/apps/AbstractDetailedAppInfo.kt deleted file mode 100644 index 9c7413d..0000000 --- a/app/src/main/java/de/jrpie/android/launcher/apps/AbstractDetailedAppInfo.kt +++ /dev/null @@ -1,42 +0,0 @@ -package de.jrpie.android.launcher.apps - -import android.content.Context -import android.graphics.drawable.Drawable -import android.os.UserHandle -import android.util.Log -import de.jrpie.android.launcher.Application -import de.jrpie.android.launcher.actions.Action -import de.jrpie.android.launcher.preferences.LauncherPreferences - -/** - * This interface is implemented by [DetailedAppInfo] and [DetailedPinnedShortcutInfo] - */ -sealed interface AbstractDetailedAppInfo { - fun getRawInfo(): AbstractAppInfo - fun getLabel(): String - fun getIcon(context: Context): Drawable - fun getUser(context: Context): UserHandle - fun isPrivate(): Boolean - fun isRemovable(): Boolean - fun getAction(): Action - - - fun getCustomLabel(context: Context): String { - val map = (context.applicationContext as? Application)?.getCustomAppNames() - return map?.get(getRawInfo()) ?: getLabel() - } - - - fun setCustomLabel(label: CharSequence?) { - Log.i("Launcher", "Setting custom label for ${this.getRawInfo()} to ${label}.") - val map = LauncherPreferences.apps().customNames() ?: HashMap() - - if (label.isNullOrEmpty()) { - map.remove(getRawInfo()) - } else { - map[getRawInfo()] = label.toString() - } - LauncherPreferences.apps().customNames(map) - } - -} \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/apps/AppFilter.kt b/app/src/main/java/de/jrpie/android/launcher/apps/AppFilter.kt index ca387c0..ecc7eaa 100644 --- a/app/src/main/java/de/jrpie/android/launcher/apps/AppFilter.kt +++ b/app/src/main/java/de/jrpie/android/launcher/apps/AppFilter.kt @@ -6,7 +6,6 @@ import android.os.Build import de.jrpie.android.launcher.actions.Action import de.jrpie.android.launcher.actions.AppAction import de.jrpie.android.launcher.actions.Gesture -import de.jrpie.android.launcher.actions.ShortcutAction import de.jrpie.android.launcher.preferences.LauncherPreferences import java.util.Locale import kotlin.text.Regex.Companion.escape @@ -19,14 +18,13 @@ class AppFilter( var privateSpaceVisibility: AppSetVisibility = AppSetVisibility.VISIBLE ) { - operator fun invoke(apps: List): List { + operator fun invoke(apps: List): List { var apps = - apps.sortedBy { app -> app.getCustomLabel(context).lowercase(Locale.ROOT) } + apps.sortedBy { app -> app.getCustomLabel(context).toString().lowercase(Locale.ROOT) } val hidden = LauncherPreferences.apps().hidden() ?: setOf() val favorites = LauncherPreferences.apps().favorites() ?: setOf() - val private = apps.filter { it.isPrivate() } - .map { it.getRawInfo() }.toSet() + val private = apps.filter { it.isPrivateSpaceApp }.map { it.app }.toSet() apps = apps.filter { info -> favoritesVisibility.predicate(favorites, info) @@ -37,13 +35,9 @@ class AppFilter( if (LauncherPreferences.apps().hideBoundApps()) { val boundApps = Gesture.entries .filter(Gesture::isEnabled) - .mapNotNull { g -> Action.forGesture(g) } - .mapNotNull { - (it as? AppAction)?.app - ?: (it as? ShortcutAction)?.shortcut - } + .mapNotNull { g -> (Action.forGesture(g) as? AppAction)?.app } .toSet() - apps = apps.filterNot { info -> boundApps.contains(info.getRawInfo()) } + apps = apps.filterNot { info -> boundApps.contains(info.app) } } // normalize text for search @@ -63,11 +57,11 @@ class AppFilter( if (query.isEmpty()) { return apps } else { - val r: MutableList = ArrayList() - val appsSecondary: MutableList = ArrayList() + val r: MutableList = ArrayList() + val appsSecondary: MutableList = ArrayList() val normalizedQuery: String = normalize(query) for (item in apps) { - val itemLabel: String = normalize(item.getCustomLabel(context)) + val itemLabel: String = normalize(item.getCustomLabel(context).toString()) if (itemLabel.startsWith(normalizedQuery)) { r.add(item) @@ -83,11 +77,11 @@ class AppFilter( companion object { enum class AppSetVisibility( - val predicate: (set: Set, AbstractDetailedAppInfo) -> Boolean + val predicate: (set: Set, DetailedAppInfo) -> Boolean ) { VISIBLE({ _, _ -> true }), - HIDDEN({ set, appInfo -> !set.contains(appInfo.getRawInfo()) }), - EXCLUSIVE({ set, appInfo -> set.contains(appInfo.getRawInfo()) }), + HIDDEN({ set, appInfo -> !set.contains(appInfo.app) }), + EXCLUSIVE({ set, appInfo -> set.contains(appInfo.app) }), ; } diff --git a/app/src/main/java/de/jrpie/android/launcher/apps/AppInfo.kt b/app/src/main/java/de/jrpie/android/launcher/apps/AppInfo.kt index 944cfaa..21614f8 100644 --- a/app/src/main/java/de/jrpie/android/launcher/apps/AppInfo.kt +++ b/app/src/main/java/de/jrpie/android/launcher/apps/AppInfo.kt @@ -4,18 +4,21 @@ import android.app.Service import android.content.Context import android.content.pm.LauncherActivityInfo import android.content.pm.LauncherApps -import de.jrpie.android.launcher.apps.AbstractAppInfo.Companion.INVALID_USER import de.jrpie.android.launcher.getUserFromId -import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json /** * Represents an app installed on the users device. * Contains the minimal amount of data required to identify the app. */ @Serializable -@SerialName("app") -class AppInfo(val packageName: String, val activityName: String?, val user: Int = INVALID_USER): AbstractAppInfo { +class AppInfo(val packageName: String, val activityName: String?, val user: Int = INVALID_USER) { + + fun serialize(): String { + return Json.encodeToString(this) + } override fun equals(other: Any?): Boolean { if(other is AppInfo) { @@ -44,4 +47,11 @@ class AppInfo(val packageName: String, val activityName: String?, val user: Int return "AppInfo {package=$packageName, activity=$activityName, user=$user}" } + companion object { + const val INVALID_USER = -1 + + fun deserialize(serialized: String): AppInfo { + return Json.decodeFromString(serialized) + } + } } \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/apps/DetailedAppInfo.kt b/app/src/main/java/de/jrpie/android/launcher/apps/DetailedAppInfo.kt index 76f7fbb..d77bf93 100644 --- a/app/src/main/java/de/jrpie/android/launcher/apps/DetailedAppInfo.kt +++ b/app/src/main/java/de/jrpie/android/launcher/apps/DetailedAppInfo.kt @@ -4,21 +4,20 @@ import android.content.Context import android.content.pm.ApplicationInfo import android.content.pm.LauncherActivityInfo import android.graphics.drawable.Drawable -import android.os.UserHandle -import de.jrpie.android.launcher.actions.Action -import de.jrpie.android.launcher.actions.AppAction -import de.jrpie.android.launcher.getUserFromId +import android.util.Log +import de.jrpie.android.launcher.Application +import de.jrpie.android.launcher.preferences.LauncherPreferences /** * Stores information used to create [de.jrpie.android.launcher.ui.list.apps.AppsRecyclerAdapter] rows. */ class DetailedAppInfo( - private val app: AppInfo, - private val label: CharSequence, - private val icon: Drawable, - private val privateSpace: Boolean, - private val removable: Boolean = true, -): AbstractDetailedAppInfo { + val app: AppInfo, + val label: CharSequence, + val icon: Drawable, + val isPrivateSpaceApp: Boolean, + val isSystemApp: Boolean = false, +) { constructor(activityInfo: LauncherActivityInfo, private: Boolean) : this( AppInfo( @@ -29,41 +28,29 @@ class DetailedAppInfo( activityInfo.label, activityInfo.getBadgedIcon(0), private, - // App can be uninstalled iff it is not a system app - activityInfo.applicationInfo.flags.and(ApplicationInfo.FLAG_SYSTEM) == 0 + activityInfo.applicationInfo.flags.and(ApplicationInfo.FLAG_SYSTEM) != 0 ) + fun getCustomLabel(context: Context): CharSequence { + val map = (context.applicationContext as? Application)?.getCustomAppNames() ?: return label - - override fun getLabel(): String { - return label.toString() + return map[app] ?: label } - override fun getIcon(context: Context): Drawable { - return icon - } + fun setCustomLabel(label: CharSequence?) { - override fun getRawInfo(): AppInfo { - return app - } + Log.i("Launcher", "Setting custom label for ${this.app} to ${label}.") + val map = LauncherPreferences.apps().customNames() ?: HashMap() - override fun getUser(context: Context): UserHandle { - return getUserFromId(app.user, context) - } + if (label.isNullOrEmpty()) { + map.remove(app) + } else { + map[app] = label.toString() + } - override fun isPrivate(): Boolean { - return privateSpace + LauncherPreferences.apps().customNames(map) } - override fun isRemovable(): Boolean { - return removable - } - - override fun getAction(): Action { - return AppAction(app) - } - - companion object { fun fromAppInfo(appInfo: AppInfo, context: Context): DetailedAppInfo? { return appInfo.getLauncherActivityInfo(context)?.let { diff --git a/app/src/main/java/de/jrpie/android/launcher/apps/DetailedPinnedShortcutInfo.kt b/app/src/main/java/de/jrpie/android/launcher/apps/DetailedPinnedShortcutInfo.kt deleted file mode 100644 index f66034d..0000000 --- a/app/src/main/java/de/jrpie/android/launcher/apps/DetailedPinnedShortcutInfo.kt +++ /dev/null @@ -1,66 +0,0 @@ -package de.jrpie.android.launcher.apps - -import android.app.Service -import android.content.Context -import android.content.pm.LauncherApps -import android.content.pm.ShortcutInfo -import android.graphics.drawable.Drawable -import android.os.Build -import android.os.UserHandle -import androidx.annotation.RequiresApi -import de.jrpie.android.launcher.actions.Action -import de.jrpie.android.launcher.actions.ShortcutAction -import de.jrpie.android.launcher.getUserFromId - -@RequiresApi(Build.VERSION_CODES.N_MR1) -class DetailedPinnedShortcutInfo( - private val shortcutInfo: PinnedShortcutInfo, - private val label: String, - private val icon: Drawable, - private val privateSpace: Boolean -) : AbstractDetailedAppInfo { - - constructor(context: Context, shortcut: ShortcutInfo) : this( - PinnedShortcutInfo(shortcut), - shortcut.longLabel.toString(), - (context.getSystemService(Service.LAUNCHER_APPS_SERVICE) as LauncherApps) - .getShortcutBadgedIconDrawable(shortcut, 0), - shortcut.userHandle == getPrivateSpaceUser(context) - ) - - override fun getRawInfo(): AbstractAppInfo { - return shortcutInfo - } - - override fun getLabel(): String { - return label - } - - override fun getIcon(context: Context): Drawable { - return icon - } - - override fun getUser(context: Context): UserHandle { - return getUserFromId(shortcutInfo.user, context) - } - - override fun isPrivate(): Boolean { - return privateSpace - } - - override fun isRemovable(): Boolean { - return true - } - - override fun getAction(): Action { - return ShortcutAction(shortcutInfo) - } - - companion object { - fun fromPinnedShortcutInfo(shortcutInfo: PinnedShortcutInfo, context: Context): DetailedPinnedShortcutInfo? { - return shortcutInfo.getShortcutInfo(context)?.let { - DetailedPinnedShortcutInfo(context, it) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java b/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java index 076445d..aacff13 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java @@ -5,9 +5,8 @@ import java.util.Set; import de.jrpie.android.launcher.R; import de.jrpie.android.launcher.actions.lock.LockMethod; -import de.jrpie.android.launcher.preferences.serialization.MapAbstractAppInfoStringPreferenceSerializer; -import de.jrpie.android.launcher.preferences.serialization.SetAbstractAppInfoPreferenceSerializer; -import de.jrpie.android.launcher.preferences.serialization.SetPinnedShortcutInfoPreferenceSerializer; +import de.jrpie.android.launcher.preferences.serialization.MapAppInfoStringPreferenceSerializer; +import de.jrpie.android.launcher.preferences.serialization.SetAppInfoPreferenceSerializer; import de.jrpie.android.launcher.preferences.theme.Background; import de.jrpie.android.launcher.preferences.theme.ColorTheme; import de.jrpie.android.launcher.preferences.theme.Font; @@ -26,17 +25,15 @@ import eu.jonahbauer.android.preference.annotations.Preferences; @Preference(name = "version_code", type = int.class, defaultValue = "-1"), }), @PreferenceGroup(name = "apps", prefix = "settings_apps_", suffix = "_key", value = { - @Preference(name = "favorites", type = Set.class, serializer = SetAbstractAppInfoPreferenceSerializer.class), - @Preference(name = "hidden", type = Set.class, serializer = SetAbstractAppInfoPreferenceSerializer.class), - @Preference(name = "pinned_shortcuts", type = Set.class, serializer = SetPinnedShortcutInfoPreferenceSerializer.class), - @Preference(name = "custom_names", type = HashMap.class, serializer = MapAbstractAppInfoStringPreferenceSerializer.class), + @Preference(name = "favorites", type = Set.class, serializer = SetAppInfoPreferenceSerializer.class), + @Preference(name = "hidden", type = Set.class, serializer = SetAppInfoPreferenceSerializer.class), + @Preference(name = "custom_names", type = HashMap.class, serializer = MapAppInfoStringPreferenceSerializer.class), @Preference(name = "hide_bound_apps", type = boolean.class, defaultValue = "false"), @Preference(name = "hide_paused_apps", type = boolean.class, defaultValue = "false"), @Preference(name = "hide_private_space_apps", type = boolean.class, defaultValue = "false"), }), @PreferenceGroup(name = "list", prefix = "settings_list_", suffix = "_key", value = { - @Preference(name = "layout", type = ListLayout.class, defaultValue = "DEFAULT"), - @Preference(name = "reverse_layout", type = boolean.class, defaultValue = "false") + @Preference(name = "layout", type = ListLayout.class, defaultValue = "DEFAULT") }), @PreferenceGroup(name = "gestures", prefix = "settings_gesture_", suffix = "_key", value = { }), diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/Preferences.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/Preferences.kt index 59ecc7a..9460125 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/Preferences.kt +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/Preferences.kt @@ -5,12 +5,9 @@ import android.util.Log import de.jrpie.android.launcher.BuildConfig import de.jrpie.android.launcher.actions.Action import de.jrpie.android.launcher.apps.AppInfo -import de.jrpie.android.launcher.apps.AbstractAppInfo -import de.jrpie.android.launcher.apps.AbstractAppInfo.Companion.INVALID_USER import de.jrpie.android.launcher.apps.DetailedAppInfo import de.jrpie.android.launcher.preferences.legacy.migratePreferencesFromVersion1 import de.jrpie.android.launcher.preferences.legacy.migratePreferencesFromVersion2 -import de.jrpie.android.launcher.preferences.legacy.migratePreferencesFromVersion3 import de.jrpie.android.launcher.preferences.legacy.migratePreferencesFromVersionUnknown import de.jrpie.android.launcher.ui.HomeActivity @@ -18,7 +15,7 @@ import de.jrpie.android.launcher.ui.HomeActivity * Increase when breaking changes are introduced and write an appropriate case in * `migratePreferencesToNewVersion` */ -const val PREFERENCE_VERSION = 4 +const val PREFERENCE_VERSION = 3 const val UNKNOWN_PREFERENCE_VERSION = -1 private const val TAG = "Launcher - Preferences" @@ -47,10 +44,6 @@ fun migratePreferencesToNewVersion(context: Context) { migratePreferencesFromVersion2() Log.i(TAG, "migration of preferences complete (2 -> ${PREFERENCE_VERSION}).") } - 3 -> { - migratePreferencesFromVersion3() - Log.i(TAG, "migration of preferences complete (3 -> ${PREFERENCE_VERSION}).") - } else -> { Log.w( @@ -73,16 +66,16 @@ fun resetPreferences(context: Context) { LauncherPreferences.internal().versionCode(PREFERENCE_VERSION) - val hidden: MutableSet = mutableSetOf() + val hidden: MutableSet = mutableSetOf() val launcher = DetailedAppInfo.fromAppInfo( AppInfo( BuildConfig.APPLICATION_ID, HomeActivity::class.java.name, - INVALID_USER + AppInfo.INVALID_USER ), context ) - launcher?.getRawInfo()?.let { hidden.add(it) } - Log.i(TAG,"Hiding ${launcher?.getRawInfo()}") + launcher?.app?.let { hidden.add(it) } + Log.i(TAG,"Hiding ${launcher?.app}") LauncherPreferences.apps().hidden(hidden) Action.resetToDefaultActions(context) diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version1.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version1.kt index 6408b70..a61980a 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version1.kt +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version1.kt @@ -5,26 +5,15 @@ import de.jrpie.android.launcher.actions.AppAction import de.jrpie.android.launcher.actions.Gesture import de.jrpie.android.launcher.actions.LauncherAction import de.jrpie.android.launcher.apps.AppInfo -import de.jrpie.android.launcher.apps.AbstractAppInfo.Companion.INVALID_USER +import de.jrpie.android.launcher.apps.AppInfo.Companion.INVALID_USER import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.preferences.PREFERENCE_VERSION -import kotlinx.serialization.Serializable +import de.jrpie.android.launcher.preferences.serialization.MapAppInfoStringPreferenceSerializer import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import org.json.JSONException import org.json.JSONObject - -@Serializable -private class LegacyMapEntry(val key: AppInfo, val value: String) - -private fun serializeMapAppInfo(value: Map?): Set? { - return value?.map { (key, value) -> - Json.encodeToString(LegacyMapEntry(key, value)) - }?.toSet() -} - - val oldLauncherActionIds: Map = mapOf( Pair("launcher:settings", LauncherAction.SETTINGS), @@ -88,7 +77,7 @@ private fun Action.Companion.legacyFromPreference(id: String): Action? { private fun migrateAppInfoStringMap(key: String) { val preferences = LauncherPreferences.getSharedPreferences() - serializeMapAppInfo( + MapAppInfoStringPreferenceSerializer().serialize( preferences.getStringSet(key, setOf())?.mapNotNull { entry -> try { val obj = JSONObject(entry) diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version2.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version2.kt index 4e6eae1..bcac3ae 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version2.kt +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version2.kt @@ -12,9 +12,9 @@ import de.jrpie.android.launcher.preferences.PREFERENCE_VERSION * (see [PREFERENCE_VERSION]) */ fun migratePreferencesFromVersion2() { + assert(PREFERENCE_VERSION == 3) assert(LauncherPreferences.internal().versionCode() == 2) // previously there was no setting for this Action.setActionForGesture(Gesture.BACK, LauncherAction.CHOOSE) LauncherPreferences.internal().versionCode(3) - migratePreferencesFromVersion3() } \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version3.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version3.kt deleted file mode 100644 index 7698e62..0000000 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version3.kt +++ /dev/null @@ -1,85 +0,0 @@ -package de.jrpie.android.launcher.preferences.legacy - -import android.content.SharedPreferences -import android.content.SharedPreferences.Editor -import de.jrpie.android.launcher.apps.AppInfo -import de.jrpie.android.launcher.apps.AbstractAppInfo -import de.jrpie.android.launcher.preferences.LauncherPreferences -import de.jrpie.android.launcher.preferences.PREFERENCE_VERSION -import de.jrpie.android.launcher.preferences.serialization.MapAbstractAppInfoStringPreferenceSerializer -import de.jrpie.android.launcher.preferences.serialization.SetAbstractAppInfoPreferenceSerializer -import kotlinx.serialization.Serializable -import kotlinx.serialization.json.Json -import java.util.HashSet - -/** - * Migrate preferences from version 3 (used until version 0.0.23) to the current format - * (see [PREFERENCE_VERSION]) - */ - - -fun deserializeSet(value: Set?): Set? { - return value?.map { - Json.decodeFromString(it) - }?.toHashSet() -} - -fun deserializeMap(value: Set?): HashMap? { - return value?.associateTo(HashMap()) { - val entry = Json.decodeFromString(it) - Pair(entry.key, entry.value) - } -} - -@Serializable -private class MapEntry(val key: AppInfo, val value: String) - -private fun migrateSetAppInfo(key: String, preferences: SharedPreferences, editor: Editor) { - try { - val serializer = SetAbstractAppInfoPreferenceSerializer() - val set = HashSet() - - deserializeSet(preferences.getStringSet(key, null))?.let { - set.addAll(it) - } - editor.putStringSet( - key, - serializer.serialize(set as java.util.Set) as Set? - ) - } catch (e: Exception) { - e.printStackTrace() - editor.putStringSet(key, null) - } - -} -private fun migrateMapAppInfoString(key: String, preferences: SharedPreferences, editor: Editor ) { - try { - val serializer = MapAbstractAppInfoStringPreferenceSerializer() - val map = HashMap() - - deserializeMap(preferences.getStringSet(key, null))?.let { - map.putAll(it) - } - editor.putStringSet(key, serializer.serialize(map) as Set?) - } catch (e: Exception) { - e.printStackTrace() - editor.putStringSet(key, null) - } -} - -fun migratePreferencesFromVersion3() { - assert(PREFERENCE_VERSION == 4) - assert(LauncherPreferences.internal().versionCode() == 3) - - val preferences = LauncherPreferences.getSharedPreferences() - val editor = preferences.edit() - migrateSetAppInfo(LauncherPreferences.apps().keys().favorites(), preferences, editor) - migrateSetAppInfo(LauncherPreferences.apps().keys().hidden(), preferences, editor) - migrateMapAppInfoString(LauncherPreferences.apps().keys().customNames(), preferences, editor) - - editor.apply() - - - - LauncherPreferences.internal().versionCode(4) -} \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/serialization/PreferenceSerializers.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/serialization/PreferenceSerializers.kt index 3e19daf..041fe4d 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/serialization/PreferenceSerializers.kt +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/serialization/PreferenceSerializers.kt @@ -2,8 +2,7 @@ package de.jrpie.android.launcher.preferences.serialization -import de.jrpie.android.launcher.apps.AbstractAppInfo -import de.jrpie.android.launcher.apps.PinnedShortcutInfo +import de.jrpie.android.launcher.apps.AppInfo import eu.jonahbauer.android.preference.annotations.serializer.PreferenceSerializationException import eu.jonahbauer.android.preference.annotations.serializer.PreferenceSerializer import kotlinx.serialization.Serializable @@ -11,61 +10,40 @@ import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json - +// Serializers for [LauncherPreference$Config] @Suppress("UNCHECKED_CAST") -class SetAbstractAppInfoPreferenceSerializer : - PreferenceSerializer?, java.util.Set?> { +class SetAppInfoPreferenceSerializer : + PreferenceSerializer?, java.util.Set?> { @Throws(PreferenceSerializationException::class) - override fun serialize(value: java.util.Set?): java.util.Set { - return value?.map(AbstractAppInfo::serialize) - ?.toHashSet() as java.util.Set + override fun serialize(value: java.util.Set?): java.util.Set { + return value?.map(AppInfo::serialize)?.toHashSet() as java.util.Set } @Throws(PreferenceSerializationException::class) - override fun deserialize(value: java.util.Set?): java.util.Set? { - return value?.map(java.lang.String::toString)?.map(AbstractAppInfo::deserialize) - ?.toHashSet() as? java.util.Set + override fun deserialize(value: java.util.Set?): java.util.Set? { + return value?.map (java.lang.String::toString)?.map(AppInfo::deserialize)?.toHashSet() as? java.util.Set } } @Suppress("UNCHECKED_CAST") -class SetPinnedShortcutInfoPreferenceSerializer : - PreferenceSerializer?, java.util.Set?> { - @Throws(PreferenceSerializationException::class) - override fun serialize(value: java.util.Set?): java.util.Set { - return value?.map { Json.encodeToString(it) } - ?.toHashSet() as java.util.Set - } - - @Throws(PreferenceSerializationException::class) - override fun deserialize(value: java.util.Set?): java.util.Set? { - return value?.map(java.lang.String::toString) - ?.map { Json.decodeFromString(it) } - ?.toHashSet() as? java.util.Set - } -} - - -@Suppress("UNCHECKED_CAST") -class MapAbstractAppInfoStringPreferenceSerializer : - PreferenceSerializer?, java.util.Set?> { +class MapAppInfoStringPreferenceSerializer : + PreferenceSerializer?, java.util.Set?> { @Serializable - private class MapEntry(val key: AbstractAppInfo, val value: String) + private class MapEntry(val key: AppInfo, val value: String) @Throws(PreferenceSerializationException::class) - override fun serialize(value: java.util.HashMap?): java.util.Set? { + override fun serialize(value: java.util.HashMap?): java.util.Set? { return value?.map { (key, value) -> Json.encodeToString(MapEntry(key, value)) }?.toHashSet() as? java.util.Set } @Throws(PreferenceSerializationException::class) - override fun deserialize(value: java.util.Set?): java.util.HashMap? { + override fun deserialize(value: java.util.Set?): java.util.HashMap? { return value?.associateTo(HashMap()) { val entry = Json.decodeFromString(it.toString()) Pair(entry.key, entry.value) } } } - diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/PinShortcutActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/PinShortcutActivity.kt index 4d5d700..d19fe04 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/PinShortcutActivity.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/PinShortcutActivity.kt @@ -21,7 +21,7 @@ import de.jrpie.android.launcher.R import de.jrpie.android.launcher.actions.Action import de.jrpie.android.launcher.actions.Gesture import de.jrpie.android.launcher.actions.ShortcutAction -import de.jrpie.android.launcher.apps.PinnedShortcutInfo +import de.jrpie.android.launcher.actions.shortcuts.PinnedShortcutInfo import de.jrpie.android.launcher.databinding.ActivityPinShortcutBinding import de.jrpie.android.launcher.preferences.LauncherPreferences @@ -29,7 +29,6 @@ class PinShortcutActivity : AppCompatActivity(), UIObject { private lateinit var binding: ActivityPinShortcutBinding private var isBound = false - private var request: PinItemRequest? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -47,7 +46,6 @@ class PinShortcutActivity : AppCompatActivity(), UIObject { val launcherApps = getSystemService(Service.LAUNCHER_APPS_SERVICE) as LauncherApps val request = launcherApps.getPinItemRequest(intent) - this.request = request if (request == null || request.requestType != PinItemRequest.REQUEST_TYPE_SHORTCUT) { finish() return @@ -86,7 +84,6 @@ class PinShortcutActivity : AppCompatActivity(), UIObject { } binding.pinShortcutClose.setOnClickListener { finish() } - binding.pinShortcutButtonOk.setOnClickListener { finish() } } override fun onStart() { @@ -94,24 +91,6 @@ class PinShortcutActivity : AppCompatActivity(), UIObject { super.onStart() } - override fun onDestroy() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { - super.onDestroy() - return - } - if(binding.pinShortcutSwitchVisible.isChecked) { - if(!isBound) { - request?.accept() - } - request?.shortcutInfo?.let { - val set = LauncherPreferences.apps().pinnedShortcuts() ?: mutableSetOf() - set.add(PinnedShortcutInfo(it)) - LauncherPreferences.apps().pinnedShortcuts(set) - } - } - super.onDestroy() - } - override fun getTheme(): Resources.Theme { return modifyTheme(super.getTheme()) } @@ -145,6 +124,5 @@ class PinShortcutActivity : AppCompatActivity(), UIObject { override fun getItemCount(): Int { return gestures.size } - } } \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/AppsRecyclerAdapter.kt b/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/AppsRecyclerAdapter.kt index 0c0407e..2d8e1eb 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/AppsRecyclerAdapter.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/AppsRecyclerAdapter.kt @@ -16,10 +16,11 @@ import androidx.recyclerview.widget.RecyclerView import de.jrpie.android.launcher.Application import de.jrpie.android.launcher.R import de.jrpie.android.launcher.REQUEST_CHOOSE_APP -import de.jrpie.android.launcher.apps.AbstractDetailedAppInfo +import de.jrpie.android.launcher.actions.AppAction import de.jrpie.android.launcher.apps.AppFilter import de.jrpie.android.launcher.apps.AppInfo import de.jrpie.android.launcher.apps.DetailedAppInfo +import de.jrpie.android.launcher.getUserFromId import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.preferences.ListLayout import de.jrpie.android.launcher.ui.list.ListActivity @@ -46,7 +47,7 @@ class AppsRecyclerAdapter( RecyclerView.Adapter() { private val apps = (activity.applicationContext as Application).apps - private val appsListDisplayed: MutableList = mutableListOf() + private val appsListDisplayed: MutableList = mutableListOf() // temporarily disable auto launch var disableAutoLaunch: Boolean = false @@ -82,11 +83,11 @@ class AppsRecyclerAdapter( if (layout.useBadgedText) { appLabel = activity.packageManager.getUserBadgedLabel( appLabel, - appsListDisplayed[i].getUser(activity) + getUserFromId(appsListDisplayed[i].app.user, activity) ).toString() } - val appIcon = appsListDisplayed[i].getIcon(activity) + val appIcon = appsListDisplayed[i].icon viewHolder.textView.text = appLabel viewHolder.img.setImageDrawable(appIcon) @@ -117,26 +118,22 @@ class AppsRecyclerAdapter( @Suppress("SameReturnValue") private fun showOptionsPopup( viewHolder: ViewHolder, - appInfo: AbstractDetailedAppInfo + appInfo: DetailedAppInfo ): Boolean { //create the popup menu val popup = PopupMenu(activity, viewHolder.img) popup.inflate(R.menu.menu_app) - if (!appInfo.isRemovable()) { + if (appInfo.isSystemApp) { popup.menu.findItem(R.id.app_menu_delete).setVisible(false) } - if (appInfo !is DetailedAppInfo) { - popup.menu.findItem(R.id.app_menu_info).setVisible(false) - } - - if (LauncherPreferences.apps().hidden()?.contains(appInfo.getRawInfo()) == true) { + if (LauncherPreferences.apps().hidden()?.contains(appInfo.app) == true) { popup.menu.findItem(R.id.app_menu_hidden).setTitle(R.string.list_app_hidden_remove) } - if (LauncherPreferences.apps().favorites()?.contains(appInfo.getRawInfo()) == true) { + if (LauncherPreferences.apps().favorites()?.contains(appInfo.app) == true) { popup.menu.findItem(R.id.app_menu_favorite).setTitle(R.string.list_app_favorite_remove) } @@ -144,19 +141,19 @@ class AppsRecyclerAdapter( popup.setOnMenuItemClickListener { when (it.itemId) { R.id.app_menu_delete -> { - appInfo.getRawInfo().uninstall(activity); true + appInfo.app.uninstall(activity); true } R.id.app_menu_info -> { - (appInfo.getRawInfo() as? AppInfo)?.openSettings(activity); true + appInfo.app.openSettings(activity); true } R.id.app_menu_favorite -> { - appInfo.getRawInfo().toggleFavorite(); true + appInfo.app.toggleFavorite(); true } R.id.app_menu_hidden -> { - appInfo.getRawInfo().toggleHidden(root); true + appInfo.app.toggleHidden(root); true } R.id.app_menu_rename -> { @@ -191,12 +188,12 @@ class AppsRecyclerAdapter( val appInfo = appsListDisplayed[pos] when (intention) { ListActivity.ListActivityIntention.VIEW -> { - appInfo.getAction().invoke(activity, rect) + AppAction(appInfo.app).invoke(activity, rect) } ListActivity.ListActivityIntention.PICK -> { val returnIntent = Intent() - appInfo.getAction().writeToIntent(returnIntent) + AppAction(appInfo.app).writeToIntent(returnIntent) returnIntent.putExtra("forGesture", forGesture) activity.setResult(REQUEST_CHOOSE_APP, returnIntent) activity.finish() @@ -214,8 +211,8 @@ class AppsRecyclerAdapter( && !disableAutoLaunch && LauncherPreferences.functionality().searchAutoLaunch() ) { - val app = appsListDisplayed[0] - app.getAction().invoke(activity) + val info = appsListDisplayed[0] + AppAction(info.app).invoke(activity) val inputMethodManager = activity.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ContextMenuActions.kt b/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ContextMenuActions.kt index c1f3406..9636dc2 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ContextMenuActions.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ContextMenuActions.kt @@ -1,6 +1,5 @@ package de.jrpie.android.launcher.ui.list.apps -import android.app.Activity import android.app.Service import android.content.Context import android.content.Intent @@ -16,10 +15,7 @@ import com.google.android.material.snackbar.Snackbar import de.jrpie.android.launcher.R import de.jrpie.android.launcher.REQUEST_UNINSTALL import de.jrpie.android.launcher.apps.AppInfo -import de.jrpie.android.launcher.apps.AbstractAppInfo -import de.jrpie.android.launcher.apps.AbstractDetailedAppInfo import de.jrpie.android.launcher.apps.DetailedAppInfo -import de.jrpie.android.launcher.apps.PinnedShortcutInfo import de.jrpie.android.launcher.getUserFromId import de.jrpie.android.launcher.preferences.LauncherPreferences @@ -36,33 +32,27 @@ fun AppInfo.openSettings( } } -fun AbstractAppInfo.uninstall(activity: Activity) { - if (this is AppInfo) { - val packageName = this.packageName - val userId = this.user +fun AppInfo.uninstall(activity: android.app.Activity) { + val packageName = this.packageName + val userId = this.user - Log.i(LOG_TAG, "uninstalling $this") + Log.i(LOG_TAG, "uninstalling $this") - val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE) - intent.data = Uri.parse("package:$packageName") - getUserFromId(userId, activity).let { user -> - intent.putExtra(Intent.EXTRA_USER, user) - } - - intent.putExtra(Intent.EXTRA_RETURN_RESULT, true) - activity.startActivityForResult( - intent, - REQUEST_UNINSTALL - ) - } else if(this is PinnedShortcutInfo) { - val pinned = LauncherPreferences.apps().pinnedShortcuts() ?: mutableSetOf() - pinned.remove(this) - LauncherPreferences.apps().pinnedShortcuts(pinned) + val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE) + intent.data = Uri.parse("package:$packageName") + getUserFromId(userId, activity).let { user -> + intent.putExtra(Intent.EXTRA_USER, user) } + + intent.putExtra(Intent.EXTRA_RETURN_RESULT, true) + activity.startActivityForResult( + intent, + REQUEST_UNINSTALL + ) } -fun AbstractAppInfo.toggleFavorite() { - val favorites: MutableSet = +fun AppInfo.toggleFavorite() { + val favorites: MutableSet = LauncherPreferences.apps().favorites() ?: mutableSetOf() if (favorites.contains(this)) { @@ -79,8 +69,8 @@ fun AbstractAppInfo.toggleFavorite() { /** * @param view: used to show a snackbar letting the user undo the action */ -fun AbstractAppInfo.toggleHidden(view: View) { - val hidden: MutableSet = +fun AppInfo.toggleHidden(view: View) { + val hidden: MutableSet = LauncherPreferences.apps().hidden() ?: mutableSetOf() if (hidden.contains(this)) { hidden.remove(this) @@ -97,9 +87,9 @@ fun AbstractAppInfo.toggleHidden(view: View) { LauncherPreferences.apps().hidden(hidden) } -fun AbstractDetailedAppInfo.showRenameDialog(context: Context) { +fun DetailedAppInfo.showRenameDialog(context: Context) { AlertDialog.Builder(context, R.style.AlertDialogCustom).apply { - setTitle(context.getString(R.string.dialog_rename_title, getLabel())) + setTitle(context.getString(R.string.dialog_rename_title, label)) setView(R.layout.dialog_rename_app) setNegativeButton(R.string.dialog_cancel) { d, _ -> d.cancel() } setPositiveButton(R.string.dialog_rename_ok) { d, _ -> @@ -112,7 +102,7 @@ fun AbstractDetailedAppInfo.showRenameDialog(context: Context) { }.create().also { it.show() }.apply { val input = findViewById(R.id.dialog_rename_app_edit_text) input?.setText(getCustomLabel(context)) - input?.hint = getLabel() + input?.hint = label } } diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ListFragmentApps.kt b/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ListFragmentApps.kt index a02c50f..3a6e403 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ListFragmentApps.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ListFragmentApps.kt @@ -9,8 +9,6 @@ import android.view.View import android.view.ViewGroup import android.widget.Toast import androidx.fragment.app.Fragment -import androidx.recyclerview.widget.GridLayoutManager -import androidx.recyclerview.widget.LinearLayoutManager import de.jrpie.android.launcher.R import de.jrpie.android.launcher.apps.AppFilter import de.jrpie.android.launcher.databinding.ListAppsBinding @@ -81,18 +79,11 @@ class ListFragmentApps : Fragment(), UIObject { layout = LauncherPreferences.list().layout() ) - // set up the list / recycler binding.listAppsRview.apply { // improve performance (since content changes don't change the layout size) setHasFixedSize(true) layoutManager = LauncherPreferences.list().layout().layoutManager(context) - .also { - if (LauncherPreferences.list().reverseLayout()) { - (it as? LinearLayoutManager)?.reverseLayout = true - (it as? GridLayoutManager)?.reverseLayout = true - } - } adapter = appsRecyclerAdapter } diff --git a/app/src/main/res/layout/activity_pin_shortcut.xml b/app/src/main/res/layout/activity_pin_shortcut.xml index 5e10118..c401b42 100644 --- a/app/src/main/res/layout/activity_pin_shortcut.xml +++ b/app/src/main/res/layout/activity_pin_shortcut.xml @@ -80,6 +80,7 @@ android:minHeight="40dp" tools:drawableLeft="@drawable/baseline_settings_24" tools:text="Shortcut name" /> + - - - -