Specific item updates added. Still needs testing and refinement.

This commit is contained in:
ottoptj 2024-05-20 04:01:28 +03:00
commit 131acb3039
4 changed files with 100 additions and 34 deletions

View file

@ -36,6 +36,7 @@ class AppActionMenu {
workProfile: Int, workProfile: Int,
launcherApps: LauncherApps, launcherApps: LauncherApps,
mainActivity: LauncherActivityInfo?, mainActivity: LauncherActivityInfo?,
position: Int
){ ){
actionMenu.findViewById<TextView>(R.id.info).setOnClickListener { actionMenu.findViewById<TextView>(R.id.info).setOnClickListener {
@ -93,7 +94,7 @@ class AppActionMenu {
imm.hideSoftInputFromWindow(editText.windowToken, 0) imm.hideSoftInputFromWindow(editText.windowToken, 0)
sharedPreferenceManager.setAppName(activity, appInfo.packageName, workProfile, editText.text.toString()) sharedPreferenceManager.setAppName(activity, appInfo.packageName, workProfile, editText.text.toString())
uiScope.launch { uiScope.launch {
activity.manualRefreshApps() activity.updateItem(position,Pair(mainActivity!!, Pair(userHandle, workProfile)))
} }
return@setOnEditorActionListener true return@setOnEditorActionListener true
@ -104,7 +105,8 @@ class AppActionMenu {
actionMenu.findViewById<TextView>(R.id.hide).setOnClickListener { actionMenu.findViewById<TextView>(R.id.hide).setOnClickListener {
sharedPreferenceManager.setAppHidden(activity, appInfo.packageName, workProfile, true) sharedPreferenceManager.setAppHidden(activity, appInfo.packageName, workProfile, true)
activity.manualRefreshApps() textView.visibility = View.GONE
editLayout.visibility = View.GONE
actionMenu.visibility = View.GONE actionMenu.visibility = View.GONE
} }

View file

@ -1,6 +1,5 @@
package eu.ottop.yamlauncher package eu.ottop.yamlauncher
import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.LauncherActivityInfo import android.content.pm.LauncherActivityInfo
@ -9,7 +8,6 @@ import android.os.Bundle
import android.os.UserHandle import android.os.UserHandle
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
import android.util.Log
import android.view.View import android.view.View
import android.widget.EditText import android.widget.EditText
import android.widget.LinearLayout import android.widget.LinearLayout
@ -45,7 +43,7 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener,
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 = "abcd" private const val MENU_MODE = "app"
fun start(context: Context, param1: String = "app", callback: (Pair<Pair<String, Int>, Pair<LauncherActivityInfo, UserHandle>>) -> Unit) { fun start(context: Context, 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 {
@ -77,7 +75,9 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener,
recyclerView.layoutManager = LinearLayoutManager(this) recyclerView.layoutManager = LinearLayoutManager(this)
installedApps = getInstalledApps() installedApps = getInstalledApps()
filteredApps = mutableListOf() filteredApps = mutableListOf()
adapter = AppMenuAdapter(this@AppMenuActivity, installedApps, this, this,this, menuMode) val newApps = mutableListOf<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>()
newApps.addAll(installedApps)
adapter = AppMenuAdapter(this@AppMenuActivity, newApps, this, this,this, menuMode)
recyclerView.adapter = adapter recyclerView.adapter = adapter
setupSearch() setupSearch()
@ -94,7 +94,7 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener,
} }
override fun onShortcut(appInfo: LauncherActivityInfo, userHandle: UserHandle, textView: TextView, userProfile: Int) { override fun onShortcut(appInfo: LauncherActivityInfo, userHandle: UserHandle, textView: TextView, userProfile: Int) {
callback.invoke(Pair(Pair(textView.text.toString(), userProfile), Pair(appInfo, userHandle,))) callback.invoke(Pair(Pair(textView.text.toString(), userProfile), Pair(appInfo, userHandle)))
finish() finish()
} }
@ -104,7 +104,8 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener,
userProfile: Int, userProfile: Int,
textView: TextView, textView: TextView,
actionMenuLayout: LinearLayout, actionMenuLayout: LinearLayout,
editView: LinearLayout editView: LinearLayout,
position: Int
) { ) {
textView.visibility = View.INVISIBLE textView.visibility = View.INVISIBLE
actionMenuLayout.visibility = View.VISIBLE actionMenuLayout.visibility = View.VISIBLE
@ -123,7 +124,8 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener,
userHandle, userHandle,
userProfile, userProfile,
launcherApps, launcherApps,
mainActivity mainActivity,
position
) )
} }
@ -166,7 +168,7 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener,
} }
} }
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
adapter.updateApps(filteredApps) //adapter.updateApps(filteredApps)
} }
} }
@ -209,9 +211,10 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener,
while (true) { while (true) {
val updatedApps = getInstalledApps() val updatedApps = getInstalledApps()
if (!listsEqual(installedApps, updatedApps)) { if (!listsEqual(installedApps, updatedApps)) {
val changes = detectChanges(installedApps, updatedApps)
installedApps = updatedApps installedApps = updatedApps
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
adapter.updateApps(installedApps) applyChanges(changes, installedApps)
} }
} }
delay(5000) delay(5000)
@ -219,15 +222,6 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener,
} }
} }
fun manualRefreshApps() {
CoroutineScope(Dispatchers.Default).launch {
installedApps = getInstalledApps()
withContext(Dispatchers.Main) {
adapter.updateApps(installedApps)
}
}
}
private fun listsEqual( private fun listsEqual(
list1: List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>, list1: List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>,
list2: List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>> list2: List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>
@ -243,4 +237,72 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener,
return true return true
} }
data class Change(val type: ChangeType, val position: Int)
enum class ChangeType {
INSERT, REMOVE, UPDATE
}
private fun detectChanges(oldList: List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>, newList: List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>): List<Change> {
val changes = mutableListOf<Change>()
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()
// Detect removals
oldList.forEachIndexed { index, oldItem ->
if (!newSet.contains(Pair(oldItem.first.applicationInfo.packageName, oldItem.second.second))) {
changes.add(Change(ChangeType.REMOVE, index))
}
}
// Detect insertions
newList.forEachIndexed { index, newItem ->
if (!oldSet.contains(Pair(newItem.first.applicationInfo.packageName, newItem.second.second))) {
changes.add(Change(ChangeType.INSERT, index))
}
}
// Detect updates
oldList.forEachIndexed { index, oldItem ->
if (newSet.contains(Pair(oldItem.first.applicationInfo.packageName, oldItem.second.second))) {
val newIndex = newList.indexOfFirst { it.first.applicationInfo.packageName == oldItem.first.applicationInfo.packageName }
if (oldItem.first.applicationInfo.packageName != newList[newIndex].first.applicationInfo.packageName) {
changes.add(Change(ChangeType.UPDATE, index))
}
}
}
return changes
}
private fun applyChanges(changes: List<Change>, updatedApps: List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>) {
changes.forEach { change ->
when (change.type) {
ChangeType.INSERT -> {
insertItem(change.position, updatedApps[change.position])
}
ChangeType.REMOVE -> {
removeItem(change.position)
}
ChangeType.UPDATE -> {
updateItem(change.position, updatedApps[change.position])
}
}
}
}
private fun insertItem(position: Int, app: Pair<LauncherActivityInfo, Pair<UserHandle, Int>>) {
adapter.addApp(position, app)
adapter.notifyItemInserted(position)
}
private fun removeItem(position: Int) {
adapter.removeApp(position)
adapter.notifyItemRemoved(position)
}
fun updateItem(position: Int, app: Pair<LauncherActivityInfo, Pair<UserHandle, Int>>) {
adapter.updateApp(position, app)
adapter.notifyItemChanged(position)
}
} }

View file

@ -2,7 +2,6 @@ package eu.ottop.yamlauncher
import android.content.Context import android.content.Context
import android.content.pm.LauncherActivityInfo import android.content.pm.LauncherActivityInfo
import android.content.res.Resources
import android.os.UserHandle import android.os.UserHandle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -18,7 +17,7 @@ import androidx.recyclerview.widget.RecyclerView
class AppMenuAdapter( class AppMenuAdapter(
private val activity: AppMenuActivity, private val activity: AppMenuActivity,
var apps: List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>, var apps: MutableList<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>,
private val itemClickListener: OnItemClickListener, private val itemClickListener: OnItemClickListener,
private val shortcutListener: OnShortcutListener, private val shortcutListener: OnShortcutListener,
private val itemLongClickListener: OnItemLongClickListener, private val itemLongClickListener: OnItemLongClickListener,
@ -43,7 +42,8 @@ class AppMenuAdapter(
userProfile: Int, userProfile: Int,
textView: TextView, textView: TextView,
actionMenuLayout: LinearLayout, actionMenuLayout: LinearLayout,
editView: LinearLayout editView: LinearLayout,
position: Int
) )
} }
@ -78,7 +78,8 @@ class AppMenuAdapter(
apps[position].second.second, apps[position].second.second,
textView, textView,
actionMenuLayout, actionMenuLayout,
editView editView,
position
) )
return@setOnLongClickListener true return@setOnLongClickListener true
} }
@ -115,7 +116,7 @@ class AppMenuAdapter(
val imm = activity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager val imm = activity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(holder.editView.windowToken, 0) imm.hideSoftInputFromWindow(holder.editView.windowToken, 0)
sharedPreferenceManager.resetAppName(activity, app.first.applicationInfo.packageName, app.second.second) sharedPreferenceManager.resetAppName(activity, app.first.applicationInfo.packageName, app.second.second)
activity.manualRefreshApps() updateApp(position, app)
} }
} }
@ -123,8 +124,15 @@ class AppMenuAdapter(
return apps.size return apps.size
} }
fun updateApps(newApps: List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>) { fun addApp(position: Int, app: Pair<LauncherActivityInfo, Pair<UserHandle, Int>>) {
apps = newApps apps.add(position, app)
notifyDataSetChanged() }
fun removeApp(position: Int) {
apps.removeAt(position)
}
fun updateApp(position: Int, app: Pair<LauncherActivityInfo, Pair<UserHandle, Int>>) {
apps[position] = app
} }
} }

View file

@ -1,19 +1,13 @@
package eu.ottop.yamlauncher package eu.ottop.yamlauncher
import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent
import android.content.pm.LauncherApps import android.content.pm.LauncherApps
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.GestureDetector import android.view.GestureDetector
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity 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