Add consolidated alert rule editing

This commit is contained in:
ajp_anton
2026-08-16 17:18:43 +00:00
parent c209ef24bb
commit 594931e51d
2 changed files with 158 additions and 0 deletions
@@ -0,0 +1,93 @@
package se.ajpanton.notificationsmaster.alerts
import java.util.UUID
/** All editable rule fields apart from app assignment, local order, and identity. */
data class AlertRuleDefinition(
val sources: Set<AlertSource>,
val matcher: AlertTextMatcher = AlertTextMatcher(),
val outcome: AlertOutcome,
val profileId: String? = null,
val playToCompletion: Boolean = false,
val allowDuringDnd: Boolean = false,
val enabled: Boolean = true,
val name: String? = null,
) {
init {
require(sources.isNotEmpty())
require((outcome == AlertOutcome.PLAY_PROFILE) == (profileId != null))
require(name?.isNotBlank() != false)
}
}
data class ConsolidatedAlertRule(
val definition: AlertRuleDefinition,
val ruleIds: Set<String>,
val packageNames: Set<String>,
)
object AlertRuleEditor {
fun consolidate(rules: Iterable<AlertRule>): List<ConsolidatedAlertRule> =
rules.groupBy(AlertRule::groupingKey).values.map { group ->
ConsolidatedAlertRule(
definition = group.first().definition(),
ruleIds = group.mapTo(linkedSetOf()) { it.id },
packageNames = group.mapTo(sortedSetOf()) { it.packageName },
)
}.sortedWith(compareBy<ConsolidatedAlertRule> { it.definition.name ?: "" }.thenBy { it.packageNames.first() })
fun updateConsolidated(
configuration: AlertConfiguration,
ruleIds: Set<String>,
definition: AlertRuleDefinition,
): AlertConfiguration = configuration.copy(
rules = configuration.rules.map { rule ->
if (rule.id in ruleIds) rule.withDefinition(definition) else rule
},
)
fun updateForApp(
configuration: AlertConfiguration,
ruleId: String,
definition: AlertRuleDefinition,
): AlertConfiguration = updateConsolidated(configuration, setOf(ruleId), definition)
fun addForApps(
configuration: AlertConfiguration,
packageNames: Iterable<String>,
definition: AlertRuleDefinition,
newId: () -> String = { UUID.randomUUID().toString() },
): AlertConfiguration {
val added = packageNames.distinct().map { packageName ->
AlertRule(
id = newId(),
packageName = packageName,
order = configuration.rules.filter { it.packageName == packageName }.maxOfOrNull { it.order }?.plus(1) ?: 0,
sources = definition.sources,
matcher = definition.matcher,
outcome = definition.outcome,
profileId = definition.profileId,
playToCompletion = definition.playToCompletion,
allowDuringDnd = definition.allowDuringDnd,
enabled = definition.enabled,
name = definition.name,
)
}
return configuration.copy(rules = configuration.rules + added)
}
private fun AlertRule.definition() = AlertRuleDefinition(
sources, matcher, outcome, profileId, playToCompletion, allowDuringDnd, enabled, name,
)
private fun AlertRule.withDefinition(definition: AlertRuleDefinition) = copy(
sources = definition.sources,
matcher = definition.matcher,
outcome = definition.outcome,
profileId = definition.profileId,
playToCompletion = definition.playToCompletion,
allowDuringDnd = definition.allowDuringDnd,
enabled = definition.enabled,
name = definition.name,
)
}