104 lines
5.4 KiB
Kotlin
104 lines
5.4 KiB
Kotlin
package se.ajpanton.notificationsmaster
|
|
|
|
import android.os.Bundle
|
|
import android.view.View
|
|
import android.widget.TextView
|
|
import androidx.core.os.bundleOf
|
|
import androidx.fragment.app.Fragment
|
|
import androidx.recyclerview.widget.ItemTouchHelper
|
|
import androidx.recyclerview.widget.RecyclerView
|
|
import se.ajpanton.notificationsmaster.alerts.AlertConfigurationStore
|
|
import se.ajpanton.notificationsmaster.alerts.AlertAppSettings
|
|
import se.ajpanton.notificationsmaster.alerts.AlertRule
|
|
import se.ajpanton.notificationsmaster.alerts.AlertRuleEditor
|
|
import se.ajpanton.notificationsmaster.databinding.FragmentAppRulesBinding
|
|
|
|
class AppRulesFragment : Fragment(R.layout.fragment_app_rules) {
|
|
private var binding: FragmentAppRulesBinding? = null
|
|
private lateinit var packageName: String
|
|
private lateinit var store: AlertConfigurationStore
|
|
private val adapter = RuleAdapter(::edit)
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
super.onCreate(savedInstanceState)
|
|
packageName = requireArguments().getString(ARG_PACKAGE)!!
|
|
}
|
|
|
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
binding = FragmentAppRulesBinding.bind(view)
|
|
store = AlertConfigurationStore(requireContext())
|
|
binding!!.rules.adapter = adapter
|
|
binding!!.addRule.setOnClickListener { edit(null) }
|
|
binding!!.allowMultipleMatches.isChecked = store.load().appSettings.firstOrNull { it.packageName == packageName }?.allowMultipleMatches == true
|
|
binding!!.allowMultipleMatches.setOnCheckedChangeListener { _, enabled -> setAllowMultipleMatches(enabled) }
|
|
ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP or ItemTouchHelper.DOWN, 0) {
|
|
override fun onMove(recyclerView: RecyclerView, holder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
|
|
adapter.move(holder.bindingAdapterPosition, target.bindingAdapterPosition)
|
|
saveOrder()
|
|
return true
|
|
}
|
|
override fun onSwiped(holder: RecyclerView.ViewHolder, direction: Int) = Unit
|
|
}).attachToRecyclerView(binding!!.rules)
|
|
refresh()
|
|
}
|
|
|
|
override fun onResume() {
|
|
super.onResume()
|
|
activity?.title = InstalledApps.name(requireContext(), packageName)
|
|
}
|
|
|
|
override fun onDestroyView() { binding = null; super.onDestroyView() }
|
|
|
|
private fun refresh() = adapter.submit(store.load().rules.filter { it.packageName == packageName }.sortedBy { it.order })
|
|
|
|
private fun edit(existing: AlertRule?) {
|
|
val configuration = store.load()
|
|
AlertRuleDialog.show(requireContext(), configuration, existing,
|
|
onSave = { _, definition ->
|
|
store.save(if (existing == null) AlertRuleEditor.addForApps(configuration, listOf(packageName), definition) else AlertRuleEditor.updateForApp(configuration, existing.id, definition))
|
|
refresh()
|
|
},
|
|
onDelete = existing?.let { rule -> { store.save(AlertRuleEditor.remove(store.load(), setOf(rule.id))); refresh() } },
|
|
)
|
|
}
|
|
|
|
private fun saveOrder() {
|
|
store.save(AlertRuleEditor.reorderForApp(store.load(), packageName, adapter.items.map { it.id }))
|
|
}
|
|
|
|
private fun setAllowMultipleMatches(enabled: Boolean) {
|
|
val configuration = store.load()
|
|
val old = configuration.appSettings.firstOrNull { it.packageName == packageName }
|
|
val setting = (old ?: AlertAppSettings(packageName)).copy(allowMultipleMatches = enabled)
|
|
saveAppSettings(configuration, setting)
|
|
}
|
|
|
|
private fun saveAppSettings(configuration: se.ajpanton.notificationsmaster.alerts.AlertConfiguration, setting: AlertAppSettings) {
|
|
store.save(configuration.copy(appSettings = configuration.appSettings.filterNot { it.packageName == packageName } +
|
|
if (setting.allowMultipleMatches) listOf(setting) else emptyList()))
|
|
}
|
|
|
|
private class RuleAdapter(private val onClick: (AlertRule) -> Unit) : RecyclerView.Adapter<RuleAdapter.Holder>() {
|
|
var items = emptyList<AlertRule>(); private set
|
|
fun submit(rules: List<AlertRule>) { items = rules; notifyDataSetChanged() }
|
|
fun move(from: Int, to: Int) { items = items.toMutableList().apply { add(to, removeAt(from)) }; notifyItemMoved(from, to) }
|
|
override fun onCreateViewHolder(parent: android.view.ViewGroup, viewType: Int) = Holder(TextView(parent.context).apply {
|
|
layoutParams = RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT)
|
|
val padding = (16 * parent.resources.displayMetrics.density).toInt()
|
|
setPadding(padding, padding, padding, padding); textSize = 16f; isClickable = true
|
|
})
|
|
override fun onBindViewHolder(holder: Holder, position: Int) {
|
|
val rule = items[position]
|
|
holder.text.text = rule.name ?: "Rule ${position + 1}" + "\n" + rule.sources.joinToString { it.label() } + rule.matcher.value.takeIf { it.isNotBlank() }?.let { " • contains $it" }.orEmpty()
|
|
holder.text.setOnClickListener { onClick(rule) }
|
|
}
|
|
override fun getItemCount() = items.size
|
|
class Holder(val text: TextView) : RecyclerView.ViewHolder(text)
|
|
}
|
|
|
|
companion object {
|
|
private const val ARG_PACKAGE = "package"
|
|
fun newInstance(packageName: String) = AppRulesFragment().apply { arguments = bundleOf(ARG_PACKAGE to packageName) }
|
|
}
|
|
}
|