Add per-app alert rule management
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
package se.ajpanton.notificationsmaster
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.CheckBox
|
||||
import android.widget.EditText
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Spinner
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.switchmaterial.SwitchMaterial
|
||||
import se.ajpanton.notificationsmaster.alerts.AlertConfiguration
|
||||
import se.ajpanton.notificationsmaster.alerts.AlertOutcome
|
||||
import se.ajpanton.notificationsmaster.alerts.AlertRule
|
||||
import se.ajpanton.notificationsmaster.alerts.AlertRuleDefinition
|
||||
import se.ajpanton.notificationsmaster.alerts.AlertSource
|
||||
import se.ajpanton.notificationsmaster.alerts.AlertTextField
|
||||
import se.ajpanton.notificationsmaster.alerts.AlertTextMatcher
|
||||
import se.ajpanton.notificationsmaster.alerts.AlertTextMode
|
||||
|
||||
object AlertRuleDialog {
|
||||
fun show(
|
||||
context: Context,
|
||||
configuration: AlertConfiguration,
|
||||
existing: AlertRule?,
|
||||
apps: List<InstalledApp>? = null,
|
||||
onSave: (String?, AlertRuleDefinition) -> Unit,
|
||||
) {
|
||||
val form = LinearLayout(context).apply { orientation = LinearLayout.VERTICAL; setPadding(dp(context, 24), 0, dp(context, 24), 0) }
|
||||
val app = apps?.let {
|
||||
Spinner(context).apply {
|
||||
adapter = ArrayAdapter(context, android.R.layout.simple_spinner_dropdown_item, it)
|
||||
existing?.let { rule -> setSelection(apps.indexOfFirst { choice -> choice.packageName == rule.packageName }.coerceAtLeast(0)) }
|
||||
}.also(form::addView)
|
||||
}
|
||||
val profile = Spinner(context).apply {
|
||||
adapter = ArrayAdapter(context, android.R.layout.simple_spinner_dropdown_item, configuration.profiles.map { it.name })
|
||||
existing?.let { rule -> setSelection(configuration.profiles.indexOfFirst { it.id == rule.profileId }.coerceAtLeast(0)) }
|
||||
}
|
||||
val post = CheckBox(context).apply { text = "Appearing"; isChecked = existing == null || AlertSource.NOTIFICATION_POST in existing.sources }
|
||||
val update = CheckBox(context).apply { text = "Edits"; isChecked = existing == null || AlertSource.NOTIFICATION_UPDATE in existing.sources }
|
||||
val pattern = EditText(context).apply { hint = "Text to match (optional)"; setText(existing?.matcher?.value) }
|
||||
val regex = SwitchMaterial(context).apply { text = "Use regular expression"; isChecked = existing?.matcher?.mode == AlertTextMode.REGEX }
|
||||
val protected = SwitchMaterial(context).apply { text = "Play to completion"; isChecked = existing?.playToCompletion == true }
|
||||
val dnd = SwitchMaterial(context).apply { text = "Allow during DND when supported"; isChecked = existing?.allowDuringDnd == true }
|
||||
listOf(profile, post, update, pattern, regex, protected, dnd).forEach(form::addView)
|
||||
val dialog = MaterialAlertDialogBuilder(context).setTitle(if (existing == null) "Add rule" else "Edit rule")
|
||||
.setView(form).setNegativeButton("Cancel", null).setPositiveButton("Save", null).show()
|
||||
dialog.getButton(android.content.DialogInterface.BUTTON_POSITIVE).setOnClickListener {
|
||||
val sources = buildSet {
|
||||
if (post.isChecked) add(AlertSource.NOTIFICATION_POST)
|
||||
if (update.isChecked) add(AlertSource.NOTIFICATION_UPDATE)
|
||||
}
|
||||
if (sources.isEmpty()) { post.error = "Choose an event"; return@setOnClickListener }
|
||||
val value = pattern.text.toString().trim()
|
||||
val matcher = runCatching {
|
||||
AlertTextMatcher(
|
||||
AlertTextField.ANY_TEXT,
|
||||
if (value.isEmpty()) AlertTextMode.ANY else if (regex.isChecked) AlertTextMode.REGEX else AlertTextMode.CONTAINS,
|
||||
value,
|
||||
)
|
||||
}.getOrElse {
|
||||
pattern.error = "Invalid regular expression"
|
||||
return@setOnClickListener
|
||||
}
|
||||
val definition = AlertRuleDefinition(
|
||||
sources,
|
||||
matcher,
|
||||
AlertOutcome.PLAY_PROFILE,
|
||||
configuration.profiles[profile.selectedItemPosition].id,
|
||||
protected.isChecked,
|
||||
dnd.isChecked,
|
||||
)
|
||||
onSave(app?.selectedItem?.let { it as InstalledApp }?.packageName, definition)
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
private fun dp(context: Context, value: Int) = (value * context.resources.displayMetrics.density).toInt()
|
||||
}
|
||||
Reference in New Issue
Block a user