diff --git a/CHANGES.md b/CHANGES.md index 5769eb52c5..c923053b24 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,7 @@ Improvements 🙌: Bugfix 🐛: - Display name not shown under Settings/General (#1926) + - Words containing my name should not trigger notifications (#1781) - Fix changing language issue - Fix FontSize issue (#1483, #1787) - Fix bad color for settings icon on Android < 24 (#1786) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Action.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Action.kt index 7a21920e58..ff58650781 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Action.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Action.kt @@ -24,21 +24,24 @@ sealed class Action { object DoNotNotify : Action() data class Sound(val sound: String = ACTION_OBJECT_VALUE_VALUE_DEFAULT) : Action() data class Highlight(val highlight: Boolean) : Action() + + companion object { + const val ACTION_NOTIFY = "notify" + const val ACTION_DONT_NOTIFY = "dont_notify" + const val ACTION_COALESCE = "coalesce" + + // Ref: https://matrix.org/docs/spec/client_server/latest#tweaks + const val ACTION_OBJECT_SET_TWEAK_KEY = "set_tweak" + + const val ACTION_OBJECT_SET_TWEAK_VALUE_SOUND = "sound" + const val ACTION_OBJECT_SET_TWEAK_VALUE_HIGHLIGHT = "highlight" + + const val ACTION_OBJECT_VALUE_KEY = "value" + const val ACTION_OBJECT_VALUE_VALUE_DEFAULT = "default" + const val ACTION_OBJECT_VALUE_VALUE_RING = "ring" + } } -private const val ACTION_NOTIFY = "notify" -private const val ACTION_DONT_NOTIFY = "dont_notify" -private const val ACTION_COALESCE = "coalesce" - -// Ref: https://matrix.org/docs/spec/client_server/latest#tweaks -private const val ACTION_OBJECT_SET_TWEAK_KEY = "set_tweak" - -private const val ACTION_OBJECT_SET_TWEAK_VALUE_SOUND = "sound" -private const val ACTION_OBJECT_SET_TWEAK_VALUE_HIGHLIGHT = "highlight" - -private const val ACTION_OBJECT_VALUE_KEY = "value" -private const val ACTION_OBJECT_VALUE_VALUE_DEFAULT = "default" - /** * Ref: https://matrix.org/docs/spec/client_server/latest#actions * @@ -69,18 +72,18 @@ private const val ACTION_OBJECT_VALUE_VALUE_DEFAULT = "default" fun List.toJson(): List { return map { action -> when (action) { - is Action.Notify -> ACTION_NOTIFY - is Action.DoNotNotify -> ACTION_DONT_NOTIFY - is Action.Sound -> { + is Action.Notify -> Action.ACTION_NOTIFY + is Action.DoNotNotify -> Action.ACTION_DONT_NOTIFY + is Action.Sound -> { mapOf( - ACTION_OBJECT_SET_TWEAK_KEY to ACTION_OBJECT_SET_TWEAK_VALUE_SOUND, - ACTION_OBJECT_VALUE_KEY to action.sound + Action.ACTION_OBJECT_SET_TWEAK_KEY to Action.ACTION_OBJECT_SET_TWEAK_VALUE_SOUND, + Action.ACTION_OBJECT_VALUE_KEY to action.sound ) } - is Action.Highlight -> { + is Action.Highlight -> { mapOf( - ACTION_OBJECT_SET_TWEAK_KEY to ACTION_OBJECT_SET_TWEAK_VALUE_HIGHLIGHT, - ACTION_OBJECT_VALUE_KEY to action.highlight + Action.ACTION_OBJECT_SET_TWEAK_KEY to Action.ACTION_OBJECT_SET_TWEAK_VALUE_HIGHLIGHT, + Action.ACTION_OBJECT_VALUE_KEY to action.highlight ) } } @@ -92,26 +95,26 @@ fun PushRule.getActions(): List { actions.forEach { actionStrOrObj -> when (actionStrOrObj) { - ACTION_NOTIFY -> Action.Notify - ACTION_DONT_NOTIFY -> Action.DoNotNotify - is Map<*, *> -> { - when (actionStrOrObj[ACTION_OBJECT_SET_TWEAK_KEY]) { - ACTION_OBJECT_SET_TWEAK_VALUE_SOUND -> { - (actionStrOrObj[ACTION_OBJECT_VALUE_KEY] as? String)?.let { stringValue -> + Action.ACTION_NOTIFY -> Action.Notify + Action.ACTION_DONT_NOTIFY -> Action.DoNotNotify + is Map<*, *> -> { + when (actionStrOrObj[Action.ACTION_OBJECT_SET_TWEAK_KEY]) { + Action.ACTION_OBJECT_SET_TWEAK_VALUE_SOUND -> { + (actionStrOrObj[Action.ACTION_OBJECT_VALUE_KEY] as? String)?.let { stringValue -> Action.Sound(stringValue) } // When the value is not there, default sound (not specified by the spec) - ?: Action.Sound(ACTION_OBJECT_VALUE_VALUE_DEFAULT) + ?: Action.Sound(Action.ACTION_OBJECT_VALUE_VALUE_DEFAULT) } - ACTION_OBJECT_SET_TWEAK_VALUE_HIGHLIGHT -> { - (actionStrOrObj[ACTION_OBJECT_VALUE_KEY] as? Boolean)?.let { boolValue -> + Action.ACTION_OBJECT_SET_TWEAK_VALUE_HIGHLIGHT -> { + (actionStrOrObj[Action.ACTION_OBJECT_VALUE_KEY] as? Boolean)?.let { boolValue -> Action.Highlight(boolValue) } // When the value is not there, default is true, says the spec ?: Action.Highlight(true) } else -> { - Timber.w("Unsupported set_tweak value ${actionStrOrObj[ACTION_OBJECT_SET_TWEAK_KEY]}") + Timber.w("Unsupported set_tweak value ${actionStrOrObj[Action.ACTION_OBJECT_SET_TWEAK_KEY]}") null } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Condition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Condition.kt index 50c2f8505b..3b1082ea0a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Condition.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Condition.kt @@ -18,32 +18,8 @@ package org.matrix.android.sdk.api.pushrules import org.matrix.android.sdk.api.session.events.model.Event -abstract class Condition(val kind: Kind) { +interface Condition { + fun isSatisfied(event: Event, conditionResolver: ConditionResolver): Boolean - enum class Kind(val value: String) { - EventMatch("event_match"), - ContainsDisplayName("contains_display_name"), - RoomMemberCount("room_member_count"), - SenderNotificationPermission("sender_notification_permission"), - Unrecognised(""); - - companion object { - - fun fromString(value: String): Kind { - return when (value) { - "event_match" -> EventMatch - "contains_display_name" -> ContainsDisplayName - "room_member_count" -> RoomMemberCount - "sender_notification_permission" -> SenderNotificationPermission - else -> Unrecognised - } - } - } - } - - abstract fun isSatisfied(event: Event, conditionResolver: ConditionResolver): Boolean - - open fun technicalDescription(): String { - return "Kind: $kind" - } + fun technicalDescription(): String } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/ContainsDisplayNameCondition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/ContainsDisplayNameCondition.kt index a836c24c4e..72eda20679 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/ContainsDisplayNameCondition.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/ContainsDisplayNameCondition.kt @@ -20,17 +20,15 @@ import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.model.message.MessageContent -import timber.log.Timber +import org.matrix.android.sdk.internal.util.caseInsensitiveFind -class ContainsDisplayNameCondition : Condition(Kind.ContainsDisplayName) { +class ContainsDisplayNameCondition : Condition { override fun isSatisfied(event: Event, conditionResolver: ConditionResolver): Boolean { return conditionResolver.resolveContainsDisplayNameCondition(event, this) } - override fun technicalDescription(): String { - return "User is mentioned" - } + override fun technicalDescription() = "User is mentioned" fun isSatisfied(event: Event, displayName: String): Boolean { val message = when (event.type) { @@ -45,31 +43,6 @@ class ContainsDisplayNameCondition : Condition(Kind.ContainsDisplayName) { else -> null } ?: return false - return caseInsensitiveFind(displayName, message.body) - } - - companion object { - /** - * Returns whether a string contains an occurrence of another, as a standalone word, regardless of case. - * - * @param subString the string to search for - * @param longString the string to search in - * @return whether a match was found - */ - fun caseInsensitiveFind(subString: String, longString: String): Boolean { - // add sanity checks - if (subString.isEmpty() || longString.isEmpty()) { - return false - } - - try { - val regex = Regex("(\\W|^)" + Regex.escape(subString) + "(\\W|$)", RegexOption.IGNORE_CASE) - return regex.containsMatchIn(longString) - } catch (e: Exception) { - Timber.e(e, "## caseInsensitiveFind() : failed") - } - - return false - } + return message.body.caseInsensitiveFind(displayName) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/EventMatchCondition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/EventMatchCondition.kt index 5eed785899..c9aa0d001a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/EventMatchCondition.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/EventMatchCondition.kt @@ -18,6 +18,9 @@ package org.matrix.android.sdk.api.pushrules import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.internal.di.MoshiProvider +import org.matrix.android.sdk.internal.util.caseInsensitiveFind +import org.matrix.android.sdk.internal.util.hasSpecialGlobChar +import org.matrix.android.sdk.internal.util.simpleGlobToRegExp import timber.log.Timber class EventMatchCondition( @@ -29,16 +32,18 @@ class EventMatchCondition( * The glob-style pattern to match against. Patterns with no special glob characters should * be treated as having asterisks prepended and appended when testing the condition. */ - val pattern: String -) : Condition(Kind.EventMatch) { + val pattern: String, + /** + * true to match only words. In this case pattern will not be considered as a glob + */ + val wordsOnly: Boolean +) : Condition { override fun isSatisfied(event: Event, conditionResolver: ConditionResolver): Boolean { return conditionResolver.resolveEventMatchCondition(event, this) } - override fun technicalDescription(): String { - return "'$key' Matches '$pattern'" - } + override fun technicalDescription() = "'$key' matches '$pattern', words only '$wordsOnly'" fun isSatisfied(event: Event): Boolean { // TODO encrypted events? @@ -48,14 +53,18 @@ class EventMatchCondition( // Patterns with no special glob characters should be treated as having asterisks prepended // and appended when testing the condition. - try { - val modPattern = if (hasSpecialGlobChar(pattern)) simpleGlobToRegExp(pattern) else simpleGlobToRegExp("*$pattern*") - val regex = Regex(modPattern, RegexOption.DOT_MATCHES_ALL) - return regex.containsMatchIn(value) + return try { + if (wordsOnly) { + value.caseInsensitiveFind(pattern) + } else { + val modPattern = if (pattern.hasSpecialGlobChar()) pattern.simpleGlobToRegExp() else "*$pattern*".simpleGlobToRegExp() + val regex = Regex(modPattern, RegexOption.DOT_MATCHES_ALL) + regex.containsMatchIn(value) + } } catch (e: Throwable) { // e.g PatternSyntaxException Timber.e(e, "Failed to evaluate push condition") - return false + false } } @@ -78,27 +87,4 @@ class EventMatchCondition( } return null } - - companion object { - - private fun hasSpecialGlobChar(glob: String): Boolean { - return glob.contains("*") || glob.contains("?") - } - - // Very simple glob to regexp converter - private fun simpleGlobToRegExp(glob: String): String { - var out = "" // "^" - for (element in glob) { - when (element) { - '*' -> out += ".*" - '?' -> out += '.'.toString() - '.' -> out += "\\." - '\\' -> out += "\\\\" - else -> out += element - } - } - out += "" // '$'.toString() - return out - } - } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Kind.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Kind.kt new file mode 100644 index 0000000000..78f3a8a156 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Kind.kt @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020 New Vector Ltd + * Copyright 2020 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.api.pushrules + +enum class Kind(val value: String) { + EventMatch("event_match"), + ContainsDisplayName("contains_display_name"), + RoomMemberCount("room_member_count"), + SenderNotificationPermission("sender_notification_permission"), + Unrecognised(""); + + companion object { + + fun fromString(value: String): Kind { + return when (value) { + "event_match" -> EventMatch + "contains_display_name" -> ContainsDisplayName + "room_member_count" -> RoomMemberCount + "sender_notification_permission" -> SenderNotificationPermission + else -> Unrecognised + } + } + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RoomMemberCountCondition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RoomMemberCountCondition.kt index f97636a7bd..ba36c54fb4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RoomMemberCountCondition.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RoomMemberCountCondition.kt @@ -29,15 +29,13 @@ class RoomMemberCountCondition( * If no prefix is present, this parameter defaults to ==. */ val iz: String -) : Condition(Kind.RoomMemberCount) { +) : Condition { override fun isSatisfied(event: Event, conditionResolver: ConditionResolver): Boolean { return conditionResolver.resolveRoomMemberCountCondition(event, this) } - override fun technicalDescription(): String { - return "Room member count is $iz" - } + override fun technicalDescription() = "Room member count is $iz" internal fun isSatisfied(event: Event, roomGetter: RoomGetter): Boolean { // sanity checks diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RuleIds.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RuleIds.kt index eeb2577d4c..2353d06252 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RuleIds.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RuleIds.kt @@ -45,4 +45,6 @@ object RuleIds { // Not documented const val RULE_ID_FALLBACK = ".m.rule.fallback" + + const val RULE_ID_REACTION = ".m.rule.reaction" } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/SenderNotificationPermissionCondition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/SenderNotificationPermissionCondition.kt index a8d08e5458..aeb2f01c80 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/SenderNotificationPermissionCondition.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/SenderNotificationPermissionCondition.kt @@ -28,15 +28,13 @@ class SenderNotificationPermissionCondition( * type from the notifications object in the power level event content. */ val key: String -) : Condition(Kind.SenderNotificationPermission) { +) : Condition { override fun isSatisfied(event: Event, conditionResolver: ConditionResolver): Boolean { return conditionResolver.resolveSenderNotificationPermissionCondition(event, this) } - override fun technicalDescription(): String { - return "User power level <$key>" - } + override fun technicalDescription() = "User power level <$key>" fun isSatisfied(event: Event, powerLevels: PowerLevelsContent): Boolean { val powerLevelsHelper = PowerLevelsHelper(powerLevels) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushCondition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushCondition.kt index 9469da3ea5..29466ca33b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushCondition.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushCondition.kt @@ -21,7 +21,9 @@ import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.pushrules.Condition import org.matrix.android.sdk.api.pushrules.ContainsDisplayNameCondition import org.matrix.android.sdk.api.pushrules.EventMatchCondition +import org.matrix.android.sdk.api.pushrules.Kind import org.matrix.android.sdk.api.pushrules.RoomMemberCountCondition +import org.matrix.android.sdk.api.pushrules.RuleIds import org.matrix.android.sdk.api.pushrules.SenderNotificationPermissionCondition import timber.log.Timber @@ -58,20 +60,20 @@ data class PushCondition( val iz: String? = null ) { - fun asExecutableCondition(): Condition? { - return when (Condition.Kind.fromString(kind)) { - Condition.Kind.EventMatch -> { + fun asExecutableCondition(rule: PushRule): Condition? { + return when (Kind.fromString(kind)) { + Kind.EventMatch -> { if (key != null && pattern != null) { - EventMatchCondition(key, pattern) + EventMatchCondition(key, pattern, rule.ruleId == RuleIds.RULE_ID_CONTAIN_USER_NAME) } else { Timber.e("Malformed Event match condition") null } } - Condition.Kind.ContainsDisplayName -> { + Kind.ContainsDisplayName -> { ContainsDisplayNameCondition() } - Condition.Kind.RoomMemberCount -> { + Kind.RoomMemberCount -> { if (iz.isNullOrEmpty()) { Timber.e("Malformed ROOM_MEMBER_COUNT condition") null @@ -79,7 +81,7 @@ data class PushCondition( RoomMemberCountCondition(iz) } } - Condition.Kind.SenderNotificationPermission -> { + Kind.SenderNotificationPermission -> { if (key == null) { Timber.e("Malformed Sender Notification Permission condition") null @@ -87,7 +89,7 @@ data class PushCondition( SenderNotificationPermissionCondition(key) } } - Condition.Kind.Unrecognised -> { + Kind.Unrecognised -> { Timber.e("Unknown kind $kind") null } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushRule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushRule.kt index 46d73a8aa2..bdb4f2cf29 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushRule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushRule.kt @@ -63,7 +63,7 @@ data class PushRule( * Add the default notification sound. */ fun setNotificationSound(): PushRule { - return setNotificationSound(ACTION_VALUE_DEFAULT) + return setNotificationSound(Action.ACTION_OBJECT_VALUE_VALUE_DEFAULT) } fun getNotificationSound(): String? { @@ -109,13 +109,13 @@ data class PushRule( fun setNotify(notify: Boolean): PushRule { val mutableActions = actions.toMutableList() - mutableActions.remove(ACTION_DONT_NOTIFY) - mutableActions.remove(ACTION_NOTIFY) + mutableActions.remove(Action.ACTION_DONT_NOTIFY) + mutableActions.remove(Action.ACTION_NOTIFY) if (notify) { - mutableActions.add(ACTION_NOTIFY) + mutableActions.add(Action.ACTION_NOTIFY) } else { - mutableActions.add(ACTION_DONT_NOTIFY) + mutableActions.add(Action.ACTION_DONT_NOTIFY) } return copy(actions = mutableActions) @@ -126,51 +126,12 @@ data class PushRule( * * @return true if the rule should play sound */ - fun shouldNotify() = actions.contains(ACTION_NOTIFY) + fun shouldNotify() = actions.contains(Action.ACTION_NOTIFY) /** * Return true if the rule should not highlight the event. * * @return true if the rule should not play sound */ - fun shouldNotNotify() = actions.contains(ACTION_DONT_NOTIFY) - - companion object { - /* ========================================================================================== - * Rule id - * ========================================================================================== */ - - const val RULE_ID_DISABLE_ALL = ".m.rule.master" - const val RULE_ID_CONTAIN_USER_NAME = ".m.rule.contains_user_name" - const val RULE_ID_CONTAIN_DISPLAY_NAME = ".m.rule.contains_display_name" - const val RULE_ID_ONE_TO_ONE_ROOM = ".m.rule.room_one_to_one" - const val RULE_ID_INVITE_ME = ".m.rule.invite_for_me" - const val RULE_ID_PEOPLE_JOIN_LEAVE = ".m.rule.member_event" - const val RULE_ID_CALL = ".m.rule.call" - const val RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS = ".m.rule.suppress_notices" - const val RULE_ID_ALL_OTHER_MESSAGES_ROOMS = ".m.rule.message" - const val RULE_ID_AT_ROOMS = ".m.rule.roomnotif" - const val RULE_ID_TOMBSTONE = ".m.rule.tombstone" - const val RULE_ID_E2E_ONE_TO_ONE_ROOM = ".m.rule.encrypted_room_one_to_one" - const val RULE_ID_E2E_GROUP = ".m.rule.encrypted" - const val RULE_ID_REACTION = ".m.rule.reaction" - const val RULE_ID_FALLBACK = ".m.rule.fallback" - - /* ========================================================================================== - * Actions - * ========================================================================================== */ - - const val ACTION_NOTIFY = "notify" - const val ACTION_DONT_NOTIFY = "dont_notify" - const val ACTION_COALESCE = "coalesce" - - const val ACTION_SET_TWEAK_SOUND_VALUE = "sound" - const val ACTION_SET_TWEAK_HIGHLIGHT_VALUE = "highlight" - - const val ACTION_PARAMETER_SET_TWEAK = "set_tweak" - const val ACTION_PARAMETER_VALUE = "value" - - const val ACTION_VALUE_DEFAULT = "default" - const val ACTION_VALUE_RING = "ring" - } + fun shouldNotNotify() = actions.contains(Action.ACTION_DONT_NOTIFY) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/RuleSet.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/RuleSet.kt index eb813dba45..a8708819f5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/RuleSet.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/RuleSet.kt @@ -18,6 +18,7 @@ package org.matrix.android.sdk.api.pushrules.rest import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.pushrules.RuleIds import org.matrix.android.sdk.api.pushrules.RuleSetKey /** @@ -51,7 +52,7 @@ data class RuleSet( var result: PushRuleAndKind? = null // sanity check if (null != ruleId) { - if (PushRule.RULE_ID_CONTAIN_USER_NAME == ruleId) { + if (RuleIds.RULE_ID_CONTAIN_USER_NAME == ruleId) { result = findRule(content, ruleId)?.let { PushRuleAndKind(it, RuleSetKey.CONTENT) } } else { // assume that the ruleId is unique. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/PushRulesMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/PushRulesMapper.kt index 90fc62f8f3..3bcc3d2ea7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/PushRulesMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/PushRulesMapper.kt @@ -17,12 +17,12 @@ package org.matrix.android.sdk.internal.database.mapper import com.squareup.moshi.Types -import org.matrix.android.sdk.api.pushrules.Condition +import io.realm.RealmList +import org.matrix.android.sdk.api.pushrules.Kind import org.matrix.android.sdk.api.pushrules.rest.PushCondition import org.matrix.android.sdk.api.pushrules.rest.PushRule import org.matrix.android.sdk.internal.database.model.PushRuleEntity import org.matrix.android.sdk.internal.di.MoshiProvider -import io.realm.RealmList import timber.log.Timber internal object PushRulesMapper { @@ -39,7 +39,7 @@ internal object PushRulesMapper { enabled = pushrule.enabled, ruleId = pushrule.ruleId, conditions = listOf( - PushCondition(Condition.Kind.EventMatch.value, "content.body", pushrule.pattern) + PushCondition(Kind.EventMatch.value, "content.body", pushrule.pattern) ) ) } @@ -60,7 +60,7 @@ internal object PushRulesMapper { enabled = pushrule.enabled, ruleId = pushrule.ruleId, conditions = listOf( - PushCondition(Condition.Kind.EventMatch.value, "room_id", pushrule.ruleId) + PushCondition(Kind.EventMatch.value, "room_id", pushrule.ruleId) ) ) } @@ -72,7 +72,7 @@ internal object PushRulesMapper { enabled = pushrule.enabled, ruleId = pushrule.ruleId, conditions = listOf( - PushCondition(Condition.Kind.EventMatch.value, "user_id", pushrule.ruleId) + PushCondition(Kind.EventMatch.value, "user_id", pushrule.ruleId) ) ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/notification/ProcessEventForPushTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/notification/ProcessEventForPushTask.kt index 49a92acc54..a0667cc4a3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/notification/ProcessEventForPushTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/notification/ProcessEventForPushTask.kt @@ -100,7 +100,7 @@ internal class DefaultProcessEventForPushTask @Inject constructor( return rules.firstOrNull { rule -> // All conditions must hold true for an event in order to apply the action for the event. rule.enabled && rule.conditions?.all { - it.asExecutableCondition()?.isSatisfied(event, conditionResolver) ?: false + it.asExecutableCondition(rule)?.isSatisfied(event, conditionResolver) ?: false } ?: false } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/RoomPushRuleMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/RoomPushRuleMapper.kt index 1a19a40602..86a9500339 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/RoomPushRuleMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/RoomPushRuleMapper.kt @@ -18,7 +18,7 @@ package org.matrix.android.sdk.internal.session.room.notification import org.matrix.android.sdk.api.pushrules.Action -import org.matrix.android.sdk.api.pushrules.Condition +import org.matrix.android.sdk.api.pushrules.Kind import org.matrix.android.sdk.api.pushrules.RuleSetKey import org.matrix.android.sdk.api.pushrules.getActions import org.matrix.android.sdk.api.pushrules.rest.PushCondition @@ -59,7 +59,7 @@ internal fun RoomNotificationState.toRoomPushRule(roomId: String): RoomPushRule? } else -> { val condition = PushCondition( - kind = Condition.Kind.EventMatch.value, + kind = Kind.EventMatch.value, key = "room_id", pattern = roomId ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Glob.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Glob.kt new file mode 100644 index 0000000000..129bf0dec4 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Glob.kt @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020 New Vector Ltd + * Copyright 2020 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.internal.util + +internal fun String.hasSpecialGlobChar(): Boolean { + return contains("*") || contains("?") +} + +// Very simple glob to regexp converter +internal fun String.simpleGlobToRegExp(): String { + val string = this + return buildString { + // append("^") + string.forEach { char -> + when (char) { + '*' -> append(".*") + '?' -> append(".") + '.' -> append("\\.") + '\\' -> append("\\\\") + else -> append(char) + } + } + // append("$") + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/StringUtils.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/StringUtils.kt index a236771cd6..681e7e5fed 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/StringUtils.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/StringUtils.kt @@ -52,3 +52,25 @@ fun convertFromUTF8(s: String): String { } fun String.withoutPrefix(prefix: String) = if (startsWith(prefix)) substringAfter(prefix) else this + +/** + * Returns whether a string contains an occurrence of another, as a standalone word, regardless of case. + * + * @param subString the string to search for + * @return whether a match was found + */ +fun String.caseInsensitiveFind(subString: String): Boolean { + // add sanity checks + if (subString.isEmpty() || isEmpty()) { + return false + } + + try { + val regex = Regex("(\\W|^)" + Regex.escape(subString) + "(\\W|$)", RegexOption.IGNORE_CASE) + return regex.containsMatchIn(this) + } catch (e: Exception) { + Timber.e(e, "## caseInsensitiveFind() : failed") + } + + return false +} diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/pushrules/PushrulesConditionTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/pushrules/PushRulesConditionTest.kt similarity index 82% rename from matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/pushrules/PushrulesConditionTest.kt rename to matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/pushrules/PushRulesConditionTest.kt index be5aeaaf0f..b2c8d3bda8 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/pushrules/PushrulesConditionTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/pushrules/PushRulesConditionTest.kt @@ -16,6 +16,12 @@ package org.matrix.android.sdk.api.pushrules +import io.mockk.every +import io.mockk.mockk +import org.amshove.kluent.shouldBe +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test import org.matrix.android.sdk.MatrixTest import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.toContent @@ -24,28 +30,26 @@ import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomMemberContent import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent import org.matrix.android.sdk.internal.session.room.RoomGetter -import io.mockk.every -import io.mockk.mockk -import org.amshove.kluent.shouldBe -import org.junit.Assert.assertFalse -import org.junit.Assert.assertTrue -import org.junit.Test -class PushrulesConditionTest: MatrixTest { +class PushRulesConditionTest : MatrixTest { /* ========================================================================================== * Test EventMatchCondition * ========================================================================================== */ - @Test - fun test_eventmatch_type_condition() { - val condition = EventMatchCondition("type", "m.room.message") - - val simpleTextEvent = Event( + private fun createSimpleTextEvent(text: String): Event { + return Event( type = "m.room.message", eventId = "mx0", - content = MessageTextContent("m.text", "Yo wtf?").toContent(), + content = MessageTextContent("m.text", text).toContent(), originServerTs = 0) + } + + @Test + fun test_eventmatch_type_condition() { + val condition = EventMatchCondition("type", "m.room.message", false) + + val simpleTextEvent = createSimpleTextEvent("Yo wtf?") val rm = RoomMemberContent( Membership.INVITE, @@ -65,13 +69,9 @@ class PushrulesConditionTest: MatrixTest { @Test fun test_eventmatch_path_condition() { - val condition = EventMatchCondition("content.msgtype", "m.text") + val condition = EventMatchCondition("content.msgtype", "m.text", false) - val simpleTextEvent = Event( - type = "m.room.message", - eventId = "mx0", - content = MessageTextContent("m.text", "Yo wtf?").toContent(), - originServerTs = 0) + val simpleTextEvent = createSimpleTextEvent("Yo wtf?") assert(condition.isSatisfied(simpleTextEvent)) @@ -86,49 +86,44 @@ class PushrulesConditionTest: MatrixTest { ).toContent(), originServerTs = 0 ).apply { - assert(EventMatchCondition("content.membership", "invite").isSatisfied(this)) + assert(EventMatchCondition("content.membership", "invite", false).isSatisfied(this)) } } @Test fun test_eventmatch_cake_condition() { - val condition = EventMatchCondition("content.body", "cake") + val condition = EventMatchCondition("content.body", "cake", false) - Event( - type = "m.room.message", - eventId = "mx0", - content = MessageTextContent("m.text", "How was the cake?").toContent(), - originServerTs = 0 - ).apply { - assert(condition.isSatisfied(this)) - } - - Event( - type = "m.room.message", - eventId = "mx0", - content = MessageTextContent("m.text", "Howwasthecake?").toContent(), - originServerTs = 0 - ).apply { - assert(condition.isSatisfied(this)) - } + assert(condition.isSatisfied(createSimpleTextEvent("How was the cake?"))) + assert(condition.isSatisfied(createSimpleTextEvent("Howwasthecake?"))) } @Test fun test_eventmatch_cakelie_condition() { - val condition = EventMatchCondition("content.body", "cake*lie") + val condition = EventMatchCondition("content.body", "cake*lie", false) - val simpleTextEvent = Event( - type = "m.room.message", - eventId = "mx0", - content = MessageTextContent("m.text", "How was the cakeisalie?").toContent(), - originServerTs = 0) + assert(condition.isSatisfied(createSimpleTextEvent("How was the cakeisalie?"))) + } - assert(condition.isSatisfied(simpleTextEvent)) + @Test + fun test_eventmatch_words_only_condition() { + val condition = EventMatchCondition("content.body", "ben", true) + + assertFalse(condition.isSatisfied(createSimpleTextEvent("benoit"))) + assertFalse(condition.isSatisfied(createSimpleTextEvent("Hello benoit"))) + assertFalse(condition.isSatisfied(createSimpleTextEvent("superben"))) + + assert(condition.isSatisfied(createSimpleTextEvent("ben"))) + assert(condition.isSatisfied(createSimpleTextEvent("hello ben"))) + assert(condition.isSatisfied(createSimpleTextEvent("ben is there"))) + assert(condition.isSatisfied(createSimpleTextEvent("hello ben!"))) + assert(condition.isSatisfied(createSimpleTextEvent("hello Ben!"))) + assert(condition.isSatisfied(createSimpleTextEvent("BEN"))) } @Test fun test_notice_condition() { - val conditionEqual = EventMatchCondition("content.msgtype", "m.notice") + val conditionEqual = EventMatchCondition("content.msgtype", "m.notice", false) Event( type = "m.room.message", diff --git a/vector/src/gplay/java/im/vector/app/gplay/push/fcm/VectorFirebaseMessagingService.kt b/vector/src/gplay/java/im/vector/app/gplay/push/fcm/VectorFirebaseMessagingService.kt index 617e40225d..be0ce86326 100755 --- a/vector/src/gplay/java/im/vector/app/gplay/push/fcm/VectorFirebaseMessagingService.kt +++ b/vector/src/gplay/java/im/vector/app/gplay/push/fcm/VectorFirebaseMessagingService.kt @@ -25,9 +25,6 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.ProcessLifecycleOwner import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage -import org.matrix.android.sdk.api.pushrules.rest.PushRule -import org.matrix.android.sdk.api.session.Session -import org.matrix.android.sdk.api.session.events.model.Event import im.vector.app.BuildConfig import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder @@ -40,6 +37,9 @@ import im.vector.app.features.notifications.NotificationDrawerManager import im.vector.app.features.notifications.SimpleNotifiableEvent import im.vector.app.features.settings.VectorPreferences import im.vector.app.push.fcm.FcmHelper +import org.matrix.android.sdk.api.pushrules.Action +import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.session.events.model.Event import timber.log.Timber /** @@ -196,7 +196,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { description = "", type = null, timestamp = System.currentTimeMillis(), - soundName = PushRule.ACTION_VALUE_DEFAULT, + soundName = Action.ACTION_OBJECT_VALUE_VALUE_DEFAULT, isPushGatewayEvent = true ) notificationDrawerManager.onNotifiableEventReceived(simpleNotifiableEvent) diff --git a/vector/src/main/java/im/vector/app/core/preference/PushRulePreference.kt b/vector/src/main/java/im/vector/app/core/preference/PushRulePreference.kt index 9c4878ef06..c3e324b64a 100755 --- a/vector/src/main/java/im/vector/app/core/preference/PushRulePreference.kt +++ b/vector/src/main/java/im/vector/app/core/preference/PushRulePreference.kt @@ -22,6 +22,8 @@ import android.view.View import android.widget.RadioGroup import androidx.preference.PreferenceViewHolder import im.vector.app.R +import org.matrix.android.sdk.api.pushrules.Action +import org.matrix.android.sdk.api.pushrules.RuleIds import org.matrix.android.sdk.api.pushrules.RuleSetKey import org.matrix.android.sdk.api.pushrules.rest.PushRule import org.matrix.android.sdk.api.pushrules.rest.PushRuleAndKind @@ -51,7 +53,7 @@ class PushRulePreference : VectorPreference { get() { val safeRule = ruleAndKind?.pushRule ?: return NOTIFICATION_OFF_INDEX - if (safeRule.ruleId == PushRule.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) { + if (safeRule.ruleId == RuleIds.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) { if (safeRule.shouldNotNotify()) { return if (safeRule.enabled) { NOTIFICATION_OFF_INDEX @@ -108,7 +110,7 @@ class PushRulePreference : VectorPreference { val safeKind = ruleAndKind?.kind ?: return null return if (index != ruleStatusIndex) { - if (safeRule.ruleId == PushRule.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) { + if (safeRule.ruleId == RuleIds.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) { when (index) { NOTIFICATION_OFF_INDEX -> { safeRule.copy(enabled = true) @@ -128,7 +130,7 @@ class PushRulePreference : VectorPreference { } } else { if (NOTIFICATION_OFF_INDEX == index) { - if (safeKind == RuleSetKey.UNDERRIDE || safeRule.ruleId == PushRule.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) { + if (safeKind == RuleSetKey.UNDERRIDE || safeRule.ruleId == RuleIds.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) { safeRule.setNotify(false) } else { safeRule.copy(enabled = false) @@ -137,15 +139,15 @@ class PushRulePreference : VectorPreference { val newRule = safeRule.copy(enabled = true) .setNotify(true) .setHighlight(safeKind != RuleSetKey.UNDERRIDE - && safeRule.ruleId != PushRule.RULE_ID_INVITE_ME + && safeRule.ruleId != RuleIds.RULE_ID_INVITE_ME && NOTIFICATION_NOISY_INDEX == index) if (NOTIFICATION_NOISY_INDEX == index) { newRule.setNotificationSound( - if (safeRule.ruleId == PushRule.RULE_ID_CALL) { - PushRule.ACTION_VALUE_RING + if (safeRule.ruleId == RuleIds.RULE_ID_CALL) { + Action.ACTION_OBJECT_VALUE_VALUE_RING } else { - PushRule.ACTION_VALUE_DEFAULT + Action.ACTION_OBJECT_VALUE_VALUE_DEFAULT } ) } else { diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt index 27160ba234..67b5c03638 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt @@ -16,13 +16,13 @@ package im.vector.app.features.settings import androidx.preference.Preference -import org.matrix.android.sdk.api.MatrixCallback -import org.matrix.android.sdk.api.pushrules.rest.PushRule -import org.matrix.android.sdk.api.pushrules.rest.PushRuleAndKind import im.vector.app.R import im.vector.app.core.preference.PushRulePreference import im.vector.app.core.preference.VectorPreference import im.vector.app.core.utils.toast +import org.matrix.android.sdk.api.MatrixCallback +import org.matrix.android.sdk.api.pushrules.RuleIds +import org.matrix.android.sdk.api.pushrules.rest.PushRuleAndKind import javax.inject.Inject class VectorSettingsAdvancedNotificationPreferenceFragment @Inject constructor() @@ -92,17 +92,17 @@ class VectorSettingsAdvancedNotificationPreferenceFragment @Inject constructor() companion object { // preference name <-> rule Id private val prefKeyToPushRuleId = mapOf( - "SETTINGS_PUSH_RULE_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY" to PushRule.RULE_ID_CONTAIN_DISPLAY_NAME, - "SETTINGS_PUSH_RULE_CONTAINING_MY_USER_NAME_PREFERENCE_KEY" to PushRule.RULE_ID_CONTAIN_USER_NAME, - "SETTINGS_PUSH_RULE_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY" to PushRule.RULE_ID_ONE_TO_ONE_ROOM, - "SETTINGS_PUSH_RULE_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY" to PushRule.RULE_ID_ALL_OTHER_MESSAGES_ROOMS, - "SETTINGS_PUSH_RULE_INVITED_TO_ROOM_PREFERENCE_KEY" to PushRule.RULE_ID_INVITE_ME, - "SETTINGS_PUSH_RULE_CALL_INVITATIONS_PREFERENCE_KEY" to PushRule.RULE_ID_CALL, - "SETTINGS_PUSH_RULE_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY" to PushRule.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS, - "SETTINGS_PUSH_RULE_MESSAGES_CONTAINING_AT_ROOM_PREFERENCE_KEY" to PushRule.RULE_ID_AT_ROOMS, - "SETTINGS_PUSH_RULE_MESSAGES_IN_E2E_ONE_ONE_CHAT_PREFERENCE_KEY" to PushRule.RULE_ID_E2E_ONE_TO_ONE_ROOM, - "SETTINGS_PUSH_RULE_MESSAGES_IN_E2E_GROUP_CHAT_PREFERENCE_KEY" to PushRule.RULE_ID_E2E_GROUP, - "SETTINGS_PUSH_RULE_ROOMS_UPGRADED_KEY" to PushRule.RULE_ID_TOMBSTONE + "SETTINGS_PUSH_RULE_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY" to RuleIds.RULE_ID_CONTAIN_DISPLAY_NAME, + "SETTINGS_PUSH_RULE_CONTAINING_MY_USER_NAME_PREFERENCE_KEY" to RuleIds.RULE_ID_CONTAIN_USER_NAME, + "SETTINGS_PUSH_RULE_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY" to RuleIds.RULE_ID_ONE_TO_ONE_ROOM, + "SETTINGS_PUSH_RULE_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY" to RuleIds.RULE_ID_ALL_OTHER_MESSAGES_ROOMS, + "SETTINGS_PUSH_RULE_INVITED_TO_ROOM_PREFERENCE_KEY" to RuleIds.RULE_ID_INVITE_ME, + "SETTINGS_PUSH_RULE_CALL_INVITATIONS_PREFERENCE_KEY" to RuleIds.RULE_ID_CALL, + "SETTINGS_PUSH_RULE_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY" to RuleIds.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS, + "SETTINGS_PUSH_RULE_MESSAGES_CONTAINING_AT_ROOM_PREFERENCE_KEY" to RuleIds.RULE_ID_ROOM_NOTIF, + "SETTINGS_PUSH_RULE_MESSAGES_IN_E2E_ONE_ONE_CHAT_PREFERENCE_KEY" to RuleIds.RULE_ID_ONE_TO_ONE_ENCRYPTED_ROOM, + "SETTINGS_PUSH_RULE_MESSAGES_IN_E2E_GROUP_CHAT_PREFERENCE_KEY" to RuleIds.RULE_ID_ENCRYPTED, + "SETTINGS_PUSH_RULE_ROOMS_UPGRADED_KEY" to RuleIds.RULE_ID_TOMBSTONE ) } } diff --git a/vector/src/main/java/im/vector/app/features/settings/push/PushRuleItem.kt b/vector/src/main/java/im/vector/app/features/settings/push/PushRuleItem.kt index 9799b32c38..0144b162e9 100644 --- a/vector/src/main/java/im/vector/app/features/settings/push/PushRuleItem.kt +++ b/vector/src/main/java/im/vector/app/features/settings/push/PushRuleItem.kt @@ -26,11 +26,11 @@ import androidx.core.view.isVisible import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import com.airbnb.epoxy.EpoxyModelWithHolder -import org.matrix.android.sdk.api.pushrules.getActions -import org.matrix.android.sdk.api.pushrules.rest.PushRule import im.vector.app.R import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.features.notifications.toNotificationAction +import org.matrix.android.sdk.api.pushrules.getActions +import org.matrix.android.sdk.api.pushrules.rest.PushRule @EpoxyModelClass(layout = R.layout.item_pushrule_raw) abstract class PushRuleItem : EpoxyModelWithHolder() { @@ -68,7 +68,7 @@ abstract class PushRuleItem : EpoxyModelWithHolder() { val description = StringBuffer() pushRule.conditions?.forEachIndexed { i, condition -> if (i > 0) description.append("\n") - description.append(condition.asExecutableCondition()?.technicalDescription() + description.append(condition.asExecutableCondition(pushRule)?.technicalDescription() ?: "UNSUPPORTED") } if (description.isBlank()) {