Add old app/template management screens for now
This commit is contained in:
parent
14715790e0
commit
2621d656d9
27 changed files with 1233 additions and 87 deletions
|
|
@ -0,0 +1,34 @@
|
|||
package icu.nullptr.hidemyapplist.ui.adapter
|
||||
|
||||
import android.view.ViewGroup
|
||||
import icu.nullptr.hidemyapplist.service.ConfigManager
|
||||
import icu.nullptr.hidemyapplist.ui.view.AppItemView
|
||||
|
||||
class AppManageAdapter(
|
||||
private val onItemClickListener: (String) -> Unit
|
||||
) : AppSelectAdapter() {
|
||||
|
||||
inner class ViewHolder(view: AppItemView) : AppSelectAdapter.ViewHolder(view) {
|
||||
init {
|
||||
view.setOnClickListener {
|
||||
onItemClickListener.invoke(filteredList[absoluteAdapterPosition])
|
||||
}
|
||||
}
|
||||
|
||||
override fun bind(packageName: String) {
|
||||
(itemView as AppItemView).let {
|
||||
it.load(packageName)
|
||||
it.showEnabled = ConfigManager.isHideEnabled(packageName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package icu.nullptr.hidemyapplist.ui.adapter
|
||||
|
||||
import android.view.ViewGroup
|
||||
import icu.nullptr.hidemyapplist.ui.view.AppItemView
|
||||
|
||||
class AppScopeAdapter(
|
||||
private val checked: MutableSet<String>,
|
||||
firstFilter: ((String) -> Boolean)?,
|
||||
) : AppSelectAdapter(firstFilter) {
|
||||
|
||||
private inline var String.isChecked
|
||||
get() = checked.contains(this)
|
||||
set(value) {
|
||||
if (value) checked.add(this) else checked.remove(this)
|
||||
}
|
||||
|
||||
inner class ViewHolder(view: AppItemView) : AppSelectAdapter.ViewHolder(view) {
|
||||
init {
|
||||
view.setOnClickListener {
|
||||
val packageName = filteredList[absoluteAdapterPosition]
|
||||
packageName.isChecked = !packageName.isChecked
|
||||
view.isChecked = packageName.isChecked
|
||||
}
|
||||
}
|
||||
|
||||
override fun bind(packageName: String) {
|
||||
(itemView as AppItemView).let {
|
||||
it.load(packageName)
|
||||
it.isChecked = packageName.isChecked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val view = AppItemView(parent.context, true)
|
||||
view.layoutParams = ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
return ViewHolder(view)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package icu.nullptr.hidemyapplist.ui.adapter
|
||||
|
||||
import android.widget.Filter
|
||||
import android.widget.Filterable
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import icu.nullptr.hidemyapplist.service.PrefManager
|
||||
import icu.nullptr.hidemyapplist.ui.view.AppItemView
|
||||
import icu.nullptr.hidemyapplist.util.PackageHelper
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
abstract class AppSelectAdapter(
|
||||
private val firstFilter: ((String) -> Boolean)? = null
|
||||
) : RecyclerView.Adapter<AppSelectAdapter.ViewHolder>(), Filterable {
|
||||
|
||||
abstract class ViewHolder(view: AppItemView) : RecyclerView.ViewHolder(view) {
|
||||
abstract fun bind(packageName: String)
|
||||
}
|
||||
|
||||
private inner class AppFilter : Filter() {
|
||||
override fun performFiltering(constraint: CharSequence): FilterResults {
|
||||
return runBlocking {
|
||||
val constraintLowered = constraint.toString().lowercase()
|
||||
val filteredList = PackageHelper.appList.first().filter {
|
||||
if (firstFilter?.invoke(it) == false) return@filter false
|
||||
if (!PrefManager.appFilter_showSystem && PackageHelper.isSystem(it)) return@filter false
|
||||
val label = PackageHelper.loadAppLabel(it)
|
||||
val packageInfo = PackageHelper.loadPackageInfo(it)
|
||||
label.lowercase().contains(constraintLowered) || packageInfo.packageName.lowercase().contains(constraintLowered)
|
||||
}
|
||||
|
||||
FilterResults().also { it.values = filteredList }
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST", "NotifyDataSetChanged")
|
||||
override fun publishResults(constraint: CharSequence, results: FilterResults) {
|
||||
filteredList = results.values as List<String>
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
private val mFilter = AppFilter()
|
||||
|
||||
protected var filteredList: List<String> = listOf()
|
||||
|
||||
override fun getItemCount() = filteredList.size
|
||||
|
||||
override fun getItemId(position: Int) = filteredList[position].hashCode().toLong()
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(filteredList[position])
|
||||
|
||||
override fun getFilter(): Filter = mFilter
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
package icu.nullptr.hidemyapplist.ui.adapter
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import icu.nullptr.hidemyapplist.service.ConfigManager
|
||||
import icu.nullptr.hidemyapplist.ui.view.ListItemView
|
||||
import org.frknkrc44.hma_oss.R
|
||||
import java.text.Collator
|
||||
import java.util.Locale
|
||||
|
||||
class TemplateAdapter(
|
||||
private val onClickListener: ((ConfigManager.TemplateInfo) -> Unit)?
|
||||
) : RecyclerView.Adapter<TemplateAdapter.ViewHolder>() {
|
||||
|
||||
private lateinit var list: List<ConfigManager.TemplateInfo>
|
||||
|
||||
init {
|
||||
updateList()
|
||||
}
|
||||
|
||||
inner class ViewHolder(view: ListItemView) : RecyclerView.ViewHolder(view) {
|
||||
init {
|
||||
view.setOnClickListener {
|
||||
onClickListener?.invoke(list[absoluteAdapterPosition])
|
||||
}
|
||||
}
|
||||
|
||||
fun bind(info: ConfigManager.TemplateInfo) {
|
||||
with(itemView as ListItemView) {
|
||||
setIcon(
|
||||
if (info.isWhiteList) R.drawable.outline_assignment_24
|
||||
else R.drawable.baseline_assignment_24
|
||||
)
|
||||
text = info.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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])
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
fun updateList() {
|
||||
list = ConfigManager.getTemplateList().apply {
|
||||
sortWith { o1, o2 ->
|
||||
if (o1.isWhiteList != o2.isWhiteList) {
|
||||
o1.isWhiteList.compareTo(o2.isWhiteList)
|
||||
} else {
|
||||
Collator.getInstance(Locale.getDefault()).compare(o1.name, o2.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package icu.nullptr.hidemyapplist.ui.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import com.google.android.material.transition.MaterialSharedAxis
|
||||
import icu.nullptr.hidemyapplist.service.ConfigManager
|
||||
import icu.nullptr.hidemyapplist.ui.adapter.AppManageAdapter
|
||||
import icu.nullptr.hidemyapplist.ui.util.navController
|
||||
import org.frknkrc44.hma_oss.R
|
||||
|
||||
class AppManageFragment : AppSelectFragment() {
|
||||
|
||||
override val firstComparator: Comparator<String> = Comparator.comparing(ConfigManager::isHideEnabled).reversed()
|
||||
|
||||
override val adapter = AppManageAdapter {
|
||||
val args = AppSettingsFragmentArgs(it)
|
||||
navController.navigate(R.id.nav_app_settings, args.toBundle())
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
// enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
|
||||
// returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
package icu.nullptr.hidemyapplist.ui.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.activity.addCallback
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.flowWithLifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import icu.nullptr.hidemyapplist.service.PrefManager
|
||||
import icu.nullptr.hidemyapplist.ui.adapter.AppSelectAdapter
|
||||
import icu.nullptr.hidemyapplist.ui.util.navController
|
||||
import icu.nullptr.hidemyapplist.ui.util.setupToolbar
|
||||
import icu.nullptr.hidemyapplist.util.PackageHelper
|
||||
import kotlinx.coroutines.launch
|
||||
import org.frknkrc44.hma_oss.R
|
||||
import org.frknkrc44.hma_oss.databinding.FragmentAppSelectBinding
|
||||
|
||||
abstract class AppSelectFragment : Fragment(R.layout.fragment_app_select) {
|
||||
|
||||
private val binding by viewBinding<FragmentAppSelectBinding>()
|
||||
|
||||
protected abstract val firstComparator: Comparator<String>
|
||||
protected abstract val adapter: AppSelectAdapter
|
||||
|
||||
private var search = ""
|
||||
|
||||
protected open fun onBack() {
|
||||
navController.navigateUp()
|
||||
}
|
||||
|
||||
private fun applyFilter() {
|
||||
adapter.filter.filter(search)
|
||||
}
|
||||
|
||||
private fun sortList() {
|
||||
lifecycleScope.launch {
|
||||
PackageHelper.sortList(firstComparator)
|
||||
applyFilter()
|
||||
}
|
||||
}
|
||||
|
||||
private fun onMenuOptionSelected(item: MenuItem) {
|
||||
when (item.itemId) {
|
||||
R.id.menu_show_system -> {
|
||||
item.isChecked = !item.isChecked
|
||||
PrefManager.appFilter_showSystem = item.isChecked
|
||||
}
|
||||
R.id.menu_sort_by_label -> {
|
||||
item.isChecked = true
|
||||
PrefManager.appFilter_sortMethod = PrefManager.SortMethod.BY_LABEL
|
||||
}
|
||||
R.id.menu_sort_by_package_name -> {
|
||||
item.isChecked = true
|
||||
PrefManager.appFilter_sortMethod = PrefManager.SortMethod.BY_PACKAGE_NAME
|
||||
}
|
||||
R.id.menu_sort_by_install_time -> {
|
||||
item.isChecked = true
|
||||
PrefManager.appFilter_sortMethod = PrefManager.SortMethod.BY_INSTALL_TIME
|
||||
}
|
||||
R.id.menu_sort_by_update_time -> {
|
||||
item.isChecked = true
|
||||
PrefManager.appFilter_sortMethod = PrefManager.SortMethod.BY_UPDATE_TIME
|
||||
}
|
||||
R.id.menu_reverse_order -> {
|
||||
item.isChecked = !item.isChecked
|
||||
PrefManager.appFilter_reverseOrder = item.isChecked
|
||||
}
|
||||
}
|
||||
sortList()
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { onBack() }
|
||||
setupToolbar(
|
||||
toolbar = binding.toolbar,
|
||||
title = getString(R.string.title_app_select),
|
||||
navigationIcon = R.drawable.baseline_arrow_back_24,
|
||||
navigationOnClick = { onBack() },
|
||||
menuRes = R.menu.menu_app_list,
|
||||
onMenuOptionSelected = this::onMenuOptionSelected
|
||||
)
|
||||
|
||||
with(binding.toolbar.menu) {
|
||||
val searchView = findItem(R.id.menu_search).actionView as SearchView
|
||||
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||
override fun onQueryTextSubmit(query: String) = false
|
||||
|
||||
override fun onQueryTextChange(newText: String): Boolean {
|
||||
search = newText
|
||||
applyFilter()
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
findItem(R.id.menu_show_system).isChecked = PrefManager.appFilter_showSystem
|
||||
when (PrefManager.appFilter_sortMethod) {
|
||||
PrefManager.SortMethod.BY_LABEL -> findItem(R.id.menu_sort_by_label).isChecked = true
|
||||
PrefManager.SortMethod.BY_PACKAGE_NAME -> findItem(R.id.menu_sort_by_package_name).isChecked = true
|
||||
PrefManager.SortMethod.BY_INSTALL_TIME -> findItem(R.id.menu_sort_by_install_time).isChecked = true
|
||||
PrefManager.SortMethod.BY_UPDATE_TIME -> findItem(R.id.menu_sort_by_update_time).isChecked = true
|
||||
}
|
||||
findItem(R.id.menu_reverse_order).isChecked = PrefManager.appFilter_reverseOrder
|
||||
}
|
||||
binding.list.layoutManager = LinearLayoutManager(context)
|
||||
binding.list.adapter = adapter
|
||||
binding.swipeRefresh.setOnRefreshListener {
|
||||
PackageHelper.invalidateCache()
|
||||
}
|
||||
|
||||
lifecycleScope.launch {
|
||||
PackageHelper.isRefreshing
|
||||
.flowWithLifecycle(lifecycle)
|
||||
.collect {
|
||||
binding.swipeRefresh.isRefreshing = it
|
||||
}
|
||||
}
|
||||
|
||||
sortList()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,210 @@
|
|||
package icu.nullptr.hidemyapplist.ui.fragment
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.activity.addCallback
|
||||
import androidx.core.graphics.drawable.toDrawable
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.clearFragmentResultListener
|
||||
import androidx.fragment.app.setFragmentResultListener
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceDataStore
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.SwitchPreference
|
||||
import androidx.preference.SwitchPreferenceCompat
|
||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import icu.nullptr.hidemyapplist.common.JsonConfig
|
||||
import icu.nullptr.hidemyapplist.common.Presets
|
||||
import icu.nullptr.hidemyapplist.service.ConfigManager
|
||||
import icu.nullptr.hidemyapplist.ui.util.navController
|
||||
import icu.nullptr.hidemyapplist.ui.util.setupToolbar
|
||||
import icu.nullptr.hidemyapplist.ui.viewmodel.AppSettingsViewModel
|
||||
import icu.nullptr.hidemyapplist.util.PackageHelper
|
||||
import org.frknkrc44.hma_oss.BuildConfig
|
||||
import org.frknkrc44.hma_oss.R
|
||||
import org.frknkrc44.hma_oss.databinding.FragmentSettingsBinding
|
||||
|
||||
class AppSettingsFragment : Fragment(R.layout.fragment_settings) {
|
||||
|
||||
private val binding by viewBinding<FragmentSettingsBinding>()
|
||||
private val viewModel by viewModels<AppSettingsViewModel>() {
|
||||
val args by navArgs<AppSettingsFragmentArgs>()
|
||||
val cfg = ConfigManager.getAppConfig(args.packageName)
|
||||
val pack = if (cfg != null) AppSettingsViewModel.Pack(args.packageName, true, cfg)
|
||||
else AppSettingsViewModel.Pack(args.packageName, false, JsonConfig.AppConfig())
|
||||
AppSettingsViewModel.Factory(pack)
|
||||
}
|
||||
|
||||
private fun saveConfig() {
|
||||
if (!viewModel.pack.enabled) ConfigManager.setAppConfig(viewModel.pack.app, null)
|
||||
else ConfigManager.setAppConfig(viewModel.pack.app, viewModel.pack.config)
|
||||
}
|
||||
|
||||
private fun onBack() {
|
||||
saveConfig()
|
||||
navController.navigateUp()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
saveConfig()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
saveConfig()
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { onBack() }
|
||||
setupToolbar(
|
||||
toolbar = binding.toolbar,
|
||||
title = getString(R.string.title_app_settings),
|
||||
navigationIcon = R.drawable.baseline_arrow_back_24,
|
||||
navigationOnClick = { onBack() }
|
||||
)
|
||||
|
||||
if (childFragmentManager.findFragmentById(R.id.settings_container) == null) {
|
||||
childFragmentManager.beginTransaction()
|
||||
.replace(R.id.settings_container, AppPreferenceFragment())
|
||||
.commit()
|
||||
}
|
||||
}
|
||||
|
||||
class AppPreferenceDataStore(private val pack: AppSettingsViewModel.Pack) : PreferenceDataStore() {
|
||||
|
||||
override fun getBoolean(key: String, defValue: Boolean): Boolean {
|
||||
return when (key) {
|
||||
"enableHide" -> pack.enabled
|
||||
"useWhiteList" -> pack.config.useWhitelist
|
||||
"excludeSystemApps" -> pack.config.excludeSystemApps
|
||||
else -> throw IllegalArgumentException("Invalid key: $key")
|
||||
}
|
||||
}
|
||||
|
||||
override fun putBoolean(key: String, value: Boolean) {
|
||||
when (key) {
|
||||
"enableHide" -> pack.enabled = value
|
||||
"useWhiteList" -> pack.config.useWhitelist = value
|
||||
"excludeSystemApps" -> pack.config.excludeSystemApps = value
|
||||
else -> throw IllegalArgumentException("Invalid key: $key")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AppPreferenceFragment : PreferenceFragmentCompat() {
|
||||
|
||||
private val parent get() = requireParentFragment() as AppSettingsFragment
|
||||
private val pack get() = parent.viewModel.pack
|
||||
|
||||
private fun updateApplyTemplates() {
|
||||
findPreference<Preference>("applyTemplates")?.title =
|
||||
getString(R.string.app_template_using, pack.config.applyTemplates.size)
|
||||
}
|
||||
|
||||
private fun updateApplyPresets() {
|
||||
findPreference<Preference>("applyPresets")?.title =
|
||||
getString(R.string.app_preset_using, pack.config.applyPresets.size)
|
||||
}
|
||||
|
||||
private fun updateExtraAppList(useWhiteList: Boolean) {
|
||||
findPreference<Preference>("extraAppList")?.title =
|
||||
if (useWhiteList) getString(R.string.app_extra_apps_visible_count, pack.config.extraAppList.size)
|
||||
else getString(R.string.app_extra_apps_invisible_count, pack.config.extraAppList.size)
|
||||
}
|
||||
|
||||
@SuppressLint("DiscouragedApi")
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
preferenceManager.preferenceDataStore = AppPreferenceDataStore(pack)
|
||||
setPreferencesFromResource(R.xml.app_settings, rootKey)
|
||||
findPreference<Preference>("appInfo")?.let {
|
||||
it.icon = PackageHelper.loadAppIcon(pack.app).toDrawable(resources)
|
||||
it.title = PackageHelper.loadAppLabel(pack.app)
|
||||
it.summary = PackageHelper.loadPackageInfo(pack.app).packageName
|
||||
}
|
||||
findPreference<SwitchPreferenceCompat>("useWhiteList")?.setOnPreferenceChangeListener { _, newValue ->
|
||||
pack.config.applyTemplates.clear()
|
||||
pack.config.extraAppList.clear()
|
||||
updateApplyTemplates()
|
||||
updateApplyPresets()
|
||||
updateExtraAppList(newValue as Boolean)
|
||||
true
|
||||
}
|
||||
findPreference<Preference>("applyTemplates")?.setOnPreferenceClickListener {
|
||||
val templates = ConfigManager.getTemplateList().mapNotNull {
|
||||
if (it.isWhiteList == pack.config.useWhitelist) it.name else null
|
||||
}.toTypedArray()
|
||||
val checked = templates.map {
|
||||
pack.config.applyTemplates.contains(it)
|
||||
}.toBooleanArray()
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.app_choose_template)
|
||||
.setMultiChoiceItems(templates, checked) { _, i, value -> checked[i] = value }
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
pack.config.applyTemplates = templates.mapIndexedNotNullTo(mutableSetOf()) { i, name ->
|
||||
if (checked[i]) name else null
|
||||
}
|
||||
updateApplyTemplates()
|
||||
}
|
||||
.show()
|
||||
true
|
||||
}
|
||||
findPreference<Preference>("applyPresets")?.setOnPreferenceClickListener {
|
||||
val presetNames = Presets.instance.getAllPresetNames()
|
||||
val presetTranslations = presetNames.map { name ->
|
||||
try {
|
||||
val id = resources.getIdentifier(
|
||||
"preset_${name}",
|
||||
"string",
|
||||
BuildConfig.APPLICATION_ID
|
||||
)
|
||||
|
||||
return@map if (id != 0) { getString(id) } else { name }
|
||||
} catch (ignore: Throwable) {}
|
||||
|
||||
name
|
||||
}
|
||||
|
||||
val presets = presetNames.zip(presetTranslations).toMap().toSortedMap()
|
||||
val checked = presets.keys.map {
|
||||
pack.config.applyPresets.contains(it)
|
||||
}.toBooleanArray()
|
||||
val presetValues = presets.values.toTypedArray()
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.app_choose_preset)
|
||||
.setMultiChoiceItems(presetValues, checked) { _, i, value -> checked[i] = value }
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
pack.config.applyPresets = presetValues.mapIndexedNotNullTo(mutableSetOf()) { i, name ->
|
||||
if (checked[i]) presets.filterValues { v -> v == name }.keys.first() else null
|
||||
}
|
||||
updateApplyPresets()
|
||||
}
|
||||
.show()
|
||||
true
|
||||
}
|
||||
findPreference<Preference>("extraAppList")?.setOnPreferenceClickListener {
|
||||
parent.setFragmentResultListener("app_select") { _, bundle ->
|
||||
pack.config.extraAppList = bundle.getStringArrayList("checked")!!.toMutableSet()
|
||||
updateExtraAppList(pack.config.useWhitelist)
|
||||
parent.clearFragmentResultListener("app_select")
|
||||
}
|
||||
|
||||
val args = ScopeFragmentArgs(
|
||||
filterOnlyEnabled = false,
|
||||
checked = pack.config.extraAppList.toTypedArray()
|
||||
)
|
||||
parent.navController.navigate(R.id.nav_scope, args.toBundle())
|
||||
true
|
||||
}
|
||||
updateApplyTemplates()
|
||||
updateApplyPresets()
|
||||
updateExtraAppList(pack.config.useWhitelist)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package icu.nullptr.hidemyapplist.ui.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.setFragmentResult
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import icu.nullptr.hidemyapplist.service.ConfigManager
|
||||
import icu.nullptr.hidemyapplist.ui.adapter.AppScopeAdapter
|
||||
import icu.nullptr.hidemyapplist.ui.util.navController
|
||||
|
||||
class ScopeFragment : AppSelectFragment() {
|
||||
|
||||
private lateinit var checked: MutableSet<String>
|
||||
|
||||
override val firstComparator: Comparator<String> = Comparator.comparing { !checked.contains(it) }
|
||||
|
||||
override val adapter by lazy {
|
||||
val args by navArgs<ScopeFragmentArgs>()
|
||||
checked = args.checked.toMutableSet()
|
||||
if (!args.filterOnlyEnabled) AppScopeAdapter(checked, null)
|
||||
else AppScopeAdapter(checked) { ConfigManager.getAppConfig(it)?.useWhitelist == args.isWhiteList }
|
||||
}
|
||||
|
||||
override fun onBack() {
|
||||
setFragmentResult("app_select", Bundle().apply {
|
||||
putStringArrayList("checked", ArrayList(checked))
|
||||
})
|
||||
navController.navigateUp()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
package icu.nullptr.hidemyapplist.ui.fragment
|
||||
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.core.view.doOnPreDraw
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.clearFragmentResultListener
|
||||
import androidx.fragment.app.setFragmentResultListener
|
||||
import androidx.navigation.fragment.FragmentNavigatorExtras
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import com.google.android.material.transition.MaterialContainerTransform
|
||||
import icu.nullptr.hidemyapplist.common.JsonConfig
|
||||
import icu.nullptr.hidemyapplist.service.ConfigManager
|
||||
import icu.nullptr.hidemyapplist.ui.adapter.TemplateAdapter
|
||||
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.FragmentTemplateManageBinding
|
||||
|
||||
class TemplateManageFragment : Fragment(R.layout.fragment_template_manage) {
|
||||
|
||||
private val binding by viewBinding<FragmentTemplateManageBinding>()
|
||||
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?) {
|
||||
setupToolbar(
|
||||
toolbar = binding.toolbar,
|
||||
title = getString(R.string.title_template_manage),
|
||||
navigationIcon = R.drawable.baseline_arrow_back_24,
|
||||
navigationOnClick = { navController.navigateUp() }
|
||||
)
|
||||
postponeEnterTransition()
|
||||
view.doOnPreDraw { startPostponedEnterTransition() }
|
||||
|
||||
binding.newBlacklistTemplate.setOnClickListener {
|
||||
navigateToSettings(ConfigManager.TemplateInfo(null, false))
|
||||
}
|
||||
binding.newWhitelistTemplate.setOnClickListener {
|
||||
navigateToSettings(ConfigManager.TemplateInfo(null, true))
|
||||
}
|
||||
binding.templateList.layoutManager = LinearLayoutManager(context)
|
||||
binding.templateList.adapter = adapter
|
||||
}
|
||||
|
||||
private fun navigateToSettings(info: ConfigManager.TemplateInfo) {
|
||||
setFragmentResultListener("template_settings") { _, bundle ->
|
||||
fun deal() {
|
||||
var name = bundle.getString("name")
|
||||
val appliedList = bundle.getStringArrayList("appliedList")!!
|
||||
val targetList = bundle.getStringArrayList("targetList")!!
|
||||
if (info.name == null) { // New template
|
||||
if (name.isNullOrEmpty()) return
|
||||
ConfigManager.updateTemplate(name, JsonConfig.Template(info.isWhiteList, targetList.toSet()))
|
||||
ConfigManager.updateTemplateAppliedApps(name, appliedList)
|
||||
} else { // Existing template
|
||||
if (name == null) {
|
||||
ConfigManager.deleteTemplate(info.name)
|
||||
} else {
|
||||
if (name.isEmpty()) name = info.name
|
||||
if (name != info.name) ConfigManager.renameTemplate(info.name, name)
|
||||
ConfigManager.updateTemplate(name, JsonConfig.Template(info.isWhiteList, targetList.toSet()))
|
||||
ConfigManager.updateTemplateAppliedApps(name, appliedList)
|
||||
}
|
||||
}
|
||||
}
|
||||
deal()
|
||||
adapter.updateList()
|
||||
clearFragmentResultListener("template_settings")
|
||||
}
|
||||
|
||||
val args = TemplateSettingsFragmentArgs(info.name, info.isWhiteList)
|
||||
val extras = FragmentNavigatorExtras(binding.hintCard to "transition_manage")
|
||||
navController.navigate(R.id.nav_template_settings, args.toBundle(), null, extras)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
package icu.nullptr.hidemyapplist.ui.fragment
|
||||
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.activity.addCallback
|
||||
import androidx.core.widget.addTextChangedListener
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.clearFragmentResultListener
|
||||
import androidx.fragment.app.setFragmentResult
|
||||
import androidx.fragment.app.setFragmentResultListener
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.transition.MaterialContainerTransform
|
||||
import icu.nullptr.hidemyapplist.service.ConfigManager
|
||||
import icu.nullptr.hidemyapplist.ui.util.navController
|
||||
import icu.nullptr.hidemyapplist.ui.util.setupToolbar
|
||||
import icu.nullptr.hidemyapplist.ui.viewmodel.TemplateSettingsViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import org.frknkrc44.hma_oss.R
|
||||
import org.frknkrc44.hma_oss.databinding.FragmentTemplateSettingsBinding
|
||||
|
||||
class TemplateSettingsFragment : Fragment(R.layout.fragment_template_settings) {
|
||||
|
||||
private val binding by viewBinding<FragmentTemplateSettingsBinding>()
|
||||
private val viewModel by viewModels<TemplateSettingsViewModel> {
|
||||
val args by navArgs<TemplateSettingsFragmentArgs>()
|
||||
TemplateSettingsViewModel.Factory(args)
|
||||
}
|
||||
|
||||
private fun onBack(delete: Boolean) {
|
||||
viewModel.name = viewModel.name?.trim()
|
||||
if (viewModel.name != viewModel.originalName && (ConfigManager.hasTemplate(viewModel.name) || viewModel.name == null) || delete) {
|
||||
val builder = MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(if (delete) R.string.template_delete_title else R.string.template_name_invalid)
|
||||
.setMessage(if (delete) R.string.template_delete else R.string.template_name_already_exist)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
saveResult(delete)
|
||||
}
|
||||
if (delete) builder.setNegativeButton(android.R.string.cancel, null)
|
||||
builder.show()
|
||||
} else {
|
||||
saveResult(false)
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveResult(delete: Boolean) {
|
||||
setFragmentResult("template_settings", Bundle().apply {
|
||||
putString("name",if (delete) null else viewModel.name)
|
||||
putStringArrayList("appliedList", viewModel.appliedAppList.value)
|
||||
putStringArrayList("targetList", viewModel.targetAppList.value)
|
||||
})
|
||||
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?) {
|
||||
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { onBack(false) }
|
||||
setupToolbar(
|
||||
toolbar = binding.toolbar,
|
||||
title = getString(R.string.title_template_settings),
|
||||
navigationIcon = R.drawable.baseline_arrow_back_24,
|
||||
navigationOnClick = { onBack(false) },
|
||||
menuRes = R.menu.menu_delete,
|
||||
onMenuOptionSelected = {
|
||||
onBack(true)
|
||||
}
|
||||
)
|
||||
|
||||
binding.templateName.setText(viewModel.name)
|
||||
binding.templateName.addTextChangedListener { viewModel.name = it.toString() }
|
||||
binding.targetApps.setOnClickListener {
|
||||
setFragmentResultListener("app_select") { _, bundle ->
|
||||
viewModel.targetAppList.value = bundle.getStringArrayList("checked")!!
|
||||
clearFragmentResultListener("app_select")
|
||||
}
|
||||
val args = ScopeFragmentArgs(
|
||||
filterOnlyEnabled = false,
|
||||
checked = viewModel.targetAppList.value.toTypedArray()
|
||||
)
|
||||
navController.navigate(R.id.nav_scope, args.toBundle())
|
||||
}
|
||||
binding.appliedApps.setOnClickListener {
|
||||
setFragmentResultListener("app_select") { _, bundle ->
|
||||
viewModel.appliedAppList.value = bundle.getStringArrayList("checked")!!
|
||||
clearFragmentResultListener("app_select")
|
||||
}
|
||||
val args = ScopeFragmentArgs(
|
||||
filterOnlyEnabled = true,
|
||||
isWhiteList = viewModel.isWhiteList,
|
||||
checked = viewModel.appliedAppList.value.toTypedArray()
|
||||
)
|
||||
navController.navigate(R.id.nav_scope, args.toBundle())
|
||||
}
|
||||
|
||||
lifecycleScope.launch {
|
||||
viewModel.targetAppList.collect {
|
||||
val fmt =
|
||||
if (viewModel.isWhiteList) R.string.template_apps_visible_count
|
||||
else R.string.template_apps_invisible_count
|
||||
binding.targetApps.text = String.format(getString(fmt), it.size)
|
||||
}
|
||||
}
|
||||
lifecycleScope.launch {
|
||||
viewModel.appliedAppList.collect {
|
||||
binding.appliedApps.text = String.format(getString(R.string.template_applied_count), it.size)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package icu.nullptr.hidemyapplist.ui.view
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.widget.LinearLayout
|
||||
import by.kirich1409.viewbindingdelegate.CreateMethod
|
||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import icu.nullptr.hidemyapplist.util.PackageHelper
|
||||
import org.frknkrc44.hma_oss.databinding.AppItemViewBinding
|
||||
|
||||
class AppItemView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0,
|
||||
defStyleRes: Int = 0
|
||||
) : LinearLayout(context, attrs, defStyleAttr, defStyleRes) {
|
||||
|
||||
private val binding by viewBinding<AppItemViewBinding>(createMethod = CreateMethod.INFLATE)
|
||||
|
||||
var showEnabled: Boolean
|
||||
get() = binding.enabled.visibility == VISIBLE
|
||||
set(value) {
|
||||
binding.enabled.visibility = if (value) VISIBLE else GONE
|
||||
}
|
||||
|
||||
var isChecked: Boolean
|
||||
get() = binding.checkbox.isChecked
|
||||
set(value) {
|
||||
binding.checkbox.isChecked = value
|
||||
}
|
||||
|
||||
constructor(context: Context, isCheckable: Boolean) : this(context) {
|
||||
binding.checkbox.visibility = if (isCheckable) VISIBLE else GONE
|
||||
}
|
||||
|
||||
fun load(packageName: String) {
|
||||
binding.packageName.text = packageName
|
||||
binding.label.text = PackageHelper.loadAppLabel(packageName)
|
||||
binding.icon.setImageBitmap(PackageHelper.loadAppIcon(packageName))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package icu.nullptr.hidemyapplist.ui.view
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.widget.LinearLayout
|
||||
import androidx.annotation.DrawableRes
|
||||
import by.kirich1409.viewbindingdelegate.CreateMethod
|
||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import org.frknkrc44.hma_oss.R
|
||||
import org.frknkrc44.hma_oss.databinding.ListItemViewBinding
|
||||
|
||||
class ListItemView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0,
|
||||
defStyleRes: Int = 0
|
||||
) : LinearLayout(context, attrs, defStyleAttr, defStyleRes) {
|
||||
|
||||
private val binding by viewBinding<ListItemViewBinding>(createMethod = CreateMethod.INFLATE)
|
||||
|
||||
init {
|
||||
val typedArray = context.theme.obtainStyledAttributes(attrs, R.styleable.ListItemView, defStyleAttr, defStyleRes)
|
||||
val icon = typedArray.getResourceId(R.styleable.ListItemView_icon, 0)
|
||||
val text = typedArray.getString(R.styleable.ListItemView_text)
|
||||
val buttonText = typedArray.getText(R.styleable.ListItemView_buttonText)
|
||||
typedArray.recycle()
|
||||
binding.icon.setImageResource(icon)
|
||||
binding.text.text = text
|
||||
if (buttonText != null) {
|
||||
binding.button.visibility = VISIBLE
|
||||
binding.button.text = buttonText
|
||||
}
|
||||
}
|
||||
|
||||
var text: CharSequence?
|
||||
get() = binding.text.text
|
||||
set(value) {
|
||||
binding.text.text = value
|
||||
}
|
||||
|
||||
fun setIcon(@DrawableRes icon: Int) {
|
||||
binding.icon.setImageResource(icon)
|
||||
}
|
||||
|
||||
override fun setOnClickListener(l: OnClickListener?) {
|
||||
if (binding.button.visibility == VISIBLE) {
|
||||
binding.button.setOnClickListener(l)
|
||||
} else {
|
||||
super.setOnClickListener(l)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package icu.nullptr.hidemyapplist.ui.viewmodel
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import icu.nullptr.hidemyapplist.common.JsonConfig
|
||||
|
||||
class AppSettingsViewModel(val pack: Pack) : ViewModel() {
|
||||
|
||||
class Factory(private val pack: Pack) : ViewModelProvider.Factory {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
if (modelClass.isAssignableFrom(AppSettingsViewModel::class.java)) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return AppSettingsViewModel(pack) as T
|
||||
} else throw IllegalArgumentException("Unknown ViewModel class")
|
||||
}
|
||||
}
|
||||
|
||||
class Pack(
|
||||
val app: String,
|
||||
var enabled: Boolean,
|
||||
val config: JsonConfig.AppConfig
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package icu.nullptr.hidemyapplist.ui.viewmodel
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import icu.nullptr.hidemyapplist.service.ConfigManager
|
||||
import icu.nullptr.hidemyapplist.ui.fragment.TemplateSettingsFragmentArgs
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
class TemplateSettingsViewModel(
|
||||
val originalName: String?,
|
||||
val isWhiteList: Boolean,
|
||||
var name: String?
|
||||
) : ViewModel() {
|
||||
|
||||
class Factory(private val args: TemplateSettingsFragmentArgs) : ViewModelProvider.Factory {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
if (modelClass.isAssignableFrom(TemplateSettingsViewModel::class.java)) {
|
||||
val viewModel = TemplateSettingsViewModel(args.name, args.isWhiteList, args.name)
|
||||
args.name?.let {
|
||||
viewModel.appliedAppList.value = ConfigManager.getTemplateAppliedAppList(it)
|
||||
viewModel.targetAppList.value = ConfigManager.getTemplateTargetAppList(it)
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return viewModel as T
|
||||
} else throw IllegalArgumentException("Unknown ViewModel class")
|
||||
}
|
||||
}
|
||||
|
||||
val appliedAppList = MutableStateFlow<ArrayList<String>>(ArrayList())
|
||||
val targetAppList = MutableStateFlow<ArrayList<String>>(ArrayList())
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
package org.frknkrc44.hma_oss.ui.adapter
|
||||
|
||||
class AppListAdapter {
|
||||
}
|
||||
|
|
@ -87,7 +87,7 @@ class HomeFragment : Fragment(R.layout.fragment_home) {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressLint("StringFormatInvalid")
|
||||
@SuppressLint("StringFormatInvalid", "StringFormatMatches")
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
|
||||
|
|
@ -223,7 +223,6 @@ class HomeFragment : Fragment(R.layout.fragment_home) {
|
|||
with(binding.howToUse) {
|
||||
text1.text = getString(R.string.about_how_to_use_title)
|
||||
icon.setImageResource(R.drawable.outline_info_24)
|
||||
// itemIcon.setCircleBackground(getColor(R.color.info))
|
||||
root.setOnClickListener {
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.about_how_to_use_title)
|
||||
|
|
@ -239,19 +238,22 @@ class HomeFragment : Fragment(R.layout.fragment_home) {
|
|||
with(binding.manageApps) {
|
||||
text1.text = getString(R.string.title_app_manage)
|
||||
icon.setImageResource(R.drawable.outline_android_24)
|
||||
// itemIcon.setCircleBackground(getColor(R.color.warn))
|
||||
root.setOnClickListener {
|
||||
navigate(R.id.nav_app_manage)
|
||||
}
|
||||
}
|
||||
|
||||
with(binding.manageTemplates) {
|
||||
text1.text = getString(R.string.title_template_manage)
|
||||
icon.setImageResource(R.drawable.ic_outline_layers_24)
|
||||
// itemIcon.setCircleBackground(getColor(R.color.invalid))
|
||||
root.setOnClickListener {
|
||||
navigate(R.id.nav_template_manage)
|
||||
}
|
||||
}
|
||||
|
||||
with(binding.navLogs) {
|
||||
text1.text = getString(R.string.title_logs)
|
||||
icon.setImageResource(R.drawable.outline_assignment_24)
|
||||
// itemIcon.setCircleBackground(getColor(R.color.error))
|
||||
root.setOnClickListener {
|
||||
navigate(R.id.nav_logs)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,54 +0,0 @@
|
|||
package org.frknkrc44.hma_oss.ui.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import icu.nullptr.hidemyapplist.service.ConfigManager
|
||||
import icu.nullptr.hidemyapplist.ui.util.navController
|
||||
import icu.nullptr.hidemyapplist.util.PackageHelper
|
||||
import kotlinx.coroutines.launch
|
||||
import org.frknkrc44.hma_oss.R
|
||||
import org.frknkrc44.hma_oss.databinding.FragmentManageAppsBinding
|
||||
import org.frknkrc44.hma_oss.ui.adapter.AppListAdapter
|
||||
|
||||
/**
|
||||
* A simple [Fragment] subclass.
|
||||
* Use the [ManageAppsFragment.newInstance] factory method to
|
||||
* create an instance of this fragment.
|
||||
*/
|
||||
class ManageAppsFragment : Fragment(R.layout.fragment_manage_apps) {
|
||||
protected val firstComparator: Comparator<String> = Comparator.comparing(ConfigManager::isHideEnabled).reversed()
|
||||
|
||||
private val binding by viewBinding<FragmentManageAppsBinding>()
|
||||
val adapter: AppListAdapter
|
||||
|
||||
private var search = ""
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
}
|
||||
|
||||
protected open fun onBack() {
|
||||
navController.navigateUp()
|
||||
}
|
||||
|
||||
private fun applyFilter() {
|
||||
adapter.filter.filter(search)
|
||||
}
|
||||
|
||||
private fun sortList() {
|
||||
lifecycleScope.launch {
|
||||
PackageHelper.sortList(firstComparator)
|
||||
applyFilter()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun newInstance(param1: String, param2: String) = ManageAppsFragment()
|
||||
}
|
||||
}
|
||||
56
app/src/main/res/layout/app_item_view.xml
Normal file
56
app/src/main/res/layout/app_item_view.xml
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackground"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="@dimen/item_padding_horizontal"
|
||||
android:paddingVertical="@dimen/item_padding_vertical"
|
||||
tools:context="icu.nullptr.hidemyapplist.ui.view.AppItemView">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
style="@style/AppTheme.AppIcon"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:src="@tools:sample/avatars" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?textAppearanceBodyLarge"
|
||||
tools:text="@tools:sample/full_names" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/enabled"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textStyle="bold"
|
||||
android:text="@string/enabled"
|
||||
android:textColor="?colorPrimary"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/package_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="monospace"
|
||||
tools:text="com.example.app" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<com.google.android.material.checkbox.MaterialCheckBox
|
||||
android:id="@+id/checkbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:clickable="false" />
|
||||
</LinearLayout>
|
||||
42
app/src/main/res/layout/fragment_app_select.xml
Normal file
42
app/src/main/res/layout/fragment_app_select.xml
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:transitionGroup="true"
|
||||
tools:context="icu.nullptr.hidemyapplist.ui.fragment.AppSelectFragment">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/app_bar"
|
||||
android:fitsSystemWindows="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?actionBarSize"
|
||||
android:elevation="0dp" />
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipe_refresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:scrollbars="vertical">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
</LinearLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ui.fragment.ManageAppsFragment">
|
||||
|
||||
<!-- TODO: Update blank fragment layout -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:text="@string/hello_blank_fragment" />
|
||||
|
||||
</FrameLayout>
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue