Fixed app change check cancelling and the installed apps are now loaded in MainActivity for faster app menu opening.

This commit is contained in:
ottoptj 2024-05-21 20:55:24 +03:00
commit ce78b5f37e
4 changed files with 70 additions and 36 deletions

View file

@ -23,6 +23,7 @@ import kotlinx.coroutines.launch
class AppActionMenu { class AppActionMenu {
private val sharedPreferenceManager = SharedPreferenceManager() private val sharedPreferenceManager = SharedPreferenceManager()
private val appUtils = AppUtils()
fun setActionListeners( fun setActionListeners(
activity: AppMenuActivity, activity: AppMenuActivity,
@ -105,7 +106,7 @@ class AppActionMenu {
editText.text.toString() editText.text.toString()
) )
val newPosition = activity.getInstalledApps() val newPosition = appUtils.getInstalledApps(activity)
.indexOfFirst { it.first.applicationInfo.packageName == appInfo.packageName && it.second.second == workProfile } .indexOfFirst { it.first.applicationInfo.packageName == appInfo.packageName && it.second.second == workProfile }
activity.updateItem(position, app) activity.updateItem(position, app)
@ -127,7 +128,7 @@ class AppActionMenu {
app.first.applicationInfo.packageName, app.first.applicationInfo.packageName,
app.second.second app.second.second
) )
val newPosition = activity.getInstalledApps() val newPosition = appUtils.getInstalledApps(activity)
.indexOfFirst { it.first.applicationInfo.packageName == appInfo.packageName && it.second.second == workProfile } .indexOfFirst { it.first.applicationInfo.packageName == appInfo.packageName && it.second.second == workProfile }
activity.updateItem(position, app) activity.updateItem(position, app)
activity.moveItem(position, newPosition) activity.moveItem(position, newPosition)

View file

@ -35,26 +35,28 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener,
private lateinit var searchView: EditText private lateinit var searchView: EditText
private lateinit var adapter: AppMenuAdapter private lateinit var adapter: AppMenuAdapter
private lateinit var filteredApps: MutableList<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>> private lateinit var filteredApps: MutableList<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>
private lateinit var installedApps: List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>> private var job: Job? = null
private lateinit var job: Job
private var appActionMenu = AppActionMenu() private var appActionMenu = AppActionMenu()
private lateinit var launcherApps: LauncherApps private lateinit var launcherApps: LauncherApps
private lateinit var installedApps: List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>
private val sharedPreferenceManager = SharedPreferenceManager() private val sharedPreferenceManager = SharedPreferenceManager()
private val appUtils = AppUtils()
private lateinit var menuMode: String private lateinit var menuMode: String
companion object { companion object {
private lateinit var callback: (Pair<Pair<String, Int>, Pair<LauncherActivityInfo, UserHandle>>) -> Unit private lateinit var callback: (Pair<Pair<String, Int>, Pair<LauncherActivityInfo, UserHandle>>) -> Unit
private const val MENU_MODE = "app" private const val MENU_MODE = "app"
private lateinit var currentApps: List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>
fun start(context: Context, param1: String = "app", callback: (Pair<Pair<String, Int>, Pair<LauncherActivityInfo, UserHandle>>) -> Unit) { fun start(context: Context, currentApps: List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>, param1: String = "app", callback: (Pair<Pair<String, Int>, Pair<LauncherActivityInfo, UserHandle>>) -> Unit) {
val intent = Intent(context, AppMenuActivity::class.java).apply { val intent = Intent(context, AppMenuActivity::class.java).apply {
putExtra(MENU_MODE, param1) putExtra(MENU_MODE, param1)
} }
context.startActivity(intent) context.startActivity(intent)
this.callback = callback this.callback = callback
this.currentApps = currentApps
} }
} }
@ -76,7 +78,7 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener,
recyclerView = findViewById(R.id.recycler_view) recyclerView = findViewById(R.id.recycler_view)
recyclerView.scrollToPosition(0) recyclerView.scrollToPosition(0)
installedApps = getInstalledApps() installedApps = currentApps
filteredApps = mutableListOf() filteredApps = mutableListOf()
filteredApps.addAll(installedApps) filteredApps.addAll(installedApps)
val newApps = mutableListOf<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>() val newApps = mutableListOf<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>()
@ -136,10 +138,13 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener,
binding.root.addOnLayoutChangeListener { _, _, top, _, bottom, _, oldTop, _, oldBottom -> binding.root.addOnLayoutChangeListener { _, _, top, _, bottom, _, oldTop, _, oldBottom ->
if (bottom - top > oldBottom - oldTop) { if (bottom - top > oldBottom - oldTop) {
searchView.clearFocus() searchView.clearFocus()
startTask() if (searchView.text.isNullOrEmpty()) {
job?.cancel()
startTask()
}
} }
else if (bottom - top < oldBottom - oldTop) { else {
job.cancel() job?.cancel()
} }
} }
@ -162,12 +167,11 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener,
CoroutineScope(Dispatchers.Default).launch { CoroutineScope(Dispatchers.Default).launch {
val cleanQuery = query?.clean() val cleanQuery = query?.clean()
val newFilteredApps = mutableListOf<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>() val newFilteredApps = mutableListOf<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>()
val updatedApps = getInstalledApps() val updatedApps = appUtils.getInstalledApps(this@AppMenuActivity)
if (cleanQuery.isNullOrEmpty()) { if (cleanQuery.isNullOrEmpty()) {
manualRefresh() manualRefresh()
newFilteredApps.addAll(installedApps) newFilteredApps.addAll(installedApps)
} else { } else {
updatedApps.forEach { updatedApps.forEach {
val cleanItemText = sharedPreferenceManager.getAppName(this@AppMenuActivity, it.first.applicationInfo.packageName, it.second.second, it.first.applicationInfo.loadLabel(packageManager)).toString().clean() val cleanItemText = sharedPreferenceManager.getAppName(this@AppMenuActivity, it.first.applicationInfo.packageName, it.second.second, it.first.applicationInfo.loadLabel(packageManager)).toString().clean()
@ -190,32 +194,22 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener,
return this.replace("[^a-zA-Z0-9]".toRegex(), "") return this.replace("[^a-zA-Z0-9]".toRegex(), "")
} }
fun getInstalledApps(): List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>> { override fun onStop() {
val allApps = mutableListOf<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>() super.onStop()
val launcherApps = getSystemService(LAUNCHER_APPS_SERVICE) as LauncherApps job?.cancel()
for (i in launcherApps.profiles.indices) {
launcherApps.getActivityList(null, launcherApps.profiles[i]).forEach { app ->
if (!sharedPreferenceManager.isAppHidden(this@AppMenuActivity, app.applicationInfo.packageName, i)) {
allApps.add(Pair(app, Pair(launcherApps.profiles[i], i)))
}
}
}
return allApps.sortedBy {
sharedPreferenceManager.getAppName(this, it.first.applicationInfo.packageName,it.second.second, it.first.applicationInfo.loadLabel(packageManager)).toString().lowercase()
}
} }
override fun onStop() { override fun onDestroy() {
super.onStop() super.onDestroy()
job.cancel() job?.cancel()
} }
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
startTask() startTask()
// Keyboard is sometimes open when going back to the app, so close it.
val imm = val imm =
getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(binding.root.windowToken, 0) imm.hideSoftInputFromWindow(binding.root.windowToken, 0)
@ -224,6 +218,7 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener,
private fun startTask() { private fun startTask() {
job = CoroutineScope(Dispatchers.Default).launch { job = CoroutineScope(Dispatchers.Default).launch {
while (true) { while (true) {
ensureActive()
manualRefresh() manualRefresh()
delay(5000) delay(5000)
} }
@ -232,7 +227,7 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener,
fun manualRefresh() { fun manualRefresh() {
CoroutineScope(Dispatchers.Default).launch { CoroutineScope(Dispatchers.Default).launch {
val updatedApps = getInstalledApps() val updatedApps = appUtils.getInstalledApps(this@AppMenuActivity)
val changes = detectChanges(installedApps, updatedApps) val changes = detectChanges(installedApps, updatedApps)
installedApps = updatedApps installedApps = updatedApps
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
@ -247,6 +242,7 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener,
val oldSet = oldList.map { Pair(it.first.applicationInfo.packageName, it.second.second) }.toSet() val oldSet = oldList.map { Pair(it.first.applicationInfo.packageName, it.second.second) }.toSet()
val newSet = newList.map { Pair(it.first.applicationInfo.packageName, it.second.second) }.toSet() val newSet = newList.map { Pair(it.first.applicationInfo.packageName, it.second.second) }.toSet()
//Detect updates
oldList.forEachIndexed { index, oldItem -> oldList.forEachIndexed { index, oldItem ->
if (newSet.contains(Pair(oldItem.first.applicationInfo.packageName, oldItem.second.second))) { if (newSet.contains(Pair(oldItem.first.applicationInfo.packageName, oldItem.second.second))) {
val newIndex = newList.indexOfFirst { it.first.applicationInfo.packageName == oldItem.first.applicationInfo.packageName && it.second.second == oldItem.second.second } val newIndex = newList.indexOfFirst { it.first.applicationInfo.packageName == oldItem.first.applicationInfo.packageName && it.second.second == oldItem.second.second }
@ -271,9 +267,6 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener,
} }
} }
// Detect updates
changes.addAll(removalChanges.reversed()) changes.addAll(removalChanges.reversed())
return changes return changes

View file

@ -0,0 +1,29 @@
package eu.ottop.yamlauncher
import android.app.Activity
import android.content.pm.LauncherActivityInfo
import android.content.pm.LauncherApps
import android.os.UserHandle
import androidx.appcompat.app.AppCompatActivity
class AppUtils {
private val sharedPreferenceManager = SharedPreferenceManager()
fun getInstalledApps(activity: Activity): List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>> {
val allApps = mutableListOf<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>()
val launcherApps = activity.getSystemService(AppCompatActivity.LAUNCHER_APPS_SERVICE) as LauncherApps
for (i in launcherApps.profiles.indices) {
launcherApps.getActivityList(null, launcherApps.profiles[i]).forEach { app ->
if (!sharedPreferenceManager.isAppHidden(activity, app.applicationInfo.packageName, i) && app.applicationInfo.packageName != activity.applicationInfo.packageName) {
allApps.add(Pair(app, Pair(launcherApps.profiles[i], i)))
}
}
}
return allApps.sortedBy {
sharedPreferenceManager.getAppName(activity, it.first.applicationInfo.packageName,it.second.second, it.first.applicationInfo.loadLabel(activity.packageManager)).toString().lowercase()
}
}
}

View file

@ -1,8 +1,10 @@
package eu.ottop.yamlauncher package eu.ottop.yamlauncher
import android.content.Context import android.content.Context
import android.content.pm.LauncherActivityInfo
import android.content.pm.LauncherApps import android.content.pm.LauncherApps
import android.os.Bundle import android.os.Bundle
import android.os.UserHandle
import android.view.GestureDetector import android.view.GestureDetector
import android.view.MotionEvent import android.view.MotionEvent
import android.widget.LinearLayout import android.widget.LinearLayout
@ -12,6 +14,9 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
import androidx.core.view.children import androidx.core.view.children
import eu.ottop.yamlauncher.databinding.ActivityMainBinding import eu.ottop.yamlauncher.databinding.ActivityMainBinding
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlin.math.abs import kotlin.math.abs
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
@ -19,7 +24,10 @@ class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding private lateinit var binding: ActivityMainBinding
private lateinit var gestureDetector: GestureDetector private lateinit var gestureDetector: GestureDetector
private lateinit var launcherApps: LauncherApps private lateinit var launcherApps: LauncherApps
private lateinit var installedApps: List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>
private val sharedPreferenceManager = SharedPreferenceManager() private val sharedPreferenceManager = SharedPreferenceManager()
private val appUtils = AppUtils()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -28,6 +36,9 @@ class MainActivity : AppCompatActivity() {
setSupportActionBar(null) setSupportActionBar(null)
launcherApps = getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps launcherApps = getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
CoroutineScope(Dispatchers.Default).launch {
installedApps = appUtils.getInstalledApps(this@MainActivity)
}
for (i in findViewById<LinearLayout>(R.id.shortcuts).children) { for (i in findViewById<LinearLayout>(R.id.shortcuts).children) {
@ -63,7 +74,7 @@ class MainActivity : AppCompatActivity() {
} }
i.setOnLongClickListener { i.setOnLongClickListener {
AppMenuActivity.start(this@MainActivity, "shortcut") { newText -> AppMenuActivity.start(this@MainActivity, installedApps, "shortcut") { newText ->
if (newText.first.second != 0) { if (newText.first.second != 0) {
textView.setCompoundDrawablesWithIntrinsicBounds(ResourcesCompat.getDrawable(resources, R.drawable.ic_work_app, null),null,null,null) textView.setCompoundDrawablesWithIntrinsicBounds(ResourcesCompat.getDrawable(resources, R.drawable.ic_work_app, null),null,null,null)
@ -123,7 +134,7 @@ class MainActivity : AppCompatActivity() {
} }
fun openAppMenuActivity() { fun openAppMenuActivity() {
AppMenuActivity.start(this) { AppMenuActivity.start(this, installedApps) {
} }
} }