From f5a75f4263cf6f8431c93e67e86d18334997da43 Mon Sep 17 00:00:00 2001 From: ottoptj Date: Sun, 12 May 2024 21:44:46 +0300 Subject: [PATCH] Search functions. Hiding broken. --- .../eu/ottop/yamlauncher/AppActionMenu.kt | 5 +- .../eu/ottop/yamlauncher/AppMenuActivity.kt | 188 +++++++----------- .../eu/ottop/yamlauncher/AppMenuAdapter.kt | 86 ++++++++ local.properties | 8 + 4 files changed, 163 insertions(+), 124 deletions(-) create mode 100644 app/src/main/java/eu/ottop/yamlauncher/AppMenuAdapter.kt create mode 100644 local.properties diff --git a/app/src/main/java/eu/ottop/yamlauncher/AppActionMenu.kt b/app/src/main/java/eu/ottop/yamlauncher/AppActionMenu.kt index d603cbe..0c80149 100644 --- a/app/src/main/java/eu/ottop/yamlauncher/AppActionMenu.kt +++ b/app/src/main/java/eu/ottop/yamlauncher/AppActionMenu.kt @@ -35,7 +35,7 @@ class AppActionMenu { userHandle: UserHandle, workProfile: Int, launcherApps: LauncherApps, - mainActivity: LauncherActivityInfo? + mainActivity: LauncherActivityInfo?, ){ actionMenu.findViewById(R.id.info).setOnClickListener { @@ -104,8 +104,7 @@ class AppActionMenu { actionMenu.findViewById(R.id.hide).setOnClickListener { sharedPreferenceManager.setAppHidden(activity, appInfo.packageName, workProfile, true) - actionMenu.visibility = View.INVISIBLE - textView.visibility = View.INVISIBLE + } actionMenu.findViewById(R.id.close).setOnClickListener { diff --git a/app/src/main/java/eu/ottop/yamlauncher/AppMenuActivity.kt b/app/src/main/java/eu/ottop/yamlauncher/AppMenuActivity.kt index 118968e..6fb5a0c 100644 --- a/app/src/main/java/eu/ottop/yamlauncher/AppMenuActivity.kt +++ b/app/src/main/java/eu/ottop/yamlauncher/AppMenuActivity.kt @@ -23,8 +23,10 @@ import eu.ottop.yamlauncher.databinding.ActivityAppMenuBinding import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job +import kotlinx.coroutines.cancel import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext @@ -34,11 +36,14 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener, private lateinit var recyclerView: RecyclerView private lateinit var searchView: EditText private lateinit var adapter: AppMenuAdapter - private lateinit var shownApps: List>> + private lateinit var filteredApps: MutableList>> + private lateinit var installedApps: List>> private lateinit var job: Job private var appActionMenu = AppActionMenu() private lateinit var launcherApps: LauncherApps + private val sharedPreferenceManager = SharedPreferenceManager() + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityAppMenuBinding.inflate(layoutInflater) @@ -49,15 +54,12 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener, recyclerView = findViewById(R.id.recycler_view) recyclerView.layoutManager = LinearLayoutManager(this) - shownApps = getInstalledApps() - adapter = AppMenuAdapter(shownApps, this, this) + installedApps = getInstalledApps() + filteredApps = mutableListOf() + adapter = AppMenuAdapter(installedApps, this, this) recyclerView.adapter = adapter - binding.root.addOnLayoutChangeListener { _, _, top, _, bottom, _, oldTop, _, oldBottom -> - if (bottom - top > oldBottom - oldTop) { - searchView.clearFocus() - } - } + setupSearch() } override fun onItemClick(appInfo: LauncherActivityInfo, userHandle: UserHandle) { @@ -79,24 +81,6 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener, editView: LinearLayout ) { // Handle the long click action here, for example, show additional options or information about the app - editView.findViewById(R.id.app_name_edit).addTextChangedListener(object : - TextWatcher { - override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { - // This method is called before the text is changed - } - - override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { - // This method is called when the text is changed - // You can perform actions here based on the text changes - // For example, check if text is inserted or removed - filterItems(editView.findViewById(R.id.app_name_edit).text.toString()) - } - - override fun afterTextChanged(s: Editable?) { - - } - - }) textView.visibility = View.INVISIBLE actionMenuLayout.visibility = View.VISIBLE val mainActivity = launcherApps.getActivityList(appInfo.applicationInfo.packageName, userHandle).firstOrNull() @@ -104,42 +88,63 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener, } + private fun setupSearch() { + binding.root.addOnLayoutChangeListener { _, _, top, _, bottom, _, oldTop, _, oldBottom -> + if (bottom - top > oldBottom - oldTop) { + searchView.clearFocus() + } + } + + searchView.addTextChangedListener(object : + TextWatcher { + override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { + } + + override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { + filterItems(searchView.text.toString()) + } + + override fun afterTextChanged(s: Editable?) { + } + + }) + } + private fun filterItems(query: String?) { val cleanQuery = query?.replace("[^a-zA-Z0-9]".toRegex(), "") + filteredApps.clear() - for (i in 0 until binding.recyclerView.childCount) { - val view = binding.recyclerView.getChildAt(i) + if (cleanQuery.isNullOrEmpty()) { + filteredApps.addAll(installedApps) + } - - if (view is FrameLayout) { - for (i in 0 until view.childCount) { - val text = view.getChildAt(i) - if (text is TextView) { - val itemText = text.text.toString() - val cleanItemText = itemText.replace("[^a-zA-Z0-9]".toRegex(), "") - - if (cleanItemText.contains(cleanQuery ?: "", ignoreCase = true)) { - view.visibility = View.VISIBLE - } else { - view.visibility = View.GONE - } + else { + installedApps.forEach { + val cleanItemText = it.first.applicationInfo.loadLabel(packageManager).replace("[^a-zA-Z0-9]".toRegex(), "") + if (cleanItemText.contains(cleanQuery, ignoreCase=true)) { + filteredApps.add(it) } } } - }} - private fun getInstalledApps(): List>> { - val allApps = mutableListOf>>() - val launcherApps = getSystemService(LAUNCHER_APPS_SERVICE) as LauncherApps - for (i in launcherApps.profiles.indices) { - launcherApps.getActivityList(null, launcherApps.profiles[i]).forEach { app -> + adapter.updateApps(filteredApps) + + } + + private fun getInstalledApps(): List>> { + val allApps = mutableListOf>>() + val launcherApps = getSystemService(LAUNCHER_APPS_SERVICE) as LauncherApps + 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 { - it.first.applicationInfo.loadLabel(packageManager).toString().lowercase() - } } + return allApps.sortedBy { + it.first.applicationInfo.loadLabel(packageManager).toString().lowercase() + } + } override fun onStop() { super.onStop() @@ -155,10 +160,10 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener, private fun startTask() { job = CoroutineScope(Dispatchers.IO).launch { while (true) { - if (!listsEqual(shownApps, getInstalledApps())) { - shownApps = getInstalledApps() + if (!listsEqual(installedApps, getInstalledApps())) { + installedApps = getInstalledApps() withContext(Dispatchers.Main) { - adapter.updateApps(shownApps) + adapter.updateApps(installedApps) } } delay(5000) @@ -166,6 +171,15 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener, } } + fun manualRefreshApps() { + CoroutineScope(Dispatchers.IO).launch { + installedApps = getInstalledApps() + withContext(Dispatchers.Main) { + adapter.updateApps(installedApps) + } + } + } + private fun listsEqual( list1: List>>, list2: List>> @@ -183,75 +197,7 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener, } - class AppMenuAdapter(private var apps: List>>, private val itemClickListener: OnItemClickListener, private val itemLongClickListener: OnItemLongClickListener) : - RecyclerView.Adapter() { - interface OnItemClickListener { - fun onItemClick(appInfo: LauncherActivityInfo, userHandle: UserHandle) - } - - interface OnItemLongClickListener { - fun onItemLongClick( - appInfo: LauncherActivityInfo, - userHandle: UserHandle, - userProfile: Int, - textView: TextView, - actionMenuLayout: LinearLayout, - editView: LinearLayout - ) - } - - inner class AppViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - private val listItem: FrameLayout = itemView.findViewById(R.id.list_item) - val textView: TextView = listItem.findViewById(R.id.app_name) - val actionMenuLayout: LinearLayout = listItem.findViewById(R.id.action_menu) - val editView: LinearLayout = listItem.findViewById(R.id.rename_view) - - init { - itemView.setOnClickListener { - val position = bindingAdapterPosition - if (position != RecyclerView.NO_POSITION) { - val app = apps[position].first - itemClickListener.onItemClick(app, apps[position].second.first) - } - } - itemView.setOnLongClickListener { - val position = bindingAdapterPosition - if (position != RecyclerView.NO_POSITION) { - val app = apps[position].first - itemLongClickListener.onItemLongClick(app, apps[position].second.first, apps[position].second.second, textView, actionMenuLayout, editView) - return@setOnLongClickListener true - } - false - } - } - } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AppViewHolder { - val view = LayoutInflater.from(parent.context) - .inflate(R.layout.app_item_layout, parent, false) - return AppViewHolder(view) - } - - override fun onBindViewHolder(holder: AppViewHolder, position: Int) { - val app = apps[position] - val appInfo = app.first.activityInfo.applicationInfo - holder.textView.text = appInfo.loadLabel(holder.itemView.context.packageManager) - holder.editView.findViewById(R.id.app_name_edit).setText(holder.textView.text) - holder.actionMenuLayout.viewTreeObserver.addOnGlobalLayoutListener { - Log.d("Yooo", position.toString()) - // Perform any action you want here - } - } - - override fun getItemCount(): Int { - return apps.size - } - - fun updateApps(newApps: List>>) { - apps = newApps - notifyDataSetChanged() - } - } /* private lateinit var binding: ActivityAppMenuBinding diff --git a/app/src/main/java/eu/ottop/yamlauncher/AppMenuAdapter.kt b/app/src/main/java/eu/ottop/yamlauncher/AppMenuAdapter.kt new file mode 100644 index 0000000..f8b24ff --- /dev/null +++ b/app/src/main/java/eu/ottop/yamlauncher/AppMenuAdapter.kt @@ -0,0 +1,86 @@ +package eu.ottop.yamlauncher + +import android.content.pm.LauncherActivityInfo +import android.os.UserHandle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.EditText +import android.widget.FrameLayout +import android.widget.LinearLayout +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView + +class AppMenuAdapter(private var apps: List>>, private val itemClickListener: OnItemClickListener, private val itemLongClickListener: OnItemLongClickListener) : + RecyclerView.Adapter() { + + interface OnItemClickListener { + fun onItemClick(appInfo: LauncherActivityInfo, userHandle: UserHandle) + } + + interface OnItemLongClickListener { + fun onItemLongClick( + appInfo: LauncherActivityInfo, + userHandle: UserHandle, + userProfile: Int, + textView: TextView, + actionMenuLayout: LinearLayout, + editView: LinearLayout + ) + } + + inner class AppViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + private val listItem: FrameLayout = itemView.findViewById(R.id.list_item) + val textView: TextView = listItem.findViewById(R.id.app_name) + val actionMenuLayout: LinearLayout = listItem.findViewById(R.id.action_menu) + val editView: LinearLayout = listItem.findViewById(R.id.rename_view) + + init { + actionMenuLayout.visibility = View.GONE + editView.visibility = View.GONE + + itemView.setOnClickListener { + val position = bindingAdapterPosition + if (position != RecyclerView.NO_POSITION) { + val app = apps[position].first + itemClickListener.onItemClick(app, apps[position].second.first) + } + } + itemView.setOnLongClickListener { + val position = bindingAdapterPosition + if (position != RecyclerView.NO_POSITION) { + val app = apps[position].first + itemLongClickListener.onItemLongClick(app, apps[position].second.first, apps[position].second.second, textView, actionMenuLayout, editView) + return@setOnLongClickListener true + } + false + } + } + } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AppViewHolder { + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.app_item_layout, parent, false) + return AppViewHolder(view) + } + + override fun onBindViewHolder(holder: AppViewHolder, position: Int) { + val app = apps[position] + val appInfo = app.first.activityInfo.applicationInfo + holder.textView.text = appInfo.loadLabel(holder.itemView.context.packageManager) + holder.editView.findViewById(R.id.app_name_edit).setText(holder.textView.text) + holder.actionMenuLayout.viewTreeObserver.addOnGlobalLayoutListener { + Log.d("Yooo", position.toString()) + // Perform any action you want here + } + } + + override fun getItemCount(): Int { + return apps.size + } + + fun updateApps(newApps: List>>) { + apps = newApps + notifyDataSetChanged() + } +} \ No newline at end of file diff --git a/local.properties b/local.properties new file mode 100644 index 0000000..caffe14 --- /dev/null +++ b/local.properties @@ -0,0 +1,8 @@ +## This file must *NOT* be checked into Version Control Systems, +# as it contains information specific to your local configuration. +# +# Location of the SDK. This is only used by Gradle. +# For customization when using a Version Control System, please read the +# header note. +#Sat May 11 12:03:38 EEST 2024 +sdk.dir=/home/otto/Android/Sdk