From 558e11a3643c52ff8b4977f4427d9ebebfe7da3e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 25 Aug 2020 16:01:34 +0200 Subject: [PATCH 01/11] Refactor: move Kind to its own file --- .../android/sdk/api/pushrules/Condition.kt | 21 ---------- .../matrix/android/sdk/api/pushrules/Kind.kt | 39 +++++++++++++++++++ .../sdk/api/pushrules/rest/PushCondition.kt | 13 ++++--- .../database/mapper/PushRulesMapper.kt | 10 ++--- .../room/notification/RoomPushRuleMapper.kt | 4 +- 5 files changed, 53 insertions(+), 34 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Kind.kt 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..462807cb06 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 @@ -20,27 +20,6 @@ import org.matrix.android.sdk.api.session.events.model.Event abstract class Condition(val kind: Kind) { - 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 { 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/rest/PushCondition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushCondition.kt index 9469da3ea5..e16c1df314 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,6 +21,7 @@ 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.SenderNotificationPermissionCondition import timber.log.Timber @@ -59,8 +60,8 @@ data class PushCondition( ) { fun asExecutableCondition(): Condition? { - return when (Condition.Kind.fromString(kind)) { - Condition.Kind.EventMatch -> { + return when (Kind.fromString(kind)) { + Kind.EventMatch -> { if (key != null && pattern != null) { EventMatchCondition(key, pattern) } else { @@ -68,10 +69,10 @@ data class PushCondition( 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 +80,7 @@ data class PushCondition( RoomMemberCountCondition(iz) } } - Condition.Kind.SenderNotificationPermission -> { + Kind.SenderNotificationPermission -> { if (key == null) { Timber.e("Malformed Sender Notification Permission condition") null @@ -87,7 +88,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/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/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 ) From 7b5c74f81cd717839cfc2012d920919285b1516d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 25 Aug 2020 16:06:26 +0200 Subject: [PATCH 02/11] Refactor: Condition is now an interface --- .../org/matrix/android/sdk/api/pushrules/Condition.kt | 9 +++------ .../sdk/api/pushrules/ContainsDisplayNameCondition.kt | 6 ++---- .../android/sdk/api/pushrules/EventMatchCondition.kt | 6 ++---- .../sdk/api/pushrules/RoomMemberCountCondition.kt | 6 ++---- .../pushrules/SenderNotificationPermissionCondition.kt | 6 ++---- 5 files changed, 11 insertions(+), 22 deletions(-) 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 462807cb06..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,11 +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 - 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..2d0f81e5ca 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 @@ -22,15 +22,13 @@ 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 -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) { 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..5646f5e805 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 @@ -30,15 +30,13 @@ class EventMatchCondition( * be treated as having asterisks prepended and appended when testing the condition. */ val pattern: String -) : Condition(Kind.EventMatch) { +) : 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'" fun isSatisfied(event: Event): Boolean { // TODO encrypted events? 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/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) From f5ea4fb6ac44f993eb49bced2d29cd3851e6ff65 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 25 Aug 2020 16:15:42 +0200 Subject: [PATCH 03/11] Refactor: Extract method to dedicated files --- .../pushrules/ContainsDisplayNameCondition.kt | 29 +------------- .../sdk/api/pushrules/EventMatchCondition.kt | 27 ++----------- .../matrix/android/sdk/internal/util/Glob.kt | 38 +++++++++++++++++++ .../android/sdk/internal/util/StringUtils.kt | 22 +++++++++++ 4 files changed, 65 insertions(+), 51 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Glob.kt 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 2d0f81e5ca..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,7 +20,7 @@ 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 { @@ -43,31 +43,6 @@ class ContainsDisplayNameCondition : Condition { 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 5646f5e805..a6e3836a7a 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,8 @@ 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.hasSpecialGlobChar +import org.matrix.android.sdk.internal.util.simpleGlobToRegExp import timber.log.Timber class EventMatchCondition( @@ -47,7 +49,7 @@ 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 modPattern = if (pattern.hasSpecialGlobChar()) pattern.simpleGlobToRegExp() else "*$pattern*".simpleGlobToRegExp() val regex = Regex(modPattern, RegexOption.DOT_MATCHES_ALL) return regex.containsMatchIn(value) } catch (e: Throwable) { @@ -76,27 +78,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/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..fb8a5367dd --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Glob.kt @@ -0,0 +1,38 @@ +/* + * 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 { + var out = "" // "^" + for (element in this) { + 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/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 +} From aca8fd7f3d80fde7784ee9086400599ef1003f91 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 25 Aug 2020 16:18:44 +0200 Subject: [PATCH 04/11] Refactor: Kotlin style --- .../matrix/android/sdk/internal/util/Glob.kt | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) 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 index fb8a5367dd..129bf0dec4 100644 --- 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 @@ -23,16 +23,18 @@ internal fun String.hasSpecialGlobChar(): Boolean { // Very simple glob to regexp converter internal fun String.simpleGlobToRegExp(): String { - var out = "" // "^" - for (element in this) { - when (element) { - '*' -> out += ".*" - '?' -> out += '.'.toString() - '.' -> out += "\\." - '\\' -> out += "\\\\" - else -> out += element + val string = this + return buildString { + // append("^") + string.forEach { char -> + when (char) { + '*' -> append(".*") + '?' -> append(".") + '.' -> append("\\.") + '\\' -> append("\\\\") + else -> append(char) + } } + // append("$") } - out += "" // '$'.toString() - return out } From 0d9885a1e077705c0621f287cf408474a08e7490 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 25 Aug 2020 16:53:12 +0200 Subject: [PATCH 05/11] Refactor: Remove duplicated declaration for RuleIds --- .../android/sdk/api/pushrules/RuleIds.kt | 2 ++ .../sdk/api/pushrules/rest/PushRule.kt | 19 ------------- .../android/sdk/api/pushrules/rest/RuleSet.kt | 3 +- .../app/core/preference/PushRulePreference.kt | 11 ++++---- ...sAdvancedNotificationPreferenceFragment.kt | 28 +++++++++---------- 5 files changed, 24 insertions(+), 39 deletions(-) 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/rest/PushRule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushRule.kt index 46d73a8aa2..24a16ba655 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 @@ -136,25 +136,6 @@ data class PushRule( 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 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/vector/src/main/java/im/vector/app/core/preference/PushRulePreference.kt b/vector/src/main/java/im/vector/app/core/preference/PushRulePreference.kt index 87584a9db0..c19a7e4def 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 @@ -23,6 +23,7 @@ import android.widget.RadioGroup import android.widget.TextView import androidx.preference.PreferenceViewHolder import im.vector.app.R +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 @@ -52,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 @@ -109,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) @@ -129,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) @@ -138,12 +139,12 @@ 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) { + if (safeRule.ruleId == RuleIds.RULE_ID_CALL) { PushRule.ACTION_VALUE_RING } else { PushRule.ACTION_VALUE_DEFAULT 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 ) } } From bf7a096a187af7721694b57be954fac8b66c97ef Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 25 Aug 2020 17:01:55 +0200 Subject: [PATCH 06/11] Refactor: Remove duplicated declaration for Actions --- .../android/sdk/api/pushrules/Action.kt | 65 ++++++++++--------- .../sdk/api/pushrules/rest/PushRule.kt | 34 ++-------- .../fcm/VectorFirebaseMessagingService.kt | 8 +-- .../app/core/preference/PushRulePreference.kt | 5 +- 4 files changed, 48 insertions(+), 64 deletions(-) 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/rest/PushRule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushRule.kt index 24a16ba655..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,32 +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 { - - /* ========================================================================================== - * 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/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 c19a7e4def..0c9721e589 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 @@ -23,6 +23,7 @@ import android.widget.RadioGroup import android.widget.TextView 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 @@ -145,9 +146,9 @@ class PushRulePreference : VectorPreference { if (NOTIFICATION_NOISY_INDEX == index) { newRule.setNotificationSound( if (safeRule.ruleId == RuleIds.RULE_ID_CALL) { - PushRule.ACTION_VALUE_RING + Action.ACTION_OBJECT_VALUE_VALUE_RING } else { - PushRule.ACTION_VALUE_DEFAULT + Action.ACTION_OBJECT_VALUE_VALUE_DEFAULT } ) } else { From 2e618999d9ff481c89920b69e23169c56efaf046 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 25 Aug 2020 17:26:16 +0200 Subject: [PATCH 07/11] Words containing my name should not trigger notifications (Fixes #1781) It adds a specific behavior for rule with id RuleIds.RULE_ID_CONTAIN_USER_NAME --- CHANGES.md | 1 + .../sdk/api/pushrules/EventMatchCondition.kt | 23 ++++++++---- .../sdk/api/pushrules/rest/PushCondition.kt | 5 ++- .../notification/ProcessEventForPushTask.kt | 2 +- .../api/pushrules/PushrulesConditionTest.kt | 37 +++++++++++++------ .../features/settings/push/PushRuleItem.kt | 6 +-- 6 files changed, 49 insertions(+), 25 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index d3a16c9b29..2ab1214b36 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) Translations 🗣: - 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 a6e3836a7a..c10d2fc1df 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,7 @@ 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 @@ -31,14 +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 + 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() = "'$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 (pattern.hasSpecialGlobChar()) pattern.simpleGlobToRegExp() else "*$pattern*".simpleGlobToRegExp() - 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 } } 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 e16c1df314..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 @@ -23,6 +23,7 @@ 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 @@ -59,11 +60,11 @@ data class PushCondition( val iz: String? = null ) { - fun asExecutableCondition(): Condition? { + 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 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/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 index be5aeaaf0f..e428c7ab22 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,12 +30,6 @@ 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 { @@ -39,7 +39,7 @@ class PushrulesConditionTest: MatrixTest { @Test fun test_eventmatch_type_condition() { - val condition = EventMatchCondition("type", "m.room.message") + val condition = EventMatchCondition("type", "m.room.message", false) val simpleTextEvent = Event( type = "m.room.message", @@ -65,7 +65,7 @@ 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", @@ -86,13 +86,13 @@ 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", @@ -115,7 +115,7 @@ class PushrulesConditionTest: MatrixTest { @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", @@ -126,9 +126,22 @@ class PushrulesConditionTest: MatrixTest { assert(condition.isSatisfied(simpleTextEvent)) } + @Test + fun test_eventmatch_words_only_condition() { + val condition = EventMatchCondition("content.body", "ben", true) + + val simpleTextEvent = Event( + type = "m.room.message", + eventId = "mx0", + content = MessageTextContent("m.text", "benoit").toContent(), + originServerTs = 0) + + assertFalse(condition.isSatisfied(simpleTextEvent)) + } + @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/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()) { From 8226f60fade4acfe67dae03697fbf09fb8fb87a8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 25 Aug 2020 17:31:51 +0200 Subject: [PATCH 08/11] Refactor test to avoid duplicated code --- .../api/pushrules/PushrulesConditionTest.kt | 57 +++++-------------- 1 file changed, 15 insertions(+), 42 deletions(-) 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 index e428c7ab22..c5bb9cdc8d 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 @@ -31,21 +31,25 @@ 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 -class PushrulesConditionTest: MatrixTest { +class PushrulesConditionTest : MatrixTest { /* ========================================================================================== * Test EventMatchCondition * ========================================================================================== */ + private fun createSimpleTextEvent(text: String): Event { + return Event( + type = "m.room.message", + eventId = "mx0", + content = MessageTextContent("m.text", text).toContent(), + originServerTs = 0) + } + @Test fun test_eventmatch_type_condition() { val condition = EventMatchCondition("type", "m.room.message", false) - val simpleTextEvent = Event( - type = "m.room.message", - eventId = "mx0", - content = MessageTextContent("m.text", "Yo wtf?").toContent(), - originServerTs = 0) + val simpleTextEvent = createSimpleTextEvent("Yo wtf?") val rm = RoomMemberContent( Membership.INVITE, @@ -67,11 +71,7 @@ class PushrulesConditionTest: MatrixTest { fun test_eventmatch_path_condition() { 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)) @@ -94,49 +94,22 @@ class PushrulesConditionTest: MatrixTest { fun test_eventmatch_cake_condition() { 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", false) - val simpleTextEvent = Event( - type = "m.room.message", - eventId = "mx0", - content = MessageTextContent("m.text", "How was the cakeisalie?").toContent(), - originServerTs = 0) - - assert(condition.isSatisfied(simpleTextEvent)) + assert(condition.isSatisfied(createSimpleTextEvent("How was the cakeisalie?"))) } @Test fun test_eventmatch_words_only_condition() { val condition = EventMatchCondition("content.body", "ben", true) - val simpleTextEvent = Event( - type = "m.room.message", - eventId = "mx0", - content = MessageTextContent("m.text", "benoit").toContent(), - originServerTs = 0) - - assertFalse(condition.isSatisfied(simpleTextEvent)) + assertFalse(condition.isSatisfied(createSimpleTextEvent("benoit"))) } @Test From 1a068ee191a398cdfe8bdbe2395c54197dcccc7e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 25 Aug 2020 17:34:02 +0200 Subject: [PATCH 09/11] Add more tests --- .../android/sdk/api/pushrules/PushrulesConditionTest.kt | 9 +++++++++ 1 file changed, 9 insertions(+) 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 index c5bb9cdc8d..08251062b5 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 @@ -110,6 +110,15 @@ class PushrulesConditionTest : MatrixTest { 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 From 5e0fc3e17f9c4296f86f0b5216ba35543797cb37 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 25 Aug 2020 17:34:43 +0200 Subject: [PATCH 10/11] Rename class --- .../{PushrulesConditionTest.kt => PushRulesConditionTest.kt} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/pushrules/{PushrulesConditionTest.kt => PushRulesConditionTest.kt} (99%) 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 99% 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 08251062b5..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 @@ -31,7 +31,7 @@ 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 -class PushrulesConditionTest : MatrixTest { +class PushRulesConditionTest : MatrixTest { /* ========================================================================================== * Test EventMatchCondition From 6376ba2516744777ff7d8d4a5dc8fd5e1034f79e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 25 Aug 2020 17:48:12 +0200 Subject: [PATCH 11/11] Improve wording (visible in debug screen) --- .../org/matrix/android/sdk/api/pushrules/EventMatchCondition.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 c10d2fc1df..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 @@ -43,7 +43,7 @@ class EventMatchCondition( return conditionResolver.resolveEventMatchCondition(event, this) } - override fun technicalDescription() = "'$key' Matches '$pattern', words only '$wordsOnly'" + override fun technicalDescription() = "'$key' matches '$pattern', words only '$wordsOnly'" fun isSatisfied(event: Event): Boolean { // TODO encrypted events?