Compare commits
49 changed files with 1153 additions and 491 deletions
5
app/proguard-rules.pro
vendored
5
app/proguard-rules.pro
vendored
|
|
@ -1,8 +1,3 @@
|
||||||
# Xposed
|
|
||||||
-keepclassmembers class icu.nullptr.hidemyapplist.MyApp {
|
|
||||||
boolean isHooked;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Enum class
|
# Enum class
|
||||||
-keepclassmembers,allowoptimization enum * {
|
-keepclassmembers,allowoptimization enum * {
|
||||||
public static **[] values();
|
public static **[] values();
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,6 @@
|
||||||
android:name="android.permission.QUERY_ALL_PACKAGES"
|
android:name="android.permission.QUERY_ALL_PACKAGES"
|
||||||
tools:ignore="PackageVisibilityPolicy,QueryAllPackagesPermission" />
|
tools:ignore="PackageVisibilityPolicy,QueryAllPackagesPermission" />
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name="icu.nullptr.hidemyapplist.MyApp"
|
android:name="icu.nullptr.hidemyapplist.MyApp"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,6 @@ import kotlin.system.exitProcess
|
||||||
lateinit var hmaApp: MyApp
|
lateinit var hmaApp: MyApp
|
||||||
|
|
||||||
class MyApp : Application() {
|
class MyApp : Application() {
|
||||||
|
|
||||||
@JvmField
|
|
||||||
var isHooked = false
|
|
||||||
|
|
||||||
val globalScope = CoroutineScope(Dispatchers.Default)
|
val globalScope = CoroutineScope(Dispatchers.Default)
|
||||||
val appIconLoader by lazy {
|
val appIconLoader by lazy {
|
||||||
val iconSize = resources.getDimensionPixelSize(R.dimen.app_icon_size)
|
val iconSize = resources.getDimensionPixelSize(R.dimen.app_icon_size)
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import java.io.File
|
||||||
object ConfigManager {
|
object ConfigManager {
|
||||||
|
|
||||||
data class TemplateInfo(val name: String?, val isWhiteList: Boolean)
|
data class TemplateInfo(val name: String?, val isWhiteList: Boolean)
|
||||||
|
data class PresetInfo(val name: String, val translation: String)
|
||||||
|
|
||||||
private const val TAG = "ConfigManager"
|
private const val TAG = "ConfigManager"
|
||||||
private lateinit var config: JsonConfig
|
private lateinit var config: JsonConfig
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ object PrefManager {
|
||||||
private const val PREF_THEME_COLOR = "theme_color"
|
private const val PREF_THEME_COLOR = "theme_color"
|
||||||
|
|
||||||
private const val PREF_HIDE_ICON = "hide_icon"
|
private const val PREF_HIDE_ICON = "hide_icon"
|
||||||
|
private const val PREF_BYPASS_RISKY_PACKAGE_WARNING = "bypass_risky_package_warning"
|
||||||
|
|
||||||
private const val PREF_APP_FILTER_SHOW_SYSTEM = "app_filter_show_system"
|
private const val PREF_APP_FILTER_SHOW_SYSTEM = "app_filter_show_system"
|
||||||
private const val PREF_APP_FILTER_SORT_METHOD = "app_filter_sort_method"
|
private const val PREF_APP_FILTER_SORT_METHOD = "app_filter_sort_method"
|
||||||
|
|
@ -67,6 +68,10 @@ object PrefManager {
|
||||||
hmaApp.packageManager.setComponentEnabledSetting(component, status, PackageManager.DONT_KILL_APP)
|
hmaApp.packageManager.setComponentEnabledSetting(component, status, PackageManager.DONT_KILL_APP)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var bypassRiskyPackageWarning: Boolean
|
||||||
|
get() = pref.getBoolean(PREF_BYPASS_RISKY_PACKAGE_WARNING, false)
|
||||||
|
set(value) = pref.edit().putBoolean(PREF_BYPASS_RISKY_PACKAGE_WARNING, value).apply()
|
||||||
|
|
||||||
var appFilter_showSystem: Boolean
|
var appFilter_showSystem: Boolean
|
||||||
get() = pref.getBoolean(PREF_APP_FILTER_SHOW_SYSTEM, false)
|
get() = pref.getBoolean(PREF_APP_FILTER_SHOW_SYSTEM, false)
|
||||||
set(value) = pref.edit().putBoolean(PREF_APP_FILTER_SHOW_SYSTEM, value).apply()
|
set(value) = pref.edit().putBoolean(PREF_APP_FILTER_SHOW_SYSTEM, value).apply()
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,9 @@ object ServiceClient : IHMAService, IBinder.DeathRecipient {
|
||||||
getServiceLegacy()?.handlePackageEvent(eventType, packageName)
|
getServiceLegacy()?.handlePackageEvent(eventType, packageName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getPackagesForPreset(presetName: String) =
|
||||||
|
getServiceLegacy()?.getPackagesForPreset(presetName)
|
||||||
|
|
||||||
override fun syncConfig(json: String) {
|
override fun syncConfig(json: String) {
|
||||||
getServiceLegacy()?.syncConfig(json)
|
getServiceLegacy()?.syncConfig(json)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,10 @@ class AboutActivity : AbsAboutActivity() {
|
||||||
items.add(Contributor(R.drawable.cont_icon_designer, "辉少菌", "Icon designer", "http://www.coolapk.com/u/1560270"))
|
items.add(Contributor(R.drawable.cont_icon_designer, "辉少菌", "Icon designer", "http://www.coolapk.com/u/1560270"))
|
||||||
items.add(Line())
|
items.add(Line())
|
||||||
items.add(Contributor(R.drawable.cont_cpp_master, "LoveSy", "Idea provider", "https://github.com/yujincheng08"))
|
items.add(Contributor(R.drawable.cont_cpp_master, "LoveSy", "Idea provider", "https://github.com/yujincheng08"))
|
||||||
items.add(Contributor(R.drawable.cont_cuynu, "Cuynu", "loser?", "https://git.disroot.org/cuynu"))
|
|
||||||
|
|
||||||
|
items.add(Category(getString(R.string.about_fakedev)))
|
||||||
|
items.add(Contributor(R.drawable.cont_cuynu, "Cuynu", "another loser with no coding skills", "https://git.disroot.org/cuynu"))
|
||||||
|
|
||||||
items.add(Category(getString(R.string.about_support)))
|
items.add(Category(getString(R.string.about_support)))
|
||||||
items.add(Card("Disroot\nhttps://git.disroot.org/cuynu/HMAL-OSS"))
|
items.add(Card("Disroot\nhttps://git.disroot.org/cuynu/HMAL-OSS"))
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,35 @@
|
||||||
package icu.nullptr.hidemyapplist.ui.adapter
|
package icu.nullptr.hidemyapplist.ui.adapter
|
||||||
|
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import icu.nullptr.hidemyapplist.common.Constants.GMS_PACKAGE_NAME
|
||||||
|
import icu.nullptr.hidemyapplist.common.Constants.GSF_PACKAGE_NAME
|
||||||
import icu.nullptr.hidemyapplist.service.ConfigManager
|
import icu.nullptr.hidemyapplist.service.ConfigManager
|
||||||
|
import icu.nullptr.hidemyapplist.service.PrefManager
|
||||||
import icu.nullptr.hidemyapplist.ui.view.AppItemView
|
import icu.nullptr.hidemyapplist.ui.view.AppItemView
|
||||||
|
import org.frknkrc44.hma_oss.R
|
||||||
|
|
||||||
class AppManageAdapter(
|
class AppManageAdapter(
|
||||||
private val onItemClickListener: (String) -> Unit
|
private val onItemClickListener: (String) -> Unit
|
||||||
) : AppSelectAdapter() {
|
) : AppSelectAdapter() {
|
||||||
|
private val riskyPackages = arrayOf(GMS_PACKAGE_NAME, GSF_PACKAGE_NAME)
|
||||||
|
|
||||||
inner class ViewHolder(view: AppItemView) : AppSelectAdapter.ViewHolder(view) {
|
inner class ViewHolder(view: AppItemView) : AppSelectAdapter.ViewHolder(view) {
|
||||||
init {
|
init {
|
||||||
view.setOnClickListener {
|
view.setOnClickListener {
|
||||||
|
if (!PrefManager.bypassRiskyPackageWarning && riskyPackages.contains(view.binding.packageName.text)) {
|
||||||
|
MaterialAlertDialogBuilder(view.context)
|
||||||
|
.setTitle(R.string.app_warning_risky_package_title)
|
||||||
|
.setMessage(R.string.app_warning_risky_package_desc)
|
||||||
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
|
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
|
onItemClickListener.invoke(filteredList[absoluteAdapterPosition])
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
|
||||||
onItemClickListener.invoke(filteredList[absoluteAdapterPosition])
|
onItemClickListener.invoke(filteredList[absoluteAdapterPosition])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import icu.nullptr.hidemyapplist.ui.view.AppItemView
|
||||||
import icu.nullptr.hidemyapplist.util.PackageHelper
|
import icu.nullptr.hidemyapplist.util.PackageHelper
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import org.frknkrc44.hma_oss.BuildConfig
|
||||||
|
|
||||||
abstract class AppSelectAdapter(
|
abstract class AppSelectAdapter(
|
||||||
private val firstFilter: ((String) -> Boolean)? = null
|
private val firstFilter: ((String) -> Boolean)? = null
|
||||||
|
|
@ -20,13 +21,15 @@ abstract class AppSelectAdapter(
|
||||||
private inner class AppFilter : Filter() {
|
private inner class AppFilter : Filter() {
|
||||||
override fun performFiltering(constraint: CharSequence): FilterResults {
|
override fun performFiltering(constraint: CharSequence): FilterResults {
|
||||||
return runBlocking {
|
return runBlocking {
|
||||||
val constraintLowered = constraint.toString().lowercase()
|
val constraintLowered = constraint.toString().trim().lowercase()
|
||||||
val filteredList = PackageHelper.appList.first().filter {
|
val filteredList = PackageHelper.appList.first().filter {
|
||||||
if (firstFilter?.invoke(it) == false) return@filter false
|
if (firstFilter?.invoke(it) == false) return@filter false
|
||||||
if (!PrefManager.appFilter_showSystem && PackageHelper.isSystem(it)) return@filter false
|
if (!PrefManager.appFilter_showSystem && PackageHelper.isSystem(it)) return@filter false
|
||||||
|
if (it == BuildConfig.APPLICATION_ID &&
|
||||||
|
(this@AppSelectAdapter.javaClass == AppManageAdapter::class.java ||
|
||||||
|
(this@AppSelectAdapter.javaClass == AppScopeAdapter::class.java && firstFilter != null))) return@filter false
|
||||||
val label = PackageHelper.loadAppLabel(it)
|
val label = PackageHelper.loadAppLabel(it)
|
||||||
val packageInfo = PackageHelper.loadPackageInfo(it)
|
label.lowercase().contains(constraintLowered) || it.lowercase().contains(constraintLowered)
|
||||||
label.lowercase().contains(constraintLowered) || packageInfo.packageName.lowercase().contains(constraintLowered)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FilterResults().also { it.values = filteredList }
|
FilterResults().also { it.values = filteredList }
|
||||||
|
|
@ -35,8 +38,11 @@ abstract class AppSelectAdapter(
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST", "NotifyDataSetChanged")
|
@Suppress("UNCHECKED_CAST", "NotifyDataSetChanged")
|
||||||
override fun publishResults(constraint: CharSequence, results: FilterResults) {
|
override fun publishResults(constraint: CharSequence, results: FilterResults) {
|
||||||
filteredList = results.values as List<String>
|
val values = results.values
|
||||||
notifyDataSetChanged()
|
if (values != null) {
|
||||||
|
filteredList = values as List<String>
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,14 @@ import android.os.Bundle
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowInsets
|
import android.view.WindowInsets
|
||||||
|
import android.widget.TextView
|
||||||
import androidx.activity.addCallback
|
import androidx.activity.addCallback
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.flowWithLifecycle
|
import androidx.lifecycle.flowWithLifecycle
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||||
import icu.nullptr.hidemyapplist.service.PrefManager
|
import icu.nullptr.hidemyapplist.service.PrefManager
|
||||||
import icu.nullptr.hidemyapplist.ui.adapter.AppSelectAdapter
|
import icu.nullptr.hidemyapplist.ui.adapter.AppSelectAdapter
|
||||||
|
|
@ -20,10 +22,11 @@ import icu.nullptr.hidemyapplist.util.PackageHelper
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.frknkrc44.hma_oss.R
|
import org.frknkrc44.hma_oss.R
|
||||||
import org.frknkrc44.hma_oss.databinding.FragmentAppSelectBinding
|
import org.frknkrc44.hma_oss.databinding.FragmentAppSelectBinding
|
||||||
|
import org.frknkrc44.hma_oss.ui.fragment.AppPresetFragment
|
||||||
|
|
||||||
abstract class AppSelectFragment : Fragment(R.layout.fragment_app_select) {
|
abstract class AppSelectFragment : Fragment(R.layout.fragment_app_select) {
|
||||||
|
|
||||||
private val binding by viewBinding<FragmentAppSelectBinding>()
|
protected val binding by viewBinding<FragmentAppSelectBinding>()
|
||||||
|
|
||||||
protected abstract val firstComparator: Comparator<String>
|
protected abstract val firstComparator: Comparator<String>
|
||||||
protected abstract val adapter: AppSelectAdapter
|
protected abstract val adapter: AppSelectAdapter
|
||||||
|
|
@ -34,17 +37,21 @@ abstract class AppSelectFragment : Fragment(R.layout.fragment_app_select) {
|
||||||
navController.navigateUp()
|
navController.navigateUp()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun applyFilter() {
|
protected fun applyFilter() {
|
||||||
adapter.filter.filter(search)
|
adapter.filter.filter(search)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sortList() {
|
protected open fun sortList() {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
PackageHelper.sortList(firstComparator)
|
PackageHelper.sortList(firstComparator)
|
||||||
applyFilter()
|
applyFilter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open fun invalidateCache() {
|
||||||
|
PackageHelper.invalidateCache()
|
||||||
|
}
|
||||||
|
|
||||||
private fun onMenuOptionSelected(item: MenuItem) {
|
private fun onMenuOptionSelected(item: MenuItem) {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.menu_show_system -> {
|
R.id.menu_show_system -> {
|
||||||
|
|
@ -75,11 +82,13 @@ abstract class AppSelectFragment : Fragment(R.layout.fragment_app_select) {
|
||||||
sortList()
|
sortList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open fun getFragmentTitle() = getString(R.string.title_app_select)
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { onBack() }
|
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { onBack() }
|
||||||
setupToolbar(
|
setupToolbar(
|
||||||
toolbar = binding.toolbar,
|
toolbar = binding.toolbar,
|
||||||
title = getString(R.string.title_app_select),
|
title = getFragmentTitle(),
|
||||||
navigationIcon = R.drawable.baseline_arrow_back_24,
|
navigationIcon = R.drawable.baseline_arrow_back_24,
|
||||||
navigationOnClick = { onBack() },
|
navigationOnClick = { onBack() },
|
||||||
menuRes = R.menu.menu_app_list,
|
menuRes = R.menu.menu_app_list,
|
||||||
|
|
@ -110,9 +119,16 @@ abstract class AppSelectFragment : Fragment(R.layout.fragment_app_select) {
|
||||||
binding.list.layoutManager = LinearLayoutManager(context)
|
binding.list.layoutManager = LinearLayoutManager(context)
|
||||||
binding.list.adapter = adapter
|
binding.list.adapter = adapter
|
||||||
binding.swipeRefresh.setOnRefreshListener {
|
binding.swipeRefresh.setOnRefreshListener {
|
||||||
PackageHelper.invalidateCache()
|
invalidateCache()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
adapter.registerAdapterDataObserver(
|
||||||
|
EmptyDataObserver(
|
||||||
|
binding.list,
|
||||||
|
binding.listEmptyContainer
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
PackageHelper.isRefreshing
|
PackageHelper.isRefreshing
|
||||||
.flowWithLifecycle(lifecycle)
|
.flowWithLifecycle(lifecycle)
|
||||||
|
|
@ -145,4 +161,44 @@ abstract class AppSelectFragment : Fragment(R.layout.fragment_app_select) {
|
||||||
insets
|
insets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Credit: https://medium.com/nerd-for-tech/empty-dataset-in-recyclerview-ad86833dd5c6
|
||||||
|
inner class EmptyDataObserver(
|
||||||
|
private val recyclerView: RecyclerView,
|
||||||
|
private val emptyView: View
|
||||||
|
): RecyclerView.AdapterDataObserver() {
|
||||||
|
private val fragmentType by lazy {
|
||||||
|
when(this@AppSelectFragment.javaClass) {
|
||||||
|
ScopeFragment::class.java -> 0
|
||||||
|
AppPresetFragment::class.java -> 1
|
||||||
|
else -> 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val atLeastEntryCount: Int get() {
|
||||||
|
if (!search.isBlank()) return 0
|
||||||
|
|
||||||
|
return if (fragmentType < 2) 1 else 2
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkIfEmpty() {
|
||||||
|
val emptyViewVisible = recyclerView.adapter!!.itemCount < atLeastEntryCount
|
||||||
|
emptyView.visibility = if (emptyViewVisible) View.VISIBLE else View.GONE
|
||||||
|
if (emptyViewVisible) {
|
||||||
|
emptyView.findViewById<TextView>(R.id.list_empty_text).text = getString(
|
||||||
|
when (fragmentType) {
|
||||||
|
0 -> R.string.list_empty_no_enabled
|
||||||
|
1 -> R.string.list_empty_preset
|
||||||
|
else -> R.string.list_empty_no_apps
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
recyclerView.visibility = if (emptyViewVisible) View.GONE else View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onChanged() {
|
||||||
|
super.onChanged()
|
||||||
|
checkIfEmpty()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,7 @@ class SettingsFragment : Fragment(R.layout.fragment_settings), PreferenceFragmen
|
||||||
"blackDarkTheme" -> PrefManager.blackDarkTheme
|
"blackDarkTheme" -> PrefManager.blackDarkTheme
|
||||||
"detailLog" -> ConfigManager.detailLog
|
"detailLog" -> ConfigManager.detailLog
|
||||||
"hideIcon" -> PrefManager.hideIcon
|
"hideIcon" -> PrefManager.hideIcon
|
||||||
|
"bypassRiskyPackageWarning" -> PrefManager.bypassRiskyPackageWarning
|
||||||
"appDataIsolation" -> CommonUtils.isAppDataIsolationEnabled
|
"appDataIsolation" -> CommonUtils.isAppDataIsolationEnabled
|
||||||
"voldAppDataIsolation" -> CommonUtils.isVoldAppDataIsolationEnabled
|
"voldAppDataIsolation" -> CommonUtils.isVoldAppDataIsolationEnabled
|
||||||
"forceMountData" -> ConfigManager.forceMountData
|
"forceMountData" -> ConfigManager.forceMountData
|
||||||
|
|
@ -121,6 +122,7 @@ class SettingsFragment : Fragment(R.layout.fragment_settings), PreferenceFragmen
|
||||||
"detailLog" -> ConfigManager.detailLog = value
|
"detailLog" -> ConfigManager.detailLog = value
|
||||||
"forceMountData" -> ConfigManager.forceMountData = value
|
"forceMountData" -> ConfigManager.forceMountData = value
|
||||||
"hideIcon" -> PrefManager.hideIcon = value
|
"hideIcon" -> PrefManager.hideIcon = value
|
||||||
|
"bypassRiskyPackageWarning" -> PrefManager.bypassRiskyPackageWarning = value
|
||||||
"appDataIsolation" -> Unit
|
"appDataIsolation" -> Unit
|
||||||
"voldAppDataIsolation" -> Unit
|
"voldAppDataIsolation" -> Unit
|
||||||
else -> throw IllegalArgumentException("Invalid key: $key")
|
else -> throw IllegalArgumentException("Invalid key: $key")
|
||||||
|
|
@ -267,6 +269,11 @@ class SettingsFragment : Fragment(R.layout.fragment_settings), PreferenceFragmen
|
||||||
|
|
||||||
configureDataIsolation()
|
configureDataIsolation()
|
||||||
|
|
||||||
|
findPreference<SwitchPreferenceCompat>("bypassRiskyPackageWarning")?.setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
activity?.recreate()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
findPreference<Preference>("stopSystemService")?.setOnPreferenceClickListener {
|
findPreference<Preference>("stopSystemService")?.setOnPreferenceClickListener {
|
||||||
if (ServiceClient.serviceVersion != 0) {
|
if (ServiceClient.serviceVersion != 0) {
|
||||||
MaterialAlertDialogBuilder(requireContext())
|
MaterialAlertDialogBuilder(requireContext())
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package icu.nullptr.hidemyapplist.ui.fragment
|
package icu.nullptr.hidemyapplist.ui.fragment
|
||||||
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
|
@ -12,7 +11,6 @@ import androidx.fragment.app.setFragmentResultListener
|
||||||
import androidx.navigation.fragment.FragmentNavigatorExtras
|
import androidx.navigation.fragment.FragmentNavigatorExtras
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||||
import com.google.android.material.transition.MaterialContainerTransform
|
|
||||||
import icu.nullptr.hidemyapplist.common.JsonConfig
|
import icu.nullptr.hidemyapplist.common.JsonConfig
|
||||||
import icu.nullptr.hidemyapplist.service.ConfigManager
|
import icu.nullptr.hidemyapplist.service.ConfigManager
|
||||||
import icu.nullptr.hidemyapplist.ui.adapter.TemplateAdapter
|
import icu.nullptr.hidemyapplist.ui.adapter.TemplateAdapter
|
||||||
|
|
@ -26,14 +24,6 @@ class TemplateManageFragment : Fragment(R.layout.fragment_template_manage) {
|
||||||
private val binding by viewBinding<FragmentTemplateManageBinding>()
|
private val binding by viewBinding<FragmentTemplateManageBinding>()
|
||||||
private val adapter = TemplateAdapter(this::navigateToSettings)
|
private val adapter = TemplateAdapter(this::navigateToSettings)
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
sharedElementEnterTransition = MaterialContainerTransform().apply {
|
|
||||||
drawingViewId = R.id.nav_host_fragment
|
|
||||||
scrimColor = Color.TRANSPARENT
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
setupToolbar(
|
setupToolbar(
|
||||||
toolbar = binding.toolbar,
|
toolbar = binding.toolbar,
|
||||||
|
|
|
||||||
|
|
@ -56,16 +56,6 @@ class TemplateSettingsFragment : Fragment(R.layout.fragment_template_settings) {
|
||||||
navController.navigateUp()
|
navController.navigateUp()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
/*
|
|
||||||
sharedElementEnterTransition = MaterialContainerTransform().apply {
|
|
||||||
drawingViewId = R.id.nav_host_fragment
|
|
||||||
scrimColor = Color.TRANSPARENT
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { onBack(false) }
|
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { onBack(false) }
|
||||||
setupToolbar(
|
setupToolbar(
|
||||||
|
|
@ -80,6 +70,7 @@ class TemplateSettingsFragment : Fragment(R.layout.fragment_template_settings) {
|
||||||
)
|
)
|
||||||
|
|
||||||
binding.templateName.setText(viewModel.name)
|
binding.templateName.setText(viewModel.name)
|
||||||
|
binding.workMode.setText(if (viewModel.isWhiteList) R.string.whitelist else R.string.blacklist)
|
||||||
binding.templateName.addTextChangedListener { viewModel.name = it.toString() }
|
binding.templateName.addTextChangedListener { viewModel.name = it.toString() }
|
||||||
binding.targetApps.setOnClickListener {
|
binding.targetApps.setOnClickListener {
|
||||||
setFragmentResultListener("app_select") { _, bundle ->
|
setFragmentResultListener("app_select") { _, bundle ->
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ class AppItemView @JvmOverloads constructor(
|
||||||
defStyleRes: Int = 0
|
defStyleRes: Int = 0
|
||||||
) : LinearLayout(context, attrs, defStyleAttr, defStyleRes) {
|
) : LinearLayout(context, attrs, defStyleAttr, defStyleRes) {
|
||||||
|
|
||||||
private val binding by viewBinding<AppItemViewBinding>(createMethod = CreateMethod.INFLATE)
|
val binding by viewBinding<AppItemViewBinding>(createMethod = CreateMethod.INFLATE)
|
||||||
|
|
||||||
var showEnabled: Boolean
|
var showEnabled: Boolean
|
||||||
get() = binding.enabled.visibility == VISIBLE
|
get() = binding.enabled.visibility == VISIBLE
|
||||||
|
|
@ -35,7 +35,12 @@ class AppItemView @JvmOverloads constructor(
|
||||||
|
|
||||||
fun load(packageName: String) {
|
fun load(packageName: String) {
|
||||||
binding.packageName.text = packageName
|
binding.packageName.text = packageName
|
||||||
binding.label.text = PackageHelper.loadAppLabel(packageName)
|
try {
|
||||||
binding.icon.setImageBitmap(PackageHelper.loadAppIcon(packageName))
|
binding.label.text = PackageHelper.loadAppLabel(packageName)
|
||||||
|
binding.icon.setImageBitmap(PackageHelper.loadAppIcon(packageName))
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
binding.label.text = packageName
|
||||||
|
binding.icon.setImageResource(android.R.drawable.sym_def_app_icon)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,15 @@ object PackageHelper {
|
||||||
val icon: Bitmap
|
val icon: Bitmap
|
||||||
)
|
)
|
||||||
|
|
||||||
private object Comparators {
|
object Comparators {
|
||||||
val byLabel = Comparator<String> { o1, o2 ->
|
val byLabel = Comparator<String> { o1, o2 ->
|
||||||
val n1 = loadAppLabel(o1).lowercase(Locale.getDefault())
|
try {
|
||||||
val n2 = loadAppLabel(o2).lowercase(Locale.getDefault())
|
val n1 = loadAppLabel(o1).lowercase(Locale.getDefault())
|
||||||
Collator.getInstance(Locale.getDefault()).compare(n1, n2)
|
val n2 = loadAppLabel(o2).lowercase(Locale.getDefault())
|
||||||
|
Collator.getInstance(Locale.getDefault()).compare(n1, n2)
|
||||||
|
} catch (_: Throwable) {
|
||||||
|
byPackageName.compare(o1, o2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val byPackageName = Comparator<String> { o1, o2 ->
|
val byPackageName = Comparator<String> { o1, o2 ->
|
||||||
val n1 = o1.lowercase(Locale.getDefault())
|
val n1 = o1.lowercase(Locale.getDefault())
|
||||||
|
|
@ -38,14 +42,22 @@ object PackageHelper {
|
||||||
Collator.getInstance(Locale.getDefault()).compare(n1, n2)
|
Collator.getInstance(Locale.getDefault()).compare(n1, n2)
|
||||||
}
|
}
|
||||||
val byInstallTime = Comparator<String> { o1, o2 ->
|
val byInstallTime = Comparator<String> { o1, o2 ->
|
||||||
val n1 = loadPackageInfo(o1).firstInstallTime
|
try {
|
||||||
val n2 = loadPackageInfo(o2).firstInstallTime
|
val n1 = loadPackageInfo(o1).firstInstallTime
|
||||||
n2.compareTo(n1)
|
val n2 = loadPackageInfo(o2).firstInstallTime
|
||||||
|
n2.compareTo(n1)
|
||||||
|
} catch (_: Throwable) {
|
||||||
|
byPackageName.compare(o1, o2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val byUpdateTime = Comparator<String> { o1, o2 ->
|
val byUpdateTime = Comparator<String> { o1, o2 ->
|
||||||
val n1 = loadPackageInfo(o1).lastUpdateTime
|
try {
|
||||||
val n2 = loadPackageInfo(o2).lastUpdateTime
|
val n1 = loadPackageInfo(o1).lastUpdateTime
|
||||||
n2.compareTo(n1)
|
val n2 = loadPackageInfo(o2).lastUpdateTime
|
||||||
|
n2.compareTo(n1)
|
||||||
|
} catch (_: Throwable) {
|
||||||
|
byPackageName.compare(o1, o2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -99,6 +111,10 @@ object PackageHelper {
|
||||||
mAppList.emit(list)
|
mAppList.emit(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun exists(packageName: String) = runBlocking {
|
||||||
|
packageCache.first().contains(packageName)
|
||||||
|
}
|
||||||
|
|
||||||
fun loadPackageInfo(packageName: String): PackageInfo = runBlocking {
|
fun loadPackageInfo(packageName: String): PackageInfo = runBlocking {
|
||||||
packageCache.first()[packageName]!!.info
|
packageCache.first()[packageName]!!.info
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
package org.frknkrc44.hma_oss.ui.adapter
|
||||||
|
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.Filter
|
||||||
|
import icu.nullptr.hidemyapplist.service.ServiceClient
|
||||||
|
import icu.nullptr.hidemyapplist.ui.adapter.AppSelectAdapter
|
||||||
|
import icu.nullptr.hidemyapplist.ui.view.AppItemView
|
||||||
|
import icu.nullptr.hidemyapplist.util.PackageHelper
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
|
||||||
|
class AppPresetAdapter(
|
||||||
|
private val presetName: String
|
||||||
|
) : AppSelectAdapter() {
|
||||||
|
var packages = mutableListOf<String>()
|
||||||
|
|
||||||
|
fun updateList() {
|
||||||
|
packages.clear()
|
||||||
|
packages += ServiceClient.getPackagesForPreset(presetName)?.toList() ?: listOf()
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class ViewHolder(view: AppItemView) : AppSelectAdapter.ViewHolder(view) {
|
||||||
|
override fun bind(packageName: String) {
|
||||||
|
(itemView as AppItemView).let {
|
||||||
|
it.load(packageName)
|
||||||
|
it.alpha = if (!PackageHelper.exists(packageName)) 0.5f else 1.0f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
val view = AppItemView(parent.context, false)
|
||||||
|
view.layoutParams = ViewGroup.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
)
|
||||||
|
return ViewHolder(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class PresetFilter : Filter() {
|
||||||
|
|
||||||
|
override fun performFiltering(constraint: CharSequence): FilterResults {
|
||||||
|
return runBlocking {
|
||||||
|
val constraintLowered = constraint.toString().trim().lowercase()
|
||||||
|
val filteredList = packages.filter {
|
||||||
|
if (constraintLowered.isEmpty()) return@filter true
|
||||||
|
|
||||||
|
if (it.lowercase().contains(constraintLowered)) return@filter true
|
||||||
|
|
||||||
|
try {
|
||||||
|
val label = PackageHelper.loadAppLabel(it)
|
||||||
|
return@filter label.lowercase().contains(constraintLowered)
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
return@filter false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FilterResults().also { it.values = filteredList }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST", "NotifyDataSetChanged")
|
||||||
|
override fun publishResults(constraint: CharSequence, results: FilterResults) {
|
||||||
|
val values = results.values
|
||||||
|
if (values != null) {
|
||||||
|
filteredList = values as List<String>
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val mFilter = PresetFilter()
|
||||||
|
|
||||||
|
override fun getFilter(): Filter = mFilter
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
package org.frknkrc44.hma_oss.ui.adapter
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import icu.nullptr.hidemyapplist.common.AppPresets
|
||||||
|
import icu.nullptr.hidemyapplist.service.ConfigManager
|
||||||
|
import icu.nullptr.hidemyapplist.ui.view.ListItemView
|
||||||
|
import org.frknkrc44.hma_oss.BuildConfig
|
||||||
|
import org.frknkrc44.hma_oss.R
|
||||||
|
|
||||||
|
class AppPresetListAdapter(
|
||||||
|
context: Context,
|
||||||
|
private val onClickListener: ((ConfigManager.PresetInfo) -> Unit)?
|
||||||
|
) : RecyclerView.Adapter<AppPresetListAdapter.ViewHolder>() {
|
||||||
|
|
||||||
|
private lateinit var list: List<ConfigManager.PresetInfo>
|
||||||
|
|
||||||
|
init {
|
||||||
|
updateList(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class ViewHolder(view: ListItemView) : RecyclerView.ViewHolder(view) {
|
||||||
|
init {
|
||||||
|
view.setOnClickListener {
|
||||||
|
onClickListener?.invoke(list[absoluteAdapterPosition])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bind(presetName: String) {
|
||||||
|
with(itemView as ListItemView) {
|
||||||
|
setIcon(R.drawable.baseline_assignment_24)
|
||||||
|
text = presetName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
val view = ListItemView(parent.context)
|
||||||
|
view.layoutParams = ViewGroup.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
)
|
||||||
|
return ViewHolder(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount() = list.size
|
||||||
|
|
||||||
|
override fun getItemId(position: Int) = list[position].name.hashCode().toLong()
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(list[position].translation)
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged", "DiscouragedApi")
|
||||||
|
private fun updateList(context: Context) {
|
||||||
|
val presetNames = AppPresets.instance.getAllPresetNames()
|
||||||
|
val presetTranslations = presetNames.map { name ->
|
||||||
|
try {
|
||||||
|
val id = context.resources.getIdentifier(
|
||||||
|
"preset_${name}",
|
||||||
|
"string",
|
||||||
|
BuildConfig.APPLICATION_ID
|
||||||
|
)
|
||||||
|
|
||||||
|
return@map if (id != 0) { context.resources.getString(id) } else { name }
|
||||||
|
} catch (_: Throwable) {}
|
||||||
|
|
||||||
|
name
|
||||||
|
}
|
||||||
|
|
||||||
|
list = presetNames
|
||||||
|
.map { ConfigManager.PresetInfo(it, presetTranslations[presetNames.indexOf(it)]) }
|
||||||
|
.sortedWith { a, b -> a.translation.lowercase().compareTo(b.translation.lowercase()) }
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
package org.frknkrc44.hma_oss.ui.fragment
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.navigation.fragment.navArgs
|
||||||
|
import icu.nullptr.hidemyapplist.hmaApp
|
||||||
|
import icu.nullptr.hidemyapplist.service.PrefManager
|
||||||
|
import icu.nullptr.hidemyapplist.ui.fragment.AppSelectFragment
|
||||||
|
import icu.nullptr.hidemyapplist.util.PackageHelper
|
||||||
|
import icu.nullptr.hidemyapplist.util.PackageHelper.Comparators
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.frknkrc44.hma_oss.ui.adapter.AppPresetAdapter
|
||||||
|
|
||||||
|
class AppPresetFragment() : AppSelectFragment() {
|
||||||
|
|
||||||
|
override val firstComparator: Comparator<String> = Comparator.comparing(PackageHelper::exists).reversed()
|
||||||
|
|
||||||
|
override val adapter by lazy {
|
||||||
|
val args by navArgs<AppPresetFragmentArgs>()
|
||||||
|
AppPresetAdapter(args.presetName)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getFragmentTitle(): String {
|
||||||
|
val args by navArgs<AppPresetFragmentArgs>()
|
||||||
|
return args.presetTitle
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun sortList() {
|
||||||
|
hmaApp.globalScope.launch {
|
||||||
|
sortPresetList()
|
||||||
|
|
||||||
|
lifecycleScope.launch {
|
||||||
|
applyFilter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sortPresetList() {
|
||||||
|
var comparator = when (PrefManager.appFilter_sortMethod) {
|
||||||
|
PrefManager.SortMethod.BY_LABEL -> Comparators.byLabel
|
||||||
|
PrefManager.SortMethod.BY_PACKAGE_NAME -> Comparators.byPackageName
|
||||||
|
PrefManager.SortMethod.BY_INSTALL_TIME -> Comparators.byInstallTime
|
||||||
|
PrefManager.SortMethod.BY_UPDATE_TIME -> Comparators.byUpdateTime
|
||||||
|
}
|
||||||
|
if (PrefManager.appFilter_reverseOrder) comparator = comparator.reversed()
|
||||||
|
|
||||||
|
val packages = adapter.packages.sortedWith(firstComparator.then(comparator))
|
||||||
|
|
||||||
|
lifecycleScope.launch {
|
||||||
|
adapter.packages.clear()
|
||||||
|
adapter.packages += packages
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun invalidateCache() {
|
||||||
|
super.invalidateCache()
|
||||||
|
adapter.updateList()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
lifecycleScope.launch {
|
||||||
|
binding.swipeRefresh.isRefreshing = true
|
||||||
|
adapter.updateList()
|
||||||
|
sortList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -116,7 +116,6 @@ class HomeFragment : Fragment(R.layout.fragment_home) {
|
||||||
|
|
||||||
val serviceVersion = ServiceClient.serviceVersion
|
val serviceVersion = ServiceClient.serviceVersion
|
||||||
val color = when {
|
val color = when {
|
||||||
!hmaApp.isHooked -> getColor(R.color.gray)
|
|
||||||
serviceVersion == 0 -> getColor(R.color.invalid)
|
serviceVersion == 0 -> getColor(R.color.invalid)
|
||||||
else -> themeColor(android.R.attr.colorPrimary)
|
else -> themeColor(android.R.attr.colorPrimary)
|
||||||
}
|
}
|
||||||
|
|
@ -126,7 +125,7 @@ class HomeFragment : Fragment(R.layout.fragment_home) {
|
||||||
root.outlineAmbientShadowColor = color
|
root.outlineAmbientShadowColor = color
|
||||||
root.outlineSpotShadowColor = color
|
root.outlineSpotShadowColor = color
|
||||||
|
|
||||||
if (hmaApp.isHooked) {
|
if (serviceVersion > 0) {
|
||||||
moduleStatusIcon.setImageResource(R.drawable.sentiment_calm_24px)
|
moduleStatusIcon.setImageResource(R.drawable.sentiment_calm_24px)
|
||||||
val versionNameSimple = BuildConfig.VERSION_NAME.substringBefore(".r")
|
val versionNameSimple = BuildConfig.VERSION_NAME.substringBefore(".r")
|
||||||
moduleStatus.text =
|
moduleStatus.text =
|
||||||
|
|
@ -268,6 +267,14 @@ class HomeFragment : Fragment(R.layout.fragment_home) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
with(binding.managePresets) {
|
||||||
|
text1.text = getString(R.string.title_preset_manage)
|
||||||
|
icon.setImageResource(R.drawable.baseline_my_location_24)
|
||||||
|
root.setOnClickListener {
|
||||||
|
navigate(R.id.nav_presets)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
with(binding.navLogs) {
|
with(binding.navLogs) {
|
||||||
text1.text = getString(R.string.title_logs)
|
text1.text = getString(R.string.title_logs)
|
||||||
icon.setImageResource(R.drawable.outline_assignment_24)
|
icon.setImageResource(R.drawable.outline_assignment_24)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
package org.frknkrc44.hma_oss.ui.fragment
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import android.view.WindowInsets
|
||||||
|
import androidx.core.view.doOnPreDraw
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||||
|
import icu.nullptr.hidemyapplist.service.ConfigManager
|
||||||
|
import icu.nullptr.hidemyapplist.ui.util.navController
|
||||||
|
import icu.nullptr.hidemyapplist.ui.util.setupToolbar
|
||||||
|
import org.frknkrc44.hma_oss.R
|
||||||
|
import org.frknkrc44.hma_oss.databinding.FragmentPresetManageBinding
|
||||||
|
import org.frknkrc44.hma_oss.ui.adapter.AppPresetListAdapter
|
||||||
|
|
||||||
|
class PresetManageFragment : Fragment(R.layout.fragment_preset_manage) {
|
||||||
|
|
||||||
|
private val binding by viewBinding<FragmentPresetManageBinding>()
|
||||||
|
private val adapter by lazy {
|
||||||
|
AppPresetListAdapter(requireContext(), this::navigateToPreset)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
setupToolbar(
|
||||||
|
toolbar = binding.toolbar,
|
||||||
|
title = getString(R.string.title_preset_manage),
|
||||||
|
navigationIcon = R.drawable.baseline_arrow_back_24,
|
||||||
|
navigationOnClick = { navController.navigateUp() }
|
||||||
|
)
|
||||||
|
postponeEnterTransition()
|
||||||
|
view.doOnPreDraw { startPostponedEnterTransition() }
|
||||||
|
|
||||||
|
binding.presetList.layoutManager = LinearLayoutManager(context)
|
||||||
|
binding.presetList.adapter = adapter
|
||||||
|
|
||||||
|
binding.root.setOnApplyWindowInsetsListener { v, insets ->
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
|
val barInsets = insets.getInsets(WindowInsets.Type.systemBars())
|
||||||
|
binding.root.setPadding(
|
||||||
|
barInsets.left,
|
||||||
|
barInsets.top,
|
||||||
|
barInsets.right,
|
||||||
|
barInsets.bottom,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
@Suppress("deprecation")
|
||||||
|
binding.root.setPadding(
|
||||||
|
insets.systemWindowInsetLeft,
|
||||||
|
insets.systemWindowInsetTop,
|
||||||
|
insets.systemWindowInsetRight,
|
||||||
|
insets.systemWindowInsetBottom,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
insets
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun navigateToPreset(presetInfo: ConfigManager.PresetInfo) {
|
||||||
|
val args = AppPresetFragmentArgs(presetInfo.name, presetInfo.translation)
|
||||||
|
navController.navigate(R.id.nav_preset_inner_manage, args.toBundle())
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue