From d6f1f276c2f0f3624c9182407a094f531b714c3a Mon Sep 17 00:00:00 2001
From: langleyd <davidl@element.io>
Date: Mon, 12 Jul 2021 14:07:27 +0100
Subject: [PATCH 01/21] Add checkbox preference, remove PushRulePreference,
 Split adavanced fragment to new 3 new fragments and inherit common function

---
 .../im/vector/app/core/di/FragmentModule.kt   |   9 +-
 .../preference/VectorCheckboxPreference.kt    |  92 +++++++++++
 ...sAdvancedNotificationPreferenceFragment.kt | 105 ------------
 ...ngsGlobalNotificationPreferenceFragment.kt |  38 +++++
 ...dMentionsNotificationPreferenceFragment.kt |  36 +++++
 ...ingsOtherNotificationPreferenceFragment.kt |  37 +++++
 ...PushRuleNotificationPreferenceFragment.kt} | 150 +++++++++---------
 .../layout/vector_preference_push_rule.xml    |  79 ---------
 vector/src/main/res/values/strings.xml        |   6 +
 ...ings_notification_advanced_preferences.xml |  67 --------
 .../vector_settings_notification_global.xml   |  28 ++++
 ...ngs_notification_mentions_and_keywords.xml |  23 +++
 .../vector_settings_notification_other.xml    |  27 ++++
 .../res/xml/vector_settings_notifications.xml |  21 ++-
 14 files changed, 383 insertions(+), 335 deletions(-)
 create mode 100644 vector/src/main/java/im/vector/app/core/preference/VectorCheckboxPreference.kt
 delete mode 100644 vector/src/main/java/im/vector/app/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt
 create mode 100644 vector/src/main/java/im/vector/app/features/settings/VectorSettingsGlobalNotificationPreferenceFragment.kt
 create mode 100644 vector/src/main/java/im/vector/app/features/settings/VectorSettingsKeywordAndMentionsNotificationPreferenceFragment.kt
 create mode 100644 vector/src/main/java/im/vector/app/features/settings/VectorSettingsOtherNotificationPreferenceFragment.kt
 rename vector/src/main/java/im/vector/app/{core/preference/PushRulePreference.kt => features/settings/VectorSettingsPushRuleNotificationPreferenceFragment.kt} (56%)
 mode change 100755 => 100644
 delete mode 100644 vector/src/main/res/layout/vector_preference_push_rule.xml
 delete mode 100644 vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml
 create mode 100644 vector/src/main/res/xml/vector_settings_notification_global.xml
 create mode 100644 vector/src/main/res/xml/vector_settings_notification_mentions_and_keywords.xml
 create mode 100644 vector/src/main/res/xml/vector_settings_notification_other.xml

diff --git a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
index 8580543022..77e7e7ad72 100644
--- a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
+++ b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
@@ -111,7 +111,6 @@ import im.vector.app.features.roomprofile.settings.RoomSettingsFragment
 import im.vector.app.features.roomprofile.uploads.RoomUploadsFragment
 import im.vector.app.features.roomprofile.uploads.files.RoomUploadsFilesFragment
 import im.vector.app.features.roomprofile.uploads.media.RoomUploadsMediaFragment
-import im.vector.app.features.settings.VectorSettingsAdvancedNotificationPreferenceFragment
 import im.vector.app.features.settings.VectorSettingsGeneralFragment
 import im.vector.app.features.settings.VectorSettingsHelpAboutFragment
 import im.vector.app.features.settings.VectorSettingsLabsFragment
@@ -390,10 +389,10 @@ interface FragmentModule {
     @FragmentKey(VectorSettingsNotificationsTroubleshootFragment::class)
     fun bindVectorSettingsNotificationsTroubleshootFragment(fragment: VectorSettingsNotificationsTroubleshootFragment): Fragment
 
-    @Binds
-    @IntoMap
-    @FragmentKey(VectorSettingsAdvancedNotificationPreferenceFragment::class)
-    fun bindVectorSettingsAdvancedNotificationPreferenceFragment(fragment: VectorSettingsAdvancedNotificationPreferenceFragment): Fragment
+//    @Binds
+//    @IntoMap
+//    @FragmentKey(VectorSettingsAdvancedNotificationPreferenceFragment::class)
+//    fun bindVectorSettingsAdvancedNotificationPreferenceFragment(fragment: VectorSettingsAdvancedNotificationPreferenceFragment): Fragment
 
     @Binds
     @IntoMap
diff --git a/vector/src/main/java/im/vector/app/core/preference/VectorCheckboxPreference.kt b/vector/src/main/java/im/vector/app/core/preference/VectorCheckboxPreference.kt
new file mode 100644
index 0000000000..fd7a2ef5c5
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/preference/VectorCheckboxPreference.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2021 New Vector Ltd
+ *
+ * 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 im.vector.app.core.preference
+
+import android.animation.Animator
+import android.animation.ArgbEvaluator
+import android.animation.ValueAnimator
+import android.content.Context
+import android.graphics.Color
+import android.util.AttributeSet
+import android.widget.TextView
+import androidx.core.animation.doOnEnd
+import androidx.preference.CheckBoxPreference
+import androidx.preference.PreferenceViewHolder
+import im.vector.app.R
+import im.vector.app.features.themes.ThemeUtils
+
+open class VectorCheckboxPreference : CheckBoxPreference {
+    // Note: @JvmOverload does not work here...
+    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
+
+    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
+
+    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
+
+    constructor(context: Context) : super(context)
+
+    init {
+        // Set to false to remove the space when there is no icon
+        isIconSpaceReserved = true
+    }
+
+    var isHighlighted = false
+        set(value) {
+            field = value
+            notifyChanged()
+        }
+
+    var currentHighlightAnimator: Animator? = null
+
+    override fun onBindViewHolder(holder: PreferenceViewHolder) {
+        // display the title in multi-line to avoid ellipsis.
+        (holder.findViewById(android.R.id.title) as? TextView)?.isSingleLine = false
+
+        // cancel existing animation (find a way to resume if happens during anim?)
+        currentHighlightAnimator?.cancel()
+
+        val itemView = holder.itemView
+        if (isHighlighted) {
+            val colorFrom = Color.TRANSPARENT
+            val colorTo = ThemeUtils.getColor(itemView.context, R.attr.colorControlHighlight)
+            currentHighlightAnimator = ValueAnimator.ofObject(ArgbEvaluator(), colorFrom, colorTo).apply {
+                duration = 250 // milliseconds
+                addUpdateListener { animator ->
+                    itemView.setBackgroundColor(animator.animatedValue as Int)
+                }
+                doOnEnd {
+                    currentHighlightAnimator = ValueAnimator.ofObject(ArgbEvaluator(), colorTo, colorFrom).apply {
+                        duration = 250 // milliseconds
+                        addUpdateListener { animator ->
+                            itemView.setBackgroundColor(animator.animatedValue as Int)
+                        }
+                        doOnEnd {
+                            isHighlighted = false
+                        }
+                        start()
+                    }
+                }
+                startDelay = 200
+                start()
+            }
+        } else {
+            itemView.setBackgroundColor(Color.TRANSPARENT)
+        }
+
+        super.onBindViewHolder(holder)
+    }
+}
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
deleted file mode 100644
index 8d9f8d7170..0000000000
--- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 2018 New Vector Ltd
- *
- * 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 im.vector.app.features.settings
-
-import androidx.lifecycle.lifecycleScope
-import androidx.preference.Preference
-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 kotlinx.coroutines.launch
-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()
-    : VectorSettingsBaseFragment() {
-
-    override var titleRes: Int = R.string.settings_notification_advanced
-
-    override val preferenceXmlRes = R.xml.vector_settings_notification_advanced_preferences
-
-    override fun bindPref() {
-        for (preferenceKey in prefKeyToPushRuleId.keys) {
-            val preference = findPreference<VectorPreference>(preferenceKey)
-            if (preference is PushRulePreference) {
-                // preference.isEnabled = null != rules && isConnected && pushManager.areDeviceNotificationsAllowed()
-                val ruleAndKind: PushRuleAndKind? = session.getPushRules().findDefaultRule(prefKeyToPushRuleId[preferenceKey])
-
-                if (ruleAndKind == null) {
-                    // The rule is not defined, hide the preference
-                    preference.isVisible = false
-                } else {
-                    preference.isVisible = true
-                    preference.setPushRule(ruleAndKind)
-                    preference.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
-                        val newRule = preference.createNewRule(newValue as Int)
-                        if (newRule != null) {
-                            displayLoadingView()
-
-                            lifecycleScope.launch {
-                                val result = runCatching {
-                                    session.updatePushRuleActions(ruleAndKind.kind,
-                                            preference.ruleAndKind?.pushRule ?: ruleAndKind.pushRule,
-                                            newRule)
-                                }
-                                if (!isAdded) {
-                                    return@launch
-                                }
-                                hideLoadingView()
-                                result.onSuccess {
-                                    preference.setPushRule(ruleAndKind.copy(pushRule = newRule))
-                                }
-                                result.onFailure { failure ->
-                                    // Restore the previous value
-                                    refreshDisplay()
-                                    activity?.toast(errorFormatter.toHumanReadable(failure))
-                                }
-                            }
-                        }
-                        false
-                    }
-                }
-            }
-        }
-    }
-
-    private fun refreshDisplay() {
-        listView?.adapter?.notifyDataSetChanged()
-    }
-
-    /* ==========================================================================================
-     * Companion
-     * ========================================================================================== */
-
-    companion object {
-        //  preference name <-> rule Id
-        private val prefKeyToPushRuleId = mapOf(
-                "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/VectorSettingsGlobalNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGlobalNotificationPreferenceFragment.kt
new file mode 100644
index 0000000000..a91b3c5ef7
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGlobalNotificationPreferenceFragment.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021 New Vector Ltd
+ *
+ * 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 im.vector.app.features.settings
+
+import im.vector.app.R
+import org.matrix.android.sdk.api.pushrules.RuleIds
+import javax.inject.Inject
+
+class VectorSettingsGlobalNotificationPreferenceFragment @Inject constructor()
+    : VectorSettingsPushRuleNotificationPreferenceFragment() {
+
+    override var titleRes: Int = R.string.settings_notification_global
+
+    override val preferenceXmlRes = R.xml.vector_settings_notification_global
+
+    override val prefKeyToPushRuleId: Map<String, String>
+        get() = mapOf(
+                "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_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
+        )
+}
+
diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsKeywordAndMentionsNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsKeywordAndMentionsNotificationPreferenceFragment.kt
new file mode 100644
index 0000000000..0c7ed23070
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsKeywordAndMentionsNotificationPreferenceFragment.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021 New Vector Ltd
+ *
+ * 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 im.vector.app.features.settings
+
+import im.vector.app.R
+import org.matrix.android.sdk.api.pushrules.RuleIds
+import javax.inject.Inject
+
+class VectorSettingsKeywordAndMentionsNotificationPreferenceFragment @Inject constructor()
+    : VectorSettingsPushRuleNotificationPreferenceFragment() {
+
+    override var titleRes: Int = R.string.settings_notification_mentions_and_keywords
+
+    override val preferenceXmlRes = R.xml.vector_settings_notification_mentions_and_keywords
+
+    override val prefKeyToPushRuleId: Map<String, String>
+        get() = mapOf(
+                "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_CONTAINING_AT_ROOM_PREFERENCE_KEY" to RuleIds.RULE_ID_ROOM_NOTIF
+        )
+}
diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsOtherNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsOtherNotificationPreferenceFragment.kt
new file mode 100644
index 0000000000..bf58ab27a1
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsOtherNotificationPreferenceFragment.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 New Vector Ltd
+ *
+ * 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 im.vector.app.features.settings
+
+import im.vector.app.R
+import org.matrix.android.sdk.api.pushrules.RuleIds
+import javax.inject.Inject
+
+class VectorSettingsOtherNotificationPreferenceFragment @Inject constructor()
+    : VectorSettingsPushRuleNotificationPreferenceFragment() {
+
+    override var titleRes: Int = R.string.settings_notification_other
+
+    override val preferenceXmlRes = R.xml.vector_settings_notification_other
+
+    override val prefKeyToPushRuleId: Map<String, String>
+        get() = mapOf(
+                "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_ROOMS_UPGRADED_KEY" to RuleIds.RULE_ID_TOMBSTONE
+        )
+}
diff --git a/vector/src/main/java/im/vector/app/core/preference/PushRulePreference.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPushRuleNotificationPreferenceFragment.kt
old mode 100755
new mode 100644
similarity index 56%
rename from vector/src/main/java/im/vector/app/core/preference/PushRulePreference.kt
rename to vector/src/main/java/im/vector/app/features/settings/VectorSettingsPushRuleNotificationPreferenceFragment.kt
index c3e324b64a..2f274ce904
--- a/vector/src/main/java/im/vector/app/core/preference/PushRulePreference.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPushRuleNotificationPreferenceFragment.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018 New Vector Ltd
+ * Copyright (c) 2021 New Vector Ltd
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,43 +14,39 @@
  * limitations under the License.
  */
 
-package im.vector.app.core.preference
+package im.vector.app.features.settings
 
-import android.content.Context
-import android.util.AttributeSet
-import android.view.View
-import android.widget.RadioGroup
-import androidx.preference.PreferenceViewHolder
-import im.vector.app.R
+import androidx.lifecycle.lifecycleScope
+import androidx.preference.Preference
+import im.vector.app.core.preference.VectorCheckboxPreference
+import im.vector.app.core.utils.toast
+import kotlinx.coroutines.launch
 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
 
-class PushRulePreference : VectorPreference {
+abstract class VectorSettingsPushRuleNotificationPreferenceFragment
+    : VectorSettingsBaseFragment() {
 
-    /**
-     * @return the selected push rule and its kind
-     */
-    var ruleAndKind: PushRuleAndKind? = null
-        private set
 
-    constructor(context: Context) : super(context)
+    fun indexFromBooleanPreference(pushRuleOn: Boolean): Int {
+        return if (pushRuleOn) {
+            NOTIFICATION_NOISY_INDEX
+        } else {
+            NOTIFICATION_OFF_INDEX
+        }
+    }
 
-    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
-
-    constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle)
-
-    init {
-        layoutResource = R.layout.vector_preference_push_rule
+    fun booleanPreferenceFromIndex(index: Int): Boolean {
+        return index != NOTIFICATION_OFF_INDEX
     }
 
     /**
      * @return the bing rule status index
      */
-    private val ruleStatusIndex: Int
-        get() {
+    fun ruleStatusIndexFor(ruleAndKind: PushRuleAndKind? ): Int {
             val safeRule = ruleAndKind?.pushRule ?: return NOTIFICATION_OFF_INDEX
 
             if (safeRule.ruleId == RuleIds.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) {
@@ -78,36 +74,16 @@ class PushRulePreference : VectorPreference {
             return NOTIFICATION_OFF_INDEX
         }
 
-    /**
-     * Update the push rule.
-     *
-     * @param pushRule
-     */
-    fun setPushRule(pushRuleAndKind: PushRuleAndKind?) {
-        ruleAndKind = pushRuleAndKind
-        refreshSummary()
-    }
-
-    /**
-     * Refresh the summary
-     */
-    private fun refreshSummary() {
-        summary = context.getString(when (ruleStatusIndex) {
-            NOTIFICATION_OFF_INDEX    -> R.string.notification_off
-            NOTIFICATION_SILENT_INDEX -> R.string.notification_silent
-            else                      -> R.string.notification_noisy
-        })
-    }
-
     /**
      * Create a push rule with the updated required at index.
      *
      * @param index index
      * @return a push rule with the updated flags / null if there is no update
      */
-    fun createNewRule(index: Int): PushRule? {
+    fun createNewRule(ruleAndKind: PushRuleAndKind?, index: Int): PushRule? {
         val safeRule = ruleAndKind?.pushRule ?: return null
-        val safeKind = ruleAndKind?.kind ?: return null
+        val safeKind = ruleAndKind.kind
+        val ruleStatusIndex = ruleStatusIndexFor(ruleAndKind)
 
         return if (index != ruleStatusIndex) {
             if (safeRule.ruleId == RuleIds.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) {
@@ -126,7 +102,7 @@ class PushRulePreference : VectorPreference {
                                 .setNotify(true)
                                 .setNotificationSound()
                     }
-                    else                      -> safeRule
+                    else                                         -> safeRule
                 }
             } else {
                 if (NOTIFICATION_OFF_INDEX == index) {
@@ -160,43 +136,67 @@ class PushRulePreference : VectorPreference {
         }
     }
 
-    override fun onBindViewHolder(holder: PreferenceViewHolder) {
-        super.onBindViewHolder(holder)
 
-        holder.findViewById(android.R.id.summary)?.visibility = View.GONE
-        holder.itemView.setOnClickListener(null)
-        holder.itemView.setOnLongClickListener(null)
+    override fun bindPref() {
+        for (preferenceKey in prefKeyToPushRuleId.keys) {
+            val preference = findPreference<VectorCheckboxPreference>(preferenceKey)!!
+            // preference.isEnabled = null != rules && isConnected && pushManager.areDeviceNotificationsAllowed()
+            val ruleAndKind: PushRuleAndKind? = session.getPushRules().findDefaultRule(prefKeyToPushRuleId[preferenceKey])
 
-        val radioGroup = holder.findViewById(R.id.bingPreferenceRadioGroup) as? RadioGroup
-        radioGroup?.setOnCheckedChangeListener(null)
+            if (ruleAndKind == null) {
+                // The rule is not defined, hide the preference
+                preference.isVisible = false
+            } else {
+                preference.isVisible = true
 
-        when (ruleStatusIndex) {
-            NOTIFICATION_OFF_INDEX    -> {
-                radioGroup?.check(R.id.bingPreferenceRadioBingRuleOff)
-            }
-            NOTIFICATION_SILENT_INDEX -> {
-                radioGroup?.check(R.id.bingPreferenceRadioBingRuleSilent)
-            }
-            else                      -> {
-                radioGroup?.check(R.id.bingPreferenceRadioBingRuleNoisy)
-            }
-        }
+                val index = ruleStatusIndexFor(ruleAndKind)
+                val boolPreference = booleanPreferenceFromIndex(index)
+                preference.isChecked = boolPreference
+                preference.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
+                    val newIndex = indexFromBooleanPreference(newValue as Boolean)
+                    val newRule = createNewRule(ruleAndKind, newIndex)
 
-        radioGroup?.setOnCheckedChangeListener { _, checkedId ->
-            when (checkedId) {
-                R.id.bingPreferenceRadioBingRuleOff    -> {
-                    onPreferenceChangeListener?.onPreferenceChange(this, NOTIFICATION_OFF_INDEX)
-                }
-                R.id.bingPreferenceRadioBingRuleSilent -> {
-                    onPreferenceChangeListener?.onPreferenceChange(this, NOTIFICATION_SILENT_INDEX)
-                }
-                R.id.bingPreferenceRadioBingRuleNoisy  -> {
-                    onPreferenceChangeListener?.onPreferenceChange(this, NOTIFICATION_NOISY_INDEX)
+                    if (newRule != null) {
+                        displayLoadingView()
+
+                        lifecycleScope.launch {
+                            val result = runCatching {
+                                session.updatePushRuleActions(
+                                        ruleAndKind.kind,
+                                        ruleAndKind.pushRule,
+                                        newRule
+                                )
+                            }
+                            if (!isAdded) {
+                                return@launch
+                            }
+                            hideLoadingView()
+                            result.onSuccess {
+                                preference.isChecked = newValue
+                            }
+                            result.onFailure { failure ->
+                                // Restore the previous value
+                                refreshDisplay()
+                                activity?.toast(errorFormatter.toHumanReadable(failure))
+                            }
+                        }
+                    }
+                    false
                 }
             }
         }
     }
 
+    private fun refreshDisplay() {
+        listView?.adapter?.notifyDataSetChanged()
+    }
+
+    /* ==========================================================================================
+     * Companion
+     * ========================================================================================== */
+
+    abstract val prefKeyToPushRuleId: Map<String, String>
+
     companion object {
 
         // index in mRuleStatuses
diff --git a/vector/src/main/res/layout/vector_preference_push_rule.xml b/vector/src/main/res/layout/vector_preference_push_rule.xml
deleted file mode 100644
index 5242bfdf85..0000000000
--- a/vector/src/main/res/layout/vector_preference_push_rule.xml
+++ /dev/null
@@ -1,79 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:background="?android:attr/selectableItemBackground"
-    android:baselineAligned="false"
-    android:clipToPadding="false"
-    android:gravity="center_vertical"
-    android:minHeight="?android:attr/listPreferredItemHeightSmall"
-    android:orientation="vertical"
-    android:paddingStart="?android:attr/listPreferredItemPaddingLeft"
-    android:paddingEnd="?android:attr/listPreferredItemPaddingRight">
-
-    <RelativeLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:paddingTop="16dp">
-
-        <TextView
-            android:id="@android:id/title"
-            style="@style/Widget.Vector.TextView.Body"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:ellipsize="marquee"
-            android:singleLine="true"
-            android:textAppearance="?textAppearanceListItem"
-            android:textColor="?vctr_content_primary"
-            tools:text="Title" />
-
-        <TextView
-            android:id="@android:id/summary"
-            style="@style/Widget.Vector.TextView.Body"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_below="@android:id/title"
-            android:layout_alignStart="@android:id/title"
-            android:maxLines="2"
-            android:paddingTop="6dp"
-            android:textAppearance="?textAppearanceListItemSecondary"
-            android:textColor="?vctr_content_secondary"
-            tools:text="Summary"
-            tools:visibility="visible" />
-
-    </RelativeLayout>
-
-    <RadioGroup
-        android:id="@+id/bingPreferenceRadioGroup"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center_vertical|end"
-        android:orientation="horizontal"
-        android:paddingTop="6dp"
-        android:paddingBottom="16dp">
-
-        <RadioButton
-            android:id="@+id/bingPreferenceRadioBingRuleOff"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="@string/notification_off"
-            tools:checked="true" />
-
-        <RadioButton
-            android:id="@+id/bingPreferenceRadioBingRuleSilent"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="@string/notification_silent" />
-
-        <RadioButton
-            android:id="@+id/bingPreferenceRadioBingRuleNoisy"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="@string/notification_noisy" />
-
-    </RadioGroup>
-
-</LinearLayout>
-
-
diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml
index 0159c98c20..154d5619b4 100644
--- a/vector/src/main/res/values/strings.xml
+++ b/vector/src/main/res/values/strings.xml
@@ -1075,6 +1075,12 @@
     <string name="settings_notification_advanced">Advanced Notification Settings</string>
     <string name="settings_notification_by_event">Notification importance by event</string>
 
+    <string name="settings_notification_global">Global Notifications</string>
+    <string name="settings_notification_mentions_and_keywords">Mentions and Keywords</string>
+    <string name="settings_notification_other">Other</string>
+
+    <string name="settings_notification_notify_me_for">Notify me for</string>
+
     <string name="settings_notification_privacy">Notification privacy</string>
     <string name="settings_notification_troubleshoot">Troubleshoot Notifications</string>
     <string name="settings_troubleshoot_diagnostic">Troubleshooting diagnostics</string>
diff --git a/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml b/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml
deleted file mode 100644
index 4e9a9b07bf..0000000000
--- a/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <im.vector.app.core.preference.VectorPreferenceCategory
-        android:key="SETTINGS_NOTIFICATION_LEVEL"
-        android:title="@string/settings_notification_by_event">
-
-        <im.vector.app.core.preference.PushRulePreference
-            android:key="SETTINGS_PUSH_RULE_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY"
-            android:persistent="false"
-            android:title="@string/settings_containing_my_display_name" />
-
-        <im.vector.app.core.preference.PushRulePreference
-            android:key="SETTINGS_PUSH_RULE_CONTAINING_MY_USER_NAME_PREFERENCE_KEY"
-            android:persistent="false"
-            android:title="@string/settings_containing_my_user_name" />
-
-        <im.vector.app.core.preference.PushRulePreference
-            android:key="SETTINGS_PUSH_RULE_MESSAGES_CONTAINING_AT_ROOM_PREFERENCE_KEY"
-            android:persistent="false"
-            android:title="@string/settings_messages_at_room" />
-
-        <!-- TODO Support message with keywords rule -->
-
-        <im.vector.app.core.preference.PushRulePreference
-            android:key="SETTINGS_PUSH_RULE_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY"
-            android:persistent="false"
-            android:title="@string/settings_messages_in_one_to_one" />
-
-        <im.vector.app.core.preference.PushRulePreference
-            android:key="SETTINGS_PUSH_RULE_MESSAGES_IN_E2E_ONE_ONE_CHAT_PREFERENCE_KEY"
-            android:persistent="false"
-            android:title="@string/settings_messages_in_e2e_one_to_one" />
-
-        <im.vector.app.core.preference.PushRulePreference
-            android:key="SETTINGS_PUSH_RULE_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY"
-            android:persistent="false"
-            android:title="@string/settings_messages_in_group_chat" />
-
-        <im.vector.app.core.preference.PushRulePreference
-            android:key="SETTINGS_PUSH_RULE_MESSAGES_IN_E2E_GROUP_CHAT_PREFERENCE_KEY"
-            android:persistent="false"
-            android:title="@string/settings_messages_in_e2e_group_chat" />
-
-        <im.vector.app.core.preference.PushRulePreference
-            android:key="SETTINGS_PUSH_RULE_INVITED_TO_ROOM_PREFERENCE_KEY"
-            android:persistent="false"
-            android:title="@string/settings_invited_to_room" />
-
-        <im.vector.app.core.preference.PushRulePreference
-            android:key="SETTINGS_PUSH_RULE_CALL_INVITATIONS_PREFERENCE_KEY"
-            android:persistent="false"
-            android:title="@string/settings_call_invitations" />
-
-        <im.vector.app.core.preference.PushRulePreference
-            android:key="SETTINGS_PUSH_RULE_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY"
-            android:persistent="false"
-            android:title="@string/settings_messages_sent_by_bot" />
-
-        <im.vector.app.core.preference.PushRulePreference
-            android:key="SETTINGS_PUSH_RULE_ROOMS_UPGRADED_KEY"
-            android:persistent="false"
-            android:title="@string/settings_when_rooms_are_upgraded" />
-
-    </im.vector.app.core.preference.VectorPreferenceCategory>
-
-</androidx.preference.PreferenceScreen>
diff --git a/vector/src/main/res/xml/vector_settings_notification_global.xml b/vector/src/main/res/xml/vector_settings_notification_global.xml
new file mode 100644
index 0000000000..787419bd55
--- /dev/null
+++ b/vector/src/main/res/xml/vector_settings_notification_global.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+    <im.vector.app.core.preference.VectorPreferenceCategory
+        android:key="SETTINGS_OTHER"
+        android:title="@string/settings_notification_notify_me_for">
+
+        <im.vector.app.core.preference.VectorCheckboxPreference
+            android:key="SETTINGS_PUSH_RULE_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY"
+            android:persistent="false"
+            android:title="@string/settings_messages_in_one_to_one" />
+
+        <im.vector.app.core.preference.VectorCheckboxPreference
+            android:key="SETTINGS_PUSH_RULE_MESSAGES_IN_E2E_ONE_ONE_CHAT_PREFERENCE_KEY"
+            android:persistent="false"
+            android:title="@string/settings_messages_in_e2e_one_to_one" />
+
+        <im.vector.app.core.preference.VectorCheckboxPreference
+            android:key="SETTINGS_PUSH_RULE_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY"
+            android:persistent="false"
+            android:title="@string/settings_messages_in_group_chat" />
+
+        <im.vector.app.core.preference.VectorCheckboxPreference
+            android:key="SETTINGS_PUSH_RULE_MESSAGES_IN_E2E_GROUP_CHAT_PREFERENCE_KEY"
+            android:persistent="false"
+            android:title="@string/settings_messages_in_e2e_group_chat" />
+
+    </im.vector.app.core.preference.VectorPreferenceCategory>
+</PreferenceScreen>
\ No newline at end of file
diff --git a/vector/src/main/res/xml/vector_settings_notification_mentions_and_keywords.xml b/vector/src/main/res/xml/vector_settings_notification_mentions_and_keywords.xml
new file mode 100644
index 0000000000..c84bf53faa
--- /dev/null
+++ b/vector/src/main/res/xml/vector_settings_notification_mentions_and_keywords.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+    <im.vector.app.core.preference.VectorPreferenceCategory
+        android:key="SETTINGS_KEYWORDS_AND_MENTIONS"
+        android:title="@string/settings_notification_notify_me_for">
+
+        <im.vector.app.core.preference.VectorCheckboxPreference
+            android:key="SETTINGS_PUSH_RULE_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY"
+            android:persistent="false"
+            android:title="@string/settings_containing_my_display_name" />
+
+        <im.vector.app.core.preference.VectorCheckboxPreference
+            android:key="SETTINGS_PUSH_RULE_CONTAINING_MY_USER_NAME_PREFERENCE_KEY"
+            android:persistent="false"
+            android:title="@string/settings_containing_my_user_name" />
+
+        <im.vector.app.core.preference.VectorCheckboxPreference
+            android:key="SETTINGS_PUSH_RULE_MESSAGES_CONTAINING_AT_ROOM_PREFERENCE_KEY"
+            android:persistent="false"
+            android:title="@string/settings_messages_at_room" />
+
+    </im.vector.app.core.preference.VectorPreferenceCategory>
+</PreferenceScreen>
\ No newline at end of file
diff --git a/vector/src/main/res/xml/vector_settings_notification_other.xml b/vector/src/main/res/xml/vector_settings_notification_other.xml
new file mode 100644
index 0000000000..e1119e7c16
--- /dev/null
+++ b/vector/src/main/res/xml/vector_settings_notification_other.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+    <im.vector.app.core.preference.VectorPreferenceCategory
+        android:key="SETTINGS_OTHER"
+        android:title="@string/settings_notification_notify_me_for">
+
+        <im.vector.app.core.preference.VectorCheckboxPreference
+            android:key="SETTINGS_PUSH_RULE_INVITED_TO_ROOM_PREFERENCE_KEY"
+            android:persistent="false"
+            android:title="@string/settings_invited_to_room" />
+
+        <im.vector.app.core.preference.VectorCheckboxPreference
+            android:key="SETTINGS_PUSH_RULE_CALL_INVITATIONS_PREFERENCE_KEY"
+            android:persistent="false"
+            android:title="@string/settings_call_invitations" />
+
+        <im.vector.app.core.preference.VectorCheckboxPreference
+            android:key="SETTINGS_PUSH_RULE_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY"
+            android:persistent="false"
+            android:title="@string/settings_messages_sent_by_bot" />
+
+        <im.vector.app.core.preference.VectorCheckboxPreference
+            android:key="SETTINGS_PUSH_RULE_ROOMS_UPGRADED_KEY"
+            android:persistent="false"
+            android:title="@string/settings_when_rooms_are_upgraded" />
+    </im.vector.app.core.preference.VectorPreferenceCategory>
+</PreferenceScreen>
\ No newline at end of file
diff --git a/vector/src/main/res/xml/vector_settings_notifications.xml b/vector/src/main/res/xml/vector_settings_notifications.xml
index 983ddf36f2..35e21ca320 100644
--- a/vector/src/main/res/xml/vector_settings_notifications.xml
+++ b/vector/src/main/res/xml/vector_settings_notifications.xml
@@ -22,11 +22,24 @@
 
         <im.vector.app.core.preference.VectorPreference
             android:dependency="SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY"
-            android:key="SETTINGS_NOTIFICATION_ADVANCED_PREFERENCE_KEY"
+            android:key="SETTINGS_NOTIFICATION_GLOBAL_PREFERENCE_KEY"
             android:persistent="false"
-            android:summary="@string/settings_notification_advanced_summary"
-            android:title="@string/settings_notification_advanced"
-            app:fragment="im.vector.app.features.settings.VectorSettingsAdvancedNotificationPreferenceFragment" />
+            android:title="@string/settings_notification_global"
+            app:fragment="im.vector.app.features.settings.VectorSettingsGlobalNotificationPreferenceFragment" />
+
+<!--        <im.vector.app.core.preference.VectorPreference-->
+<!--            android:dependency="SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY"-->
+<!--            android:key="SETTINGS_NOTIFICATION_KEYWORD_AND_MENTIONS_PREFERENCE_KEY"-->
+<!--            android:persistent="false"-->
+<!--            android:title="@string/settings_notification_mentions_and_keywords"-->
+<!--            app:fragment="im.vector.app.features.settings.VectorSettingsKeywordAndMentionsNotificationPreferenceFragment" />-->
+
+<!--        <im.vector.app.core.preference.VectorPreference-->
+<!--            android:dependency="SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY"-->
+<!--            android:key="SETTINGS_NOTIFICATION_OTHER_PREFERENCE_KEY"-->
+<!--            android:persistent="false"-->
+<!--            android:title="@string/settings_notification_other"-->
+<!--            app:fragment="im.vector.app.features.settings.VectorSettingsOtherNotificationPreferenceFragment" />-->
 
     </im.vector.app.core.preference.VectorPreferenceCategory>
 

From 7e156d372f7c1573e66c41d6a02aa17cbdf6e876 Mon Sep 17 00:00:00 2001
From: langleyd <davidl@element.io>
Date: Mon, 12 Jul 2021 14:08:35 +0100
Subject: [PATCH 02/21] Add checkbox preference, remove PushRulePreference,
 Split adavanced fragment to new 3 new fragments and inherit common function

---
 .../im/vector/app/core/di/FragmentModule.kt   |  5 --
 .../preference/VectorCheckboxPreference.kt    | 47 -------------------
 ...ngsGlobalNotificationPreferenceFragment.kt |  3 +-
 ...dMentionsNotificationPreferenceFragment.kt |  4 +-
 ...ingsOtherNotificationPreferenceFragment.kt |  3 +-
 .../res/xml/vector_settings_notifications.xml | 24 +++++-----
 6 files changed, 16 insertions(+), 70 deletions(-)

diff --git a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
index 77e7e7ad72..7d50dbdcb5 100644
--- a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
+++ b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
@@ -389,11 +389,6 @@ interface FragmentModule {
     @FragmentKey(VectorSettingsNotificationsTroubleshootFragment::class)
     fun bindVectorSettingsNotificationsTroubleshootFragment(fragment: VectorSettingsNotificationsTroubleshootFragment): Fragment
 
-//    @Binds
-//    @IntoMap
-//    @FragmentKey(VectorSettingsAdvancedNotificationPreferenceFragment::class)
-//    fun bindVectorSettingsAdvancedNotificationPreferenceFragment(fragment: VectorSettingsAdvancedNotificationPreferenceFragment): Fragment
-
     @Binds
     @IntoMap
     @FragmentKey(VectorSettingsNotificationPreferenceFragment::class)
diff --git a/vector/src/main/java/im/vector/app/core/preference/VectorCheckboxPreference.kt b/vector/src/main/java/im/vector/app/core/preference/VectorCheckboxPreference.kt
index fd7a2ef5c5..b66ea77bdd 100644
--- a/vector/src/main/java/im/vector/app/core/preference/VectorCheckboxPreference.kt
+++ b/vector/src/main/java/im/vector/app/core/preference/VectorCheckboxPreference.kt
@@ -16,18 +16,11 @@
 
 package im.vector.app.core.preference
 
-import android.animation.Animator
-import android.animation.ArgbEvaluator
-import android.animation.ValueAnimator
 import android.content.Context
-import android.graphics.Color
 import android.util.AttributeSet
 import android.widget.TextView
-import androidx.core.animation.doOnEnd
 import androidx.preference.CheckBoxPreference
 import androidx.preference.PreferenceViewHolder
-import im.vector.app.R
-import im.vector.app.features.themes.ThemeUtils
 
 open class VectorCheckboxPreference : CheckBoxPreference {
     // Note: @JvmOverload does not work here...
@@ -44,49 +37,9 @@ open class VectorCheckboxPreference : CheckBoxPreference {
         isIconSpaceReserved = true
     }
 
-    var isHighlighted = false
-        set(value) {
-            field = value
-            notifyChanged()
-        }
-
-    var currentHighlightAnimator: Animator? = null
-
     override fun onBindViewHolder(holder: PreferenceViewHolder) {
         // display the title in multi-line to avoid ellipsis.
         (holder.findViewById(android.R.id.title) as? TextView)?.isSingleLine = false
-
-        // cancel existing animation (find a way to resume if happens during anim?)
-        currentHighlightAnimator?.cancel()
-
-        val itemView = holder.itemView
-        if (isHighlighted) {
-            val colorFrom = Color.TRANSPARENT
-            val colorTo = ThemeUtils.getColor(itemView.context, R.attr.colorControlHighlight)
-            currentHighlightAnimator = ValueAnimator.ofObject(ArgbEvaluator(), colorFrom, colorTo).apply {
-                duration = 250 // milliseconds
-                addUpdateListener { animator ->
-                    itemView.setBackgroundColor(animator.animatedValue as Int)
-                }
-                doOnEnd {
-                    currentHighlightAnimator = ValueAnimator.ofObject(ArgbEvaluator(), colorTo, colorFrom).apply {
-                        duration = 250 // milliseconds
-                        addUpdateListener { animator ->
-                            itemView.setBackgroundColor(animator.animatedValue as Int)
-                        }
-                        doOnEnd {
-                            isHighlighted = false
-                        }
-                        start()
-                    }
-                }
-                startDelay = 200
-                start()
-            }
-        } else {
-            itemView.setBackgroundColor(Color.TRANSPARENT)
-        }
-
         super.onBindViewHolder(holder)
     }
 }
diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGlobalNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGlobalNotificationPreferenceFragment.kt
index a91b3c5ef7..7e6f51f0b6 100644
--- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGlobalNotificationPreferenceFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGlobalNotificationPreferenceFragment.kt
@@ -18,9 +18,8 @@ package im.vector.app.features.settings
 
 import im.vector.app.R
 import org.matrix.android.sdk.api.pushrules.RuleIds
-import javax.inject.Inject
 
-class VectorSettingsGlobalNotificationPreferenceFragment @Inject constructor()
+class VectorSettingsGlobalNotificationPreferenceFragment
     : VectorSettingsPushRuleNotificationPreferenceFragment() {
 
     override var titleRes: Int = R.string.settings_notification_global
diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsKeywordAndMentionsNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsKeywordAndMentionsNotificationPreferenceFragment.kt
index 0c7ed23070..2bf0a7c0ed 100644
--- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsKeywordAndMentionsNotificationPreferenceFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsKeywordAndMentionsNotificationPreferenceFragment.kt
@@ -18,9 +18,9 @@ package im.vector.app.features.settings
 
 import im.vector.app.R
 import org.matrix.android.sdk.api.pushrules.RuleIds
-import javax.inject.Inject
 
-class VectorSettingsKeywordAndMentionsNotificationPreferenceFragment @Inject constructor()
+
+class VectorSettingsKeywordAndMentionsNotificationPreferenceFragment
     : VectorSettingsPushRuleNotificationPreferenceFragment() {
 
     override var titleRes: Int = R.string.settings_notification_mentions_and_keywords
diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsOtherNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsOtherNotificationPreferenceFragment.kt
index bf58ab27a1..64d5cda638 100644
--- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsOtherNotificationPreferenceFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsOtherNotificationPreferenceFragment.kt
@@ -18,9 +18,8 @@ package im.vector.app.features.settings
 
 import im.vector.app.R
 import org.matrix.android.sdk.api.pushrules.RuleIds
-import javax.inject.Inject
 
-class VectorSettingsOtherNotificationPreferenceFragment @Inject constructor()
+class VectorSettingsOtherNotificationPreferenceFragment
     : VectorSettingsPushRuleNotificationPreferenceFragment() {
 
     override var titleRes: Int = R.string.settings_notification_other
diff --git a/vector/src/main/res/xml/vector_settings_notifications.xml b/vector/src/main/res/xml/vector_settings_notifications.xml
index 35e21ca320..d19945cd46 100644
--- a/vector/src/main/res/xml/vector_settings_notifications.xml
+++ b/vector/src/main/res/xml/vector_settings_notifications.xml
@@ -27,19 +27,19 @@
             android:title="@string/settings_notification_global"
             app:fragment="im.vector.app.features.settings.VectorSettingsGlobalNotificationPreferenceFragment" />
 
-<!--        <im.vector.app.core.preference.VectorPreference-->
-<!--            android:dependency="SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY"-->
-<!--            android:key="SETTINGS_NOTIFICATION_KEYWORD_AND_MENTIONS_PREFERENCE_KEY"-->
-<!--            android:persistent="false"-->
-<!--            android:title="@string/settings_notification_mentions_and_keywords"-->
-<!--            app:fragment="im.vector.app.features.settings.VectorSettingsKeywordAndMentionsNotificationPreferenceFragment" />-->
+        <im.vector.app.core.preference.VectorPreference
+            android:dependency="SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY"
+            android:key="SETTINGS_NOTIFICATION_KEYWORD_AND_MENTIONS_PREFERENCE_KEY"
+            android:persistent="false"
+            android:title="@string/settings_notification_mentions_and_keywords"
+            app:fragment="im.vector.app.features.settings.VectorSettingsKeywordAndMentionsNotificationPreferenceFragment" />
 
-<!--        <im.vector.app.core.preference.VectorPreference-->
-<!--            android:dependency="SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY"-->
-<!--            android:key="SETTINGS_NOTIFICATION_OTHER_PREFERENCE_KEY"-->
-<!--            android:persistent="false"-->
-<!--            android:title="@string/settings_notification_other"-->
-<!--            app:fragment="im.vector.app.features.settings.VectorSettingsOtherNotificationPreferenceFragment" />-->
+        <im.vector.app.core.preference.VectorPreference
+            android:dependency="SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY"
+            android:key="SETTINGS_NOTIFICATION_OTHER_PREFERENCE_KEY"
+            android:persistent="false"
+            android:title="@string/settings_notification_other"
+            app:fragment="im.vector.app.features.settings.VectorSettingsOtherNotificationPreferenceFragment" />
 
     </im.vector.app.core.preference.VectorPreferenceCategory>
 

From 727ce7272a58d33efcce6375d8e726933758f4e4 Mon Sep 17 00:00:00 2001
From: David Langley <langley.dave@gmail.com>
Date: Mon, 12 Jul 2021 18:38:56 +0100
Subject: [PATCH 03/21] update translations

---
 .../troubleshoot/TestPushRulesSettings.kt     |  5 -----
 vector/src/main/res/values/strings.xml        | 20 +++++++++----------
 .../vector_settings_notification_global.xml   |  8 ++++----
 ...ngs_notification_mentions_and_keywords.xml |  4 ++--
 .../vector_settings_notification_other.xml    |  6 +++---
 5 files changed, 19 insertions(+), 24 deletions(-)

diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestPushRulesSettings.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestPushRulesSettings.kt
index 8dcf9ab6ce..eea5705b7a 100644
--- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestPushRulesSettings.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestPushRulesSettings.kt
@@ -35,11 +35,6 @@ class TestPushRulesSettings @Inject constructor(private val activeSessionHolder:
                     RuleIds.RULE_ID_ONE_TO_ONE_ROOM,
                     RuleIds.RULE_ID_ALL_OTHER_MESSAGES_ROOMS)
 
-    val ruleSettingsName = arrayOf(R.string.settings_containing_my_display_name,
-            R.string.settings_containing_my_user_name,
-            R.string.settings_messages_in_one_to_one,
-            R.string.settings_messages_in_group_chat)
-
     override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
         val session = activeSessionHolder.getSafeActiveSession() ?: return
         val pushRules = session.getPushRules().getAllRules()
diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml
index 154d5619b4..a80ed06186 100644
--- a/vector/src/main/res/values/strings.xml
+++ b/vector/src/main/res/values/strings.xml
@@ -1190,13 +1190,17 @@
     <string name="settings_system_preferences_summary">Choose LED color, vibration, sound…</string>
 
 
-    <string name="settings_containing_my_display_name">Msgs containing my display name</string>
-    <string name="settings_containing_my_user_name">Msgs containing my user name</string>
-    <string name="settings_messages_in_one_to_one">Msgs in one-to-one chats</string>
-    <string name="settings_messages_in_group_chat">Msgs in group chats</string>
-    <string name="settings_invited_to_room">When I’m invited to a room</string>
+    <string name="settings_messages_containing_display_name">Messages containing my display name</string>
+    <string name="settings_messages_containing_username">Messages containing my username</string>
+    <string name="settings_messages_direct_messages">Direct messages</string>
+    <string name="settings_encrypted_direct_messages">Encrypted direct messages</string>
+    <string name="settings_group_messages">Group messages</string>
+    <string name="settings_encrypted_group_messages">Encrypted group messages</string>
+    <string name="settings_messages_at_room">Messages containing @room</string>
+    <string name="settings_room_invitations">Room invitations</string>
     <string name="settings_call_invitations">Call invitations</string>
-    <string name="settings_messages_sent_by_bot">Messages sent by bot</string>
+    <string name="settings_messages_by_bot">Messages by bot</string>
+    <string name="settings_room_upgrades">Room upgrades</string>
 
     <string name="settings_background_sync">Background synchronization</string>
     <string name="settings_background_fdroid_sync_mode">Background Sync Mode</string>
@@ -2948,10 +2952,6 @@
     <string name="error_failed_to_import_keys">Failed to import keys</string>
 
     <string name="settings_notification_configuration">Notifications configuration</string>
-    <string name="settings_messages_at_room">Messages containing @room</string>
-    <string name="settings_messages_in_e2e_one_to_one">Encrypted messages in one-to-one chats</string>
-    <string name="settings_messages_in_e2e_group_chat">Encrypted messages in group chats</string>
-    <string name="settings_when_rooms_are_upgraded">When rooms are upgraded</string>
     <string name="settings_troubleshoot_title">Troubleshoot</string>
     <string name="settings_notification_advanced_summary">Set notification importance by event</string>
 
diff --git a/vector/src/main/res/xml/vector_settings_notification_global.xml b/vector/src/main/res/xml/vector_settings_notification_global.xml
index 787419bd55..70defb32c4 100644
--- a/vector/src/main/res/xml/vector_settings_notification_global.xml
+++ b/vector/src/main/res/xml/vector_settings_notification_global.xml
@@ -7,22 +7,22 @@
         <im.vector.app.core.preference.VectorCheckboxPreference
             android:key="SETTINGS_PUSH_RULE_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY"
             android:persistent="false"
-            android:title="@string/settings_messages_in_one_to_one" />
+            android:title="@string/settings_messages_direct_messages" />
 
         <im.vector.app.core.preference.VectorCheckboxPreference
             android:key="SETTINGS_PUSH_RULE_MESSAGES_IN_E2E_ONE_ONE_CHAT_PREFERENCE_KEY"
             android:persistent="false"
-            android:title="@string/settings_messages_in_e2e_one_to_one" />
+            android:title="@string/settings_encrypted_direct_messages" />
 
         <im.vector.app.core.preference.VectorCheckboxPreference
             android:key="SETTINGS_PUSH_RULE_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY"
             android:persistent="false"
-            android:title="@string/settings_messages_in_group_chat" />
+            android:title="@string/settings_group_messages" />
 
         <im.vector.app.core.preference.VectorCheckboxPreference
             android:key="SETTINGS_PUSH_RULE_MESSAGES_IN_E2E_GROUP_CHAT_PREFERENCE_KEY"
             android:persistent="false"
-            android:title="@string/settings_messages_in_e2e_group_chat" />
+            android:title="@string/settings_encrypted_group_messages" />
 
     </im.vector.app.core.preference.VectorPreferenceCategory>
 </PreferenceScreen>
\ No newline at end of file
diff --git a/vector/src/main/res/xml/vector_settings_notification_mentions_and_keywords.xml b/vector/src/main/res/xml/vector_settings_notification_mentions_and_keywords.xml
index c84bf53faa..18de36cb52 100644
--- a/vector/src/main/res/xml/vector_settings_notification_mentions_and_keywords.xml
+++ b/vector/src/main/res/xml/vector_settings_notification_mentions_and_keywords.xml
@@ -7,12 +7,12 @@
         <im.vector.app.core.preference.VectorCheckboxPreference
             android:key="SETTINGS_PUSH_RULE_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY"
             android:persistent="false"
-            android:title="@string/settings_containing_my_display_name" />
+            android:title="@string/settings_messages_containing_display_name" />
 
         <im.vector.app.core.preference.VectorCheckboxPreference
             android:key="SETTINGS_PUSH_RULE_CONTAINING_MY_USER_NAME_PREFERENCE_KEY"
             android:persistent="false"
-            android:title="@string/settings_containing_my_user_name" />
+            android:title="@string/settings_messages_containing_username" />
 
         <im.vector.app.core.preference.VectorCheckboxPreference
             android:key="SETTINGS_PUSH_RULE_MESSAGES_CONTAINING_AT_ROOM_PREFERENCE_KEY"
diff --git a/vector/src/main/res/xml/vector_settings_notification_other.xml b/vector/src/main/res/xml/vector_settings_notification_other.xml
index e1119e7c16..ad2b5194f0 100644
--- a/vector/src/main/res/xml/vector_settings_notification_other.xml
+++ b/vector/src/main/res/xml/vector_settings_notification_other.xml
@@ -7,7 +7,7 @@
         <im.vector.app.core.preference.VectorCheckboxPreference
             android:key="SETTINGS_PUSH_RULE_INVITED_TO_ROOM_PREFERENCE_KEY"
             android:persistent="false"
-            android:title="@string/settings_invited_to_room" />
+            android:title="@string/settings_room_invitations" />
 
         <im.vector.app.core.preference.VectorCheckboxPreference
             android:key="SETTINGS_PUSH_RULE_CALL_INVITATIONS_PREFERENCE_KEY"
@@ -17,11 +17,11 @@
         <im.vector.app.core.preference.VectorCheckboxPreference
             android:key="SETTINGS_PUSH_RULE_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY"
             android:persistent="false"
-            android:title="@string/settings_messages_sent_by_bot" />
+            android:title="@string/settings_messages_by_bot" />
 
         <im.vector.app.core.preference.VectorCheckboxPreference
             android:key="SETTINGS_PUSH_RULE_ROOMS_UPGRADED_KEY"
             android:persistent="false"
-            android:title="@string/settings_when_rooms_are_upgraded" />
+            android:title="@string/settings_room_upgrades" />
     </im.vector.app.core.preference.VectorPreferenceCategory>
 </PreferenceScreen>
\ No newline at end of file

From a3204fdad954650df2f6c00c4803cea2b7c1f88d Mon Sep 17 00:00:00 2001
From: David Langley <langley.dave@gmail.com>
Date: Tue, 13 Jul 2021 21:22:56 +0100
Subject: [PATCH 04/21] add resValue to enable feature, put back old code

---
 vector/build.gradle                           |   3 +
 .../im/vector/app/core/di/FragmentModule.kt   |   6 +
 .../app/core/preference/PushRulePreference.kt | 207 ++++++++++++++++++
 ...sAdvancedNotificationPreferenceFragment.kt | 105 +++++++++
 ...sPushRuleNotificationPreferenceFragment.kt | 181 +++++----------
 .../layout/vector_preference_push_rule.xml    |  78 +++++++
 vector/src/main/res/values/strings.xml        |   9 +
 ...ings_notification_advanced_preferences.xml |  67 ++++++
 .../res/xml/vector_settings_notifications.xml |  18 +-
 9 files changed, 548 insertions(+), 126 deletions(-)
 create mode 100644 vector/src/main/java/im/vector/app/core/preference/PushRulePreference.kt
 create mode 100644 vector/src/main/java/im/vector/app/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt
 create mode 100644 vector/src/main/res/layout/vector_preference_push_rule.xml
 create mode 100644 vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml

diff --git a/vector/build.gradle b/vector/build.gradle
index 8e8e5bc3dc..7003ab1834 100644
--- a/vector/build.gradle
+++ b/vector/build.gradle
@@ -142,6 +142,9 @@ android {
         resValue "bool", "useLoginV1", "true"
         resValue "bool", "useLoginV2", "false"
 
+        resValue "bool", "useNotificationSettingsV1", "true"
+        resValue "bool", "useNotificationSettingsV2", "false"
+
         buildConfigField "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy", "outboundSessionKeySharingStrategy", "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy.WhenTyping"
 
         //  If set, MSC3086 asserted identity messages sent on VoIP calls will cause the call to appear in the room corresponding to the asserted identity.
diff --git a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
index 7d50dbdcb5..7da26a3ea1 100644
--- a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
+++ b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
@@ -111,6 +111,7 @@ import im.vector.app.features.roomprofile.settings.RoomSettingsFragment
 import im.vector.app.features.roomprofile.uploads.RoomUploadsFragment
 import im.vector.app.features.roomprofile.uploads.files.RoomUploadsFilesFragment
 import im.vector.app.features.roomprofile.uploads.media.RoomUploadsMediaFragment
+import im.vector.app.features.settings.VectorSettingsAdvancedNotificationPreferenceFragment
 import im.vector.app.features.settings.VectorSettingsGeneralFragment
 import im.vector.app.features.settings.VectorSettingsHelpAboutFragment
 import im.vector.app.features.settings.VectorSettingsLabsFragment
@@ -384,6 +385,11 @@ interface FragmentModule {
     @FragmentKey(PushGatewaysFragment::class)
     fun bindPushGatewaysFragment(fragment: PushGatewaysFragment): Fragment
 
+    @Binds
+    @IntoMap
+    @FragmentKey(VectorSettingsAdvancedNotificationPreferenceFragment::class)
+    fun bindVectorSettingsAdvancedNotificationPreferenceFragment(fragment: VectorSettingsAdvancedNotificationPreferenceFragment): Fragment
+
     @Binds
     @IntoMap
     @FragmentKey(VectorSettingsNotificationsTroubleshootFragment::class)
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
new file mode 100644
index 0000000000..c3e324b64a
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/preference/PushRulePreference.kt
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2018 New Vector Ltd
+ *
+ * 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 im.vector.app.core.preference
+
+import android.content.Context
+import android.util.AttributeSet
+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
+
+class PushRulePreference : VectorPreference {
+
+    /**
+     * @return the selected push rule and its kind
+     */
+    var ruleAndKind: PushRuleAndKind? = null
+        private set
+
+    constructor(context: Context) : super(context)
+
+    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
+
+    constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle)
+
+    init {
+        layoutResource = R.layout.vector_preference_push_rule
+    }
+
+    /**
+     * @return the bing rule status index
+     */
+    private val ruleStatusIndex: Int
+        get() {
+            val safeRule = ruleAndKind?.pushRule ?: return NOTIFICATION_OFF_INDEX
+
+            if (safeRule.ruleId == RuleIds.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) {
+                if (safeRule.shouldNotNotify()) {
+                    return if (safeRule.enabled) {
+                        NOTIFICATION_OFF_INDEX
+                    } else {
+                        NOTIFICATION_SILENT_INDEX
+                    }
+                } else if (safeRule.shouldNotify()) {
+                    return NOTIFICATION_NOISY_INDEX
+                }
+            }
+
+            if (safeRule.enabled) {
+                return if (safeRule.shouldNotNotify()) {
+                    NOTIFICATION_OFF_INDEX
+                } else if (safeRule.getNotificationSound() != null) {
+                    NOTIFICATION_NOISY_INDEX
+                } else {
+                    NOTIFICATION_SILENT_INDEX
+                }
+            }
+
+            return NOTIFICATION_OFF_INDEX
+        }
+
+    /**
+     * Update the push rule.
+     *
+     * @param pushRule
+     */
+    fun setPushRule(pushRuleAndKind: PushRuleAndKind?) {
+        ruleAndKind = pushRuleAndKind
+        refreshSummary()
+    }
+
+    /**
+     * Refresh the summary
+     */
+    private fun refreshSummary() {
+        summary = context.getString(when (ruleStatusIndex) {
+            NOTIFICATION_OFF_INDEX    -> R.string.notification_off
+            NOTIFICATION_SILENT_INDEX -> R.string.notification_silent
+            else                      -> R.string.notification_noisy
+        })
+    }
+
+    /**
+     * Create a push rule with the updated required at index.
+     *
+     * @param index index
+     * @return a push rule with the updated flags / null if there is no update
+     */
+    fun createNewRule(index: Int): PushRule? {
+        val safeRule = ruleAndKind?.pushRule ?: return null
+        val safeKind = ruleAndKind?.kind ?: return null
+
+        return if (index != ruleStatusIndex) {
+            if (safeRule.ruleId == RuleIds.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) {
+                when (index) {
+                    NOTIFICATION_OFF_INDEX    -> {
+                        safeRule.copy(enabled = true)
+                                .setNotify(false)
+                                .removeNotificationSound()
+                    }
+                    NOTIFICATION_SILENT_INDEX -> {
+                        safeRule.copy(enabled = false)
+                                .setNotify(false)
+                    }
+                    NOTIFICATION_NOISY_INDEX  -> {
+                        safeRule.copy(enabled = true)
+                                .setNotify(true)
+                                .setNotificationSound()
+                    }
+                    else                      -> safeRule
+                }
+            } else {
+                if (NOTIFICATION_OFF_INDEX == index) {
+                    if (safeKind == RuleSetKey.UNDERRIDE || safeRule.ruleId == RuleIds.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) {
+                        safeRule.setNotify(false)
+                    } else {
+                        safeRule.copy(enabled = false)
+                    }
+                } else {
+                    val newRule = safeRule.copy(enabled = true)
+                            .setNotify(true)
+                            .setHighlight(safeKind != RuleSetKey.UNDERRIDE
+                                    && safeRule.ruleId != RuleIds.RULE_ID_INVITE_ME
+                                    && NOTIFICATION_NOISY_INDEX == index)
+
+                    if (NOTIFICATION_NOISY_INDEX == index) {
+                        newRule.setNotificationSound(
+                                if (safeRule.ruleId == RuleIds.RULE_ID_CALL) {
+                                    Action.ACTION_OBJECT_VALUE_VALUE_RING
+                                } else {
+                                    Action.ACTION_OBJECT_VALUE_VALUE_DEFAULT
+                                }
+                        )
+                    } else {
+                        newRule.removeNotificationSound()
+                    }
+                }
+            }
+        } else {
+            safeRule
+        }
+    }
+
+    override fun onBindViewHolder(holder: PreferenceViewHolder) {
+        super.onBindViewHolder(holder)
+
+        holder.findViewById(android.R.id.summary)?.visibility = View.GONE
+        holder.itemView.setOnClickListener(null)
+        holder.itemView.setOnLongClickListener(null)
+
+        val radioGroup = holder.findViewById(R.id.bingPreferenceRadioGroup) as? RadioGroup
+        radioGroup?.setOnCheckedChangeListener(null)
+
+        when (ruleStatusIndex) {
+            NOTIFICATION_OFF_INDEX    -> {
+                radioGroup?.check(R.id.bingPreferenceRadioBingRuleOff)
+            }
+            NOTIFICATION_SILENT_INDEX -> {
+                radioGroup?.check(R.id.bingPreferenceRadioBingRuleSilent)
+            }
+            else                      -> {
+                radioGroup?.check(R.id.bingPreferenceRadioBingRuleNoisy)
+            }
+        }
+
+        radioGroup?.setOnCheckedChangeListener { _, checkedId ->
+            when (checkedId) {
+                R.id.bingPreferenceRadioBingRuleOff    -> {
+                    onPreferenceChangeListener?.onPreferenceChange(this, NOTIFICATION_OFF_INDEX)
+                }
+                R.id.bingPreferenceRadioBingRuleSilent -> {
+                    onPreferenceChangeListener?.onPreferenceChange(this, NOTIFICATION_SILENT_INDEX)
+                }
+                R.id.bingPreferenceRadioBingRuleNoisy  -> {
+                    onPreferenceChangeListener?.onPreferenceChange(this, NOTIFICATION_NOISY_INDEX)
+                }
+            }
+        }
+    }
+
+    companion object {
+
+        // index in mRuleStatuses
+        private const val NOTIFICATION_OFF_INDEX = 0
+        private const val NOTIFICATION_SILENT_INDEX = 1
+        private const val NOTIFICATION_NOISY_INDEX = 2
+    }
+}
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
new file mode 100644
index 0000000000..8d9f8d7170
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2018 New Vector Ltd
+ *
+ * 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 im.vector.app.features.settings
+
+import androidx.lifecycle.lifecycleScope
+import androidx.preference.Preference
+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 kotlinx.coroutines.launch
+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()
+    : VectorSettingsBaseFragment() {
+
+    override var titleRes: Int = R.string.settings_notification_advanced
+
+    override val preferenceXmlRes = R.xml.vector_settings_notification_advanced_preferences
+
+    override fun bindPref() {
+        for (preferenceKey in prefKeyToPushRuleId.keys) {
+            val preference = findPreference<VectorPreference>(preferenceKey)
+            if (preference is PushRulePreference) {
+                // preference.isEnabled = null != rules && isConnected && pushManager.areDeviceNotificationsAllowed()
+                val ruleAndKind: PushRuleAndKind? = session.getPushRules().findDefaultRule(prefKeyToPushRuleId[preferenceKey])
+
+                if (ruleAndKind == null) {
+                    // The rule is not defined, hide the preference
+                    preference.isVisible = false
+                } else {
+                    preference.isVisible = true
+                    preference.setPushRule(ruleAndKind)
+                    preference.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
+                        val newRule = preference.createNewRule(newValue as Int)
+                        if (newRule != null) {
+                            displayLoadingView()
+
+                            lifecycleScope.launch {
+                                val result = runCatching {
+                                    session.updatePushRuleActions(ruleAndKind.kind,
+                                            preference.ruleAndKind?.pushRule ?: ruleAndKind.pushRule,
+                                            newRule)
+                                }
+                                if (!isAdded) {
+                                    return@launch
+                                }
+                                hideLoadingView()
+                                result.onSuccess {
+                                    preference.setPushRule(ruleAndKind.copy(pushRule = newRule))
+                                }
+                                result.onFailure { failure ->
+                                    // Restore the previous value
+                                    refreshDisplay()
+                                    activity?.toast(errorFormatter.toHumanReadable(failure))
+                                }
+                            }
+                        }
+                        false
+                    }
+                }
+            }
+        }
+    }
+
+    private fun refreshDisplay() {
+        listView?.adapter?.notifyDataSetChanged()
+    }
+
+    /* ==========================================================================================
+     * Companion
+     * ========================================================================================== */
+
+    companion object {
+        //  preference name <-> rule Id
+        private val prefKeyToPushRuleId = mapOf(
+                "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/VectorSettingsPushRuleNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPushRuleNotificationPreferenceFragment.kt
index 2f274ce904..6683cf3038 100644
--- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPushRuleNotificationPreferenceFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPushRuleNotificationPreferenceFragment.kt
@@ -30,105 +30,58 @@ import org.matrix.android.sdk.api.pushrules.rest.PushRuleAndKind
 abstract class VectorSettingsPushRuleNotificationPreferenceFragment
     : VectorSettingsBaseFragment() {
 
-
-    fun indexFromBooleanPreference(pushRuleOn: Boolean): Int {
-        return if (pushRuleOn) {
-            NOTIFICATION_NOISY_INDEX
-        } else {
-            NOTIFICATION_OFF_INDEX
-        }
-    }
-
-    fun booleanPreferenceFromIndex(index: Int): Boolean {
-        return index != NOTIFICATION_OFF_INDEX
-    }
-
     /**
-     * @return the bing rule status index
+     * @return the bing rule status boolean
      */
-    fun ruleStatusIndexFor(ruleAndKind: PushRuleAndKind? ): Int {
-            val safeRule = ruleAndKind?.pushRule ?: return NOTIFICATION_OFF_INDEX
-
-            if (safeRule.ruleId == RuleIds.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) {
-                if (safeRule.shouldNotNotify()) {
-                    return if (safeRule.enabled) {
-                        NOTIFICATION_OFF_INDEX
-                    } else {
-                        NOTIFICATION_SILENT_INDEX
-                    }
-                } else if (safeRule.shouldNotify()) {
-                    return NOTIFICATION_NOISY_INDEX
-                }
-            }
-
-            if (safeRule.enabled) {
-                return if (safeRule.shouldNotNotify()) {
-                    NOTIFICATION_OFF_INDEX
-                } else if (safeRule.getNotificationSound() != null) {
-                    NOTIFICATION_NOISY_INDEX
-                } else {
-                    NOTIFICATION_SILENT_INDEX
-                }
-            }
-
-            return NOTIFICATION_OFF_INDEX
+    fun ruleStatusIndexFor(ruleAndKind: PushRuleAndKind): Boolean {
+        val rule = ruleAndKind.pushRule
+        if (rule.ruleId == RuleIds.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) {
+            return rule.shouldNotify() || rule.shouldNotNotify() && !rule.enabled
         }
+        return rule.enabled && !rule.shouldNotNotify()
+    }
 
     /**
      * Create a push rule with the updated required at index.
      *
-     * @param index index
-     * @return a push rule with the updated flags / null if there is no update
+     * @param status boolean checkbox status
+     * @return a push rule with the updated flags
      */
-    fun createNewRule(ruleAndKind: PushRuleAndKind?, index: Int): PushRule? {
-        val safeRule = ruleAndKind?.pushRule ?: return null
+    fun createNewRule(ruleAndKind: PushRuleAndKind, status: Boolean): PushRule {
+        val safeRule = ruleAndKind.pushRule
         val safeKind = ruleAndKind.kind
         val ruleStatusIndex = ruleStatusIndexFor(ruleAndKind)
 
-        return if (index != ruleStatusIndex) {
+        return if (status != ruleStatusIndex) {
             if (safeRule.ruleId == RuleIds.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) {
-                when (index) {
-                    NOTIFICATION_OFF_INDEX    -> {
-                        safeRule.copy(enabled = true)
-                                .setNotify(false)
-                                .removeNotificationSound()
-                    }
-                    NOTIFICATION_SILENT_INDEX -> {
-                        safeRule.copy(enabled = false)
-                                .setNotify(false)
-                    }
-                    NOTIFICATION_NOISY_INDEX  -> {
-                        safeRule.copy(enabled = true)
-                                .setNotify(true)
-                                .setNotificationSound()
-                    }
-                    else                                         -> safeRule
+                if (status) {
+                    safeRule.copy(enabled = true)
+                            .setNotify(true)
+                            .setNotificationSound()
+                } else {
+                    safeRule.copy(enabled = true)
+                            .setNotify(false)
+                            .removeNotificationSound()
                 }
             } else {
-                if (NOTIFICATION_OFF_INDEX == index) {
+                if (status) {
+                    safeRule.copy(enabled = true)
+                            .setNotify(true)
+                            .setHighlight(safeKind != RuleSetKey.UNDERRIDE
+                                    && safeRule.ruleId != RuleIds.RULE_ID_INVITE_ME)
+                            .setNotificationSound(
+                                    if (safeRule.ruleId == RuleIds.RULE_ID_CALL) {
+                                        Action.ACTION_OBJECT_VALUE_VALUE_RING
+                                    } else {
+                                        Action.ACTION_OBJECT_VALUE_VALUE_DEFAULT
+                                    }
+                            )
+                } else {
                     if (safeKind == RuleSetKey.UNDERRIDE || safeRule.ruleId == RuleIds.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) {
                         safeRule.setNotify(false)
                     } else {
                         safeRule.copy(enabled = false)
                     }
-                } else {
-                    val newRule = safeRule.copy(enabled = true)
-                            .setNotify(true)
-                            .setHighlight(safeKind != RuleSetKey.UNDERRIDE
-                                    && safeRule.ruleId != RuleIds.RULE_ID_INVITE_ME
-                                    && NOTIFICATION_NOISY_INDEX == index)
-
-                    if (NOTIFICATION_NOISY_INDEX == index) {
-                        newRule.setNotificationSound(
-                                if (safeRule.ruleId == RuleIds.RULE_ID_CALL) {
-                                    Action.ACTION_OBJECT_VALUE_VALUE_RING
-                                } else {
-                                    Action.ACTION_OBJECT_VALUE_VALUE_DEFAULT
-                                }
-                        )
-                    } else {
-                        newRule.removeNotificationSound()
-                    }
                 }
             }
         } else {
@@ -136,51 +89,44 @@ abstract class VectorSettingsPushRuleNotificationPreferenceFragment
         }
     }
 
-
     override fun bindPref() {
         for (preferenceKey in prefKeyToPushRuleId.keys) {
             val preference = findPreference<VectorCheckboxPreference>(preferenceKey)!!
-            // preference.isEnabled = null != rules && isConnected && pushManager.areDeviceNotificationsAllowed()
             val ruleAndKind: PushRuleAndKind? = session.getPushRules().findDefaultRule(prefKeyToPushRuleId[preferenceKey])
-
             if (ruleAndKind == null) {
                 // The rule is not defined, hide the preference
                 preference.isVisible = false
             } else {
+                var oldRuleAndKind: PushRuleAndKind = ruleAndKind
                 preference.isVisible = true
-
-                val index = ruleStatusIndexFor(ruleAndKind)
-                val boolPreference = booleanPreferenceFromIndex(index)
-                preference.isChecked = boolPreference
+                preference.isChecked = ruleStatusIndexFor(ruleAndKind)
                 preference.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
-                    val newIndex = indexFromBooleanPreference(newValue as Boolean)
-                    val newRule = createNewRule(ruleAndKind, newIndex)
+                    val newRule = createNewRule(ruleAndKind, newValue as Boolean)
+                    displayLoadingView()
 
-                    if (newRule != null) {
-                        displayLoadingView()
-
-                        lifecycleScope.launch {
-                            val result = runCatching {
-                                session.updatePushRuleActions(
-                                        ruleAndKind.kind,
-                                        ruleAndKind.pushRule,
-                                        newRule
-                                )
-                            }
-                            if (!isAdded) {
-                                return@launch
-                            }
-                            hideLoadingView()
-                            result.onSuccess {
-                                preference.isChecked = newValue
-                            }
-                            result.onFailure { failure ->
-                                // Restore the previous value
-                                refreshDisplay()
-                                activity?.toast(errorFormatter.toHumanReadable(failure))
-                            }
+                    lifecycleScope.launch {
+                        val result = runCatching {
+                            session.updatePushRuleActions(
+                                    oldRuleAndKind.kind,
+                                    oldRuleAndKind.pushRule,
+                                    newRule
+                            )
+                        }
+                        if (!isAdded) {
+                            return@launch
+                        }
+                        hideLoadingView()
+                        result.onSuccess {
+                            oldRuleAndKind = oldRuleAndKind.copy(pushRule = newRule)
+                            preference.isChecked = newValue
+                        }
+                        result.onFailure { failure ->
+                            // Restore the previous value
+                            refreshDisplay()
+                            activity?.toast(errorFormatter.toHumanReadable(failure))
                         }
                     }
+
                     false
                 }
             }
@@ -191,17 +137,6 @@ abstract class VectorSettingsPushRuleNotificationPreferenceFragment
         listView?.adapter?.notifyDataSetChanged()
     }
 
-    /* ==========================================================================================
-     * Companion
-     * ========================================================================================== */
-
     abstract val prefKeyToPushRuleId: Map<String, String>
 
-    companion object {
-
-        // index in mRuleStatuses
-        private const val NOTIFICATION_OFF_INDEX = 0
-        private const val NOTIFICATION_SILENT_INDEX = 1
-        private const val NOTIFICATION_NOISY_INDEX = 2
-    }
 }
diff --git a/vector/src/main/res/layout/vector_preference_push_rule.xml b/vector/src/main/res/layout/vector_preference_push_rule.xml
new file mode 100644
index 0000000000..3da5c81410
--- /dev/null
+++ b/vector/src/main/res/layout/vector_preference_push_rule.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="?android:attr/selectableItemBackground"
+    android:baselineAligned="false"
+    android:clipToPadding="false"
+    android:gravity="center_vertical"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:orientation="vertical"
+    android:paddingStart="?android:attr/listPreferredItemPaddingLeft"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingRight">
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="16dp">
+
+        <TextView
+            android:id="@android:id/title"
+            style="@style/Widget.Vector.TextView.Body"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:ellipsize="marquee"
+            android:singleLine="true"
+            android:textAppearance="?textAppearanceListItem"
+            android:textColor="?vctr_content_primary"
+            tools:text="Title" />
+
+        <TextView
+            android:id="@android:id/summary"
+            style="@style/Widget.Vector.TextView.Body"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@android:id/title"
+            android:layout_alignStart="@android:id/title"
+            android:maxLines="2"
+            android:paddingTop="6dp"
+            android:textAppearance="?textAppearanceListItemSecondary"
+            android:textColor="?vctr_content_secondary"
+            tools:text="Summary"
+            tools:visibility="visible" />
+
+    </RelativeLayout>
+
+    <RadioGroup
+        android:id="@+id/bingPreferenceRadioGroup"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical|end"
+        android:orientation="horizontal"
+        android:paddingTop="6dp"
+        android:paddingBottom="16dp">
+
+        <RadioButton
+            android:id="@+id/bingPreferenceRadioBingRuleOff"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/notification_off"
+            tools:checked="true" />
+
+        <RadioButton
+            android:id="@+id/bingPreferenceRadioBingRuleSilent"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/notification_silent" />
+
+        <RadioButton
+            android:id="@+id/bingPreferenceRadioBingRuleNoisy"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/notification_noisy" />
+
+    </RadioGroup>
+
+</LinearLayout>
+
diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml
index a80ed06186..7f93cd3957 100644
--- a/vector/src/main/res/values/strings.xml
+++ b/vector/src/main/res/values/strings.xml
@@ -1189,6 +1189,15 @@
     <string name="settings_silent_notifications_preferences">Configure Silent Notifications</string>
     <string name="settings_system_preferences_summary">Choose LED color, vibration, sound…</string>
 
+    <string name="settings_messages_in_e2e_one_to_one">Encrypted messages in one-to-one chats</string>
+    <string name="settings_messages_in_e2e_group_chat">Encrypted messages in group chats</string>
+    <string name="settings_when_rooms_are_upgraded">When rooms are upgraded</string>
+    <string name="settings_containing_my_display_name">Msgs containing my display name</string>
+    <string name="settings_containing_my_user_name">Msgs containing my user name</string>
+    <string name="settings_messages_in_one_to_one">Msgs in one-to-one chats</string>
+    <string name="settings_messages_in_group_chat">Msgs in group chats</string>
+    <string name="settings_invited_to_room">When I’m invited to a room</string>
+    <string name="settings_messages_sent_by_bot">Messages sent by bot</string>
 
     <string name="settings_messages_containing_display_name">Messages containing my display name</string>
     <string name="settings_messages_containing_username">Messages containing my username</string>
diff --git a/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml b/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml
new file mode 100644
index 0000000000..436858ac05
--- /dev/null
+++ b/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <im.vector.app.core.preference.VectorPreferenceCategory
+        android:key="SETTINGS_NOTIFICATION_LEVEL"
+        android:title="@string/settings_notification_by_event">
+
+        <im.vector.app.core.preference.PushRulePreference
+            android:key="SETTINGS_PUSH_RULE_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY"
+            android:persistent="false"
+            android:title="@string/settings_containing_my_display_name" />
+
+        <im.vector.app.core.preference.PushRulePreference
+            android:key="SETTINGS_PUSH_RULE_CONTAINING_MY_USER_NAME_PREFERENCE_KEY"
+            android:persistent="false"
+            android:title="@string/settings_containing_my_user_name" />
+
+        <im.vector.app.core.preference.PushRulePreference
+            android:key="SETTINGS_PUSH_RULE_MESSAGES_CONTAINING_AT_ROOM_PREFERENCE_KEY"
+            android:persistent="false"
+            android:title="@string/settings_messages_at_room" />
+
+        <!-- TODO Support message with keywords rule -->
+
+        <im.vector.app.core.preference.PushRulePreference
+            android:key="SETTINGS_PUSH_RULE_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY"
+            android:persistent="false"
+            android:title="@string/settings_messages_in_one_to_one" />
+
+        <im.vector.app.core.preference.PushRulePreference
+            android:key="SETTINGS_PUSH_RULE_MESSAGES_IN_E2E_ONE_ONE_CHAT_PREFERENCE_KEY"
+            android:persistent="false"
+            android:title="@string/settings_messages_in_e2e_one_to_one" />
+
+        <im.vector.app.core.preference.PushRulePreference
+            android:key="SETTINGS_PUSH_RULE_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY"
+            android:persistent="false"
+            android:title="@string/settings_messages_in_group_chat" />
+
+        <im.vector.app.core.preference.PushRulePreference
+            android:key="SETTINGS_PUSH_RULE_MESSAGES_IN_E2E_GROUP_CHAT_PREFERENCE_KEY"
+            android:persistent="false"
+            android:title="@string/settings_messages_in_e2e_group_chat" />
+
+        <im.vector.app.core.preference.PushRulePreference
+            android:key="SETTINGS_PUSH_RULE_INVITED_TO_ROOM_PREFERENCE_KEY"
+            android:persistent="false"
+            android:title="@string/settings_invited_to_room" />
+
+        <im.vector.app.core.preference.PushRulePreference
+            android:key="SETTINGS_PUSH_RULE_CALL_INVITATIONS_PREFERENCE_KEY"
+            android:persistent="false"
+            android:title="@string/settings_call_invitations" />
+
+        <im.vector.app.core.preference.PushRulePreference
+            android:key="SETTINGS_PUSH_RULE_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY"
+            android:persistent="false"
+            android:title="@string/settings_messages_sent_by_bot" />
+
+        <im.vector.app.core.preference.PushRulePreference
+            android:key="SETTINGS_PUSH_RULE_ROOMS_UPGRADED_KEY"
+            android:persistent="false"
+            android:title="@string/settings_when_rooms_are_upgraded" />
+
+    </im.vector.app.core.preference.VectorPreferenceCategory>
+
+</androidx.preference.PreferenceScreen>
\ No newline at end of file
diff --git a/vector/src/main/res/xml/vector_settings_notifications.xml b/vector/src/main/res/xml/vector_settings_notifications.xml
index d19945cd46..c9668bcd4d 100644
--- a/vector/src/main/res/xml/vector_settings_notifications.xml
+++ b/vector/src/main/res/xml/vector_settings_notifications.xml
@@ -20,26 +20,38 @@
         <!--android:key="SETTINGS_TURN_SCREEN_ON_PREFERENCE_KEY"-->
         <!--android:title="@string/settings_turn_screen_on" />-->
 
+        <im.vector.app.core.preference.VectorPreference
+            android:dependency="SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY"
+            android:key="SETTINGS_NOTIFICATION_ADVANCED_PREFERENCE_KEY"
+            android:persistent="false"
+            android:summary="@string/settings_notification_advanced_summary"
+            android:title="@string/settings_notification_advanced"
+            app:fragment="im.vector.app.features.settings.VectorSettingsAdvancedNotificationPreferenceFragment"
+            app:isPreferenceVisible="@bool/useNotificationSettingsV1" />
+
         <im.vector.app.core.preference.VectorPreference
             android:dependency="SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY"
             android:key="SETTINGS_NOTIFICATION_GLOBAL_PREFERENCE_KEY"
             android:persistent="false"
             android:title="@string/settings_notification_global"
-            app:fragment="im.vector.app.features.settings.VectorSettingsGlobalNotificationPreferenceFragment" />
+            app:fragment="im.vector.app.features.settings.VectorSettingsGlobalNotificationPreferenceFragment"
+            app:isPreferenceVisible="@bool/useNotificationSettingsV2"/>
 
         <im.vector.app.core.preference.VectorPreference
             android:dependency="SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY"
             android:key="SETTINGS_NOTIFICATION_KEYWORD_AND_MENTIONS_PREFERENCE_KEY"
             android:persistent="false"
             android:title="@string/settings_notification_mentions_and_keywords"
-            app:fragment="im.vector.app.features.settings.VectorSettingsKeywordAndMentionsNotificationPreferenceFragment" />
+            app:fragment="im.vector.app.features.settings.VectorSettingsKeywordAndMentionsNotificationPreferenceFragment"
+            app:isPreferenceVisible="@bool/useNotificationSettingsV2"/>
 
         <im.vector.app.core.preference.VectorPreference
             android:dependency="SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY"
             android:key="SETTINGS_NOTIFICATION_OTHER_PREFERENCE_KEY"
             android:persistent="false"
             android:title="@string/settings_notification_other"
-            app:fragment="im.vector.app.features.settings.VectorSettingsOtherNotificationPreferenceFragment" />
+            app:fragment="im.vector.app.features.settings.VectorSettingsOtherNotificationPreferenceFragment"
+            app:isPreferenceVisible="@bool/useNotificationSettingsV2"/>
 
     </im.vector.app.core.preference.VectorPreferenceCategory>
 

From 5044b21545fe0588f5d269f7740dc67d0db36d13 Mon Sep 17 00:00:00 2001
From: David Langley <langley.dave@gmail.com>
Date: Wed, 14 Jul 2021 11:49:16 +0100
Subject: [PATCH 05/21] add changelog, checks/tests

---
 changelog.d/3646.feature                                      | 1 +
 vector/build.gradle                                           | 1 +
 .../VectorSettingsGlobalNotificationPreferenceFragment.kt     | 1 -
 ...ettingsKeywordAndMentionsNotificationPreferenceFragment.kt | 1 -
 .../VectorSettingsPushRuleNotificationPreferenceFragment.kt   | 1 -
 .../src/main/res/xml/vector_settings_notification_global.xml  | 4 ++--
 .../vector_settings_notification_mentions_and_keywords.xml    | 4 ++--
 .../src/main/res/xml/vector_settings_notification_other.xml   | 4 ++--
 8 files changed, 8 insertions(+), 9 deletions(-)
 create mode 100644 changelog.d/3646.feature

diff --git a/changelog.d/3646.feature b/changelog.d/3646.feature
new file mode 100644
index 0000000000..ba2e870052
--- /dev/null
+++ b/changelog.d/3646.feature
@@ -0,0 +1 @@
+Reorganise Advanced Notifications in to Global Notifications, Keywords and Mentions, Other (This feature is hidden in the release ui until a future release date.)
\ No newline at end of file
diff --git a/vector/build.gradle b/vector/build.gradle
index eaf70e50b1..dabdcfb4dc 100644
--- a/vector/build.gradle
+++ b/vector/build.gradle
@@ -142,6 +142,7 @@ android {
         resValue "bool", "useLoginV1", "true"
         resValue "bool", "useLoginV2", "false"
 
+        // NotificationSettingsV2 is disabled. To be released in conjunction with iOS/Web
         resValue "bool", "useNotificationSettingsV1", "true"
         resValue "bool", "useNotificationSettingsV2", "false"
 
diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGlobalNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGlobalNotificationPreferenceFragment.kt
index 7e6f51f0b6..b9ac089158 100644
--- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGlobalNotificationPreferenceFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGlobalNotificationPreferenceFragment.kt
@@ -34,4 +34,3 @@ class VectorSettingsGlobalNotificationPreferenceFragment
                 "SETTINGS_PUSH_RULE_MESSAGES_IN_E2E_GROUP_CHAT_PREFERENCE_KEY" to RuleIds.RULE_ID_ENCRYPTED
         )
 }
-
diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsKeywordAndMentionsNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsKeywordAndMentionsNotificationPreferenceFragment.kt
index 2bf0a7c0ed..b2a1d26fc8 100644
--- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsKeywordAndMentionsNotificationPreferenceFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsKeywordAndMentionsNotificationPreferenceFragment.kt
@@ -19,7 +19,6 @@ package im.vector.app.features.settings
 import im.vector.app.R
 import org.matrix.android.sdk.api.pushrules.RuleIds
 
-
 class VectorSettingsKeywordAndMentionsNotificationPreferenceFragment
     : VectorSettingsPushRuleNotificationPreferenceFragment() {
 
diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPushRuleNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPushRuleNotificationPreferenceFragment.kt
index 6683cf3038..705d90a8c9 100644
--- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPushRuleNotificationPreferenceFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPushRuleNotificationPreferenceFragment.kt
@@ -138,5 +138,4 @@ abstract class VectorSettingsPushRuleNotificationPreferenceFragment
     }
 
     abstract val prefKeyToPushRuleId: Map<String, String>
-
 }
diff --git a/vector/src/main/res/xml/vector_settings_notification_global.xml b/vector/src/main/res/xml/vector_settings_notification_global.xml
index 70defb32c4..64d0c131b7 100644
--- a/vector/src/main/res/xml/vector_settings_notification_global.xml
+++ b/vector/src/main/res/xml/vector_settings_notification_global.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
     <im.vector.app.core.preference.VectorPreferenceCategory
         android:key="SETTINGS_OTHER"
         android:title="@string/settings_notification_notify_me_for">
@@ -25,4 +25,4 @@
             android:title="@string/settings_encrypted_group_messages" />
 
     </im.vector.app.core.preference.VectorPreferenceCategory>
-</PreferenceScreen>
\ No newline at end of file
+</androidx.preference.PreferenceScreen>
\ No newline at end of file
diff --git a/vector/src/main/res/xml/vector_settings_notification_mentions_and_keywords.xml b/vector/src/main/res/xml/vector_settings_notification_mentions_and_keywords.xml
index 18de36cb52..be89c86cb1 100644
--- a/vector/src/main/res/xml/vector_settings_notification_mentions_and_keywords.xml
+++ b/vector/src/main/res/xml/vector_settings_notification_mentions_and_keywords.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
     <im.vector.app.core.preference.VectorPreferenceCategory
         android:key="SETTINGS_KEYWORDS_AND_MENTIONS"
         android:title="@string/settings_notification_notify_me_for">
@@ -20,4 +20,4 @@
             android:title="@string/settings_messages_at_room" />
 
     </im.vector.app.core.preference.VectorPreferenceCategory>
-</PreferenceScreen>
\ No newline at end of file
+</androidx.preference.PreferenceScreen>
\ No newline at end of file
diff --git a/vector/src/main/res/xml/vector_settings_notification_other.xml b/vector/src/main/res/xml/vector_settings_notification_other.xml
index ad2b5194f0..b15329635c 100644
--- a/vector/src/main/res/xml/vector_settings_notification_other.xml
+++ b/vector/src/main/res/xml/vector_settings_notification_other.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
     <im.vector.app.core.preference.VectorPreferenceCategory
         android:key="SETTINGS_OTHER"
         android:title="@string/settings_notification_notify_me_for">
@@ -24,4 +24,4 @@
             android:persistent="false"
             android:title="@string/settings_room_upgrades" />
     </im.vector.app.core.preference.VectorPreferenceCategory>
-</PreferenceScreen>
\ No newline at end of file
+</androidx.preference.PreferenceScreen>
\ No newline at end of file

From f0d5950b13e3c79966812ed284ee1f4e7056292d Mon Sep 17 00:00:00 2001
From: David Langley <langley.dave@gmail.com>
Date: Wed, 14 Jul 2021 11:59:00 +0100
Subject: [PATCH 06/21] fix unncessary reformatting and function description

---
 .../src/main/java/im/vector/app/core/di/FragmentModule.kt | 8 ++++----
 ...ectorSettingsPushRuleNotificationPreferenceFragment.kt | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
index 7da26a3ea1..8580543022 100644
--- a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
+++ b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
@@ -387,13 +387,13 @@ interface FragmentModule {
 
     @Binds
     @IntoMap
-    @FragmentKey(VectorSettingsAdvancedNotificationPreferenceFragment::class)
-    fun bindVectorSettingsAdvancedNotificationPreferenceFragment(fragment: VectorSettingsAdvancedNotificationPreferenceFragment): Fragment
+    @FragmentKey(VectorSettingsNotificationsTroubleshootFragment::class)
+    fun bindVectorSettingsNotificationsTroubleshootFragment(fragment: VectorSettingsNotificationsTroubleshootFragment): Fragment
 
     @Binds
     @IntoMap
-    @FragmentKey(VectorSettingsNotificationsTroubleshootFragment::class)
-    fun bindVectorSettingsNotificationsTroubleshootFragment(fragment: VectorSettingsNotificationsTroubleshootFragment): Fragment
+    @FragmentKey(VectorSettingsAdvancedNotificationPreferenceFragment::class)
+    fun bindVectorSettingsAdvancedNotificationPreferenceFragment(fragment: VectorSettingsAdvancedNotificationPreferenceFragment): Fragment
 
     @Binds
     @IntoMap
diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPushRuleNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPushRuleNotificationPreferenceFragment.kt
index 705d90a8c9..9aa6bf2f9f 100644
--- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPushRuleNotificationPreferenceFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPushRuleNotificationPreferenceFragment.kt
@@ -42,7 +42,7 @@ abstract class VectorSettingsPushRuleNotificationPreferenceFragment
     }
 
     /**
-     * Create a push rule with the updated required at index.
+     * Create a push rule with the updated checkbox status.
      *
      * @param status boolean checkbox status
      * @return a push rule with the updated flags

From 73bf50b93c37f190725ff30990899e8f7346f95d Mon Sep 17 00:00:00 2001
From: David Langley <langley.dave@gmail.com>
Date: Tue, 27 Jul 2021 20:21:40 +0100
Subject: [PATCH 07/21] rename global -> default, address comments

---
 .../preference/VectorCheckboxPreference.kt    |  2 +-
 ...sDefaultNotificationPreferenceFragment.kt} |  9 ++++---
 ...dMentionsNotificationPreferenceFragment.kt |  3 +--
 ...ingsOtherNotificationPreferenceFragment.kt |  3 +--
 ...sPushRuleNotificationPreferenceFragment.kt | 24 ++++++++++---------
 vector/src/main/res/values/strings.xml        |  2 +-
 ... vector_settings_notification_default.xml} |  2 +-
 .../res/xml/vector_settings_notifications.xml |  6 ++---
 8 files changed, 25 insertions(+), 26 deletions(-)
 rename vector/src/main/java/im/vector/app/features/settings/notifications/{VectorSettingsGlobalNotificationPreferenceFragment.kt => VectorSettingsDefaultNotificationPreferenceFragment.kt} (89%)
 rename vector/src/main/res/xml/{vector_settings_notification_global.xml => vector_settings_notification_default.xml} (94%)

diff --git a/vector/src/main/java/im/vector/app/core/preference/VectorCheckboxPreference.kt b/vector/src/main/java/im/vector/app/core/preference/VectorCheckboxPreference.kt
index b66ea77bdd..13b65e11b4 100644
--- a/vector/src/main/java/im/vector/app/core/preference/VectorCheckboxPreference.kt
+++ b/vector/src/main/java/im/vector/app/core/preference/VectorCheckboxPreference.kt
@@ -22,7 +22,7 @@ import android.widget.TextView
 import androidx.preference.CheckBoxPreference
 import androidx.preference.PreferenceViewHolder
 
-open class VectorCheckboxPreference : CheckBoxPreference {
+class VectorCheckboxPreference : CheckBoxPreference {
     // Note: @JvmOverload does not work here...
     constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
 
diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsGlobalNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsDefaultNotificationPreferenceFragment.kt
similarity index 89%
rename from vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsGlobalNotificationPreferenceFragment.kt
rename to vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsDefaultNotificationPreferenceFragment.kt
index 7fe4c4b87d..7d6b74b093 100644
--- a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsGlobalNotificationPreferenceFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsDefaultNotificationPreferenceFragment.kt
@@ -19,15 +19,14 @@ package im.vector.app.features.settings.notifications
 import im.vector.app.R
 import org.matrix.android.sdk.api.pushrules.RuleIds
 
-class VectorSettingsGlobalNotificationPreferenceFragment
+class VectorSettingsDefaultNotificationPreferenceFragment
     : VectorSettingsPushRuleNotificationPreferenceFragment() {
 
-    override var titleRes: Int = R.string.settings_notification_global
+    override var titleRes: Int = R.string.settings_notification_default
 
-    override val preferenceXmlRes = R.xml.vector_settings_notification_global
+    override val preferenceXmlRes = R.xml.vector_settings_notification_default
 
-    override val prefKeyToPushRuleId: Map<String, String>
-        get() = mapOf(
+    override val prefKeyToPushRuleId = mapOf(
                 "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_MESSAGES_IN_E2E_ONE_ONE_CHAT_PREFERENCE_KEY" to RuleIds.RULE_ID_ONE_TO_ONE_ENCRYPTED_ROOM,
diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsKeywordAndMentionsNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsKeywordAndMentionsNotificationPreferenceFragment.kt
index 149b176e09..37acc1d898 100644
--- a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsKeywordAndMentionsNotificationPreferenceFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsKeywordAndMentionsNotificationPreferenceFragment.kt
@@ -26,8 +26,7 @@ class VectorSettingsKeywordAndMentionsNotificationPreferenceFragment
 
     override val preferenceXmlRes = R.xml.vector_settings_notification_mentions_and_keywords
 
-    override val prefKeyToPushRuleId: Map<String, String>
-        get() = mapOf(
+    override val prefKeyToPushRuleId = mapOf(
                 "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_CONTAINING_AT_ROOM_PREFERENCE_KEY" to RuleIds.RULE_ID_ROOM_NOTIF
diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsOtherNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsOtherNotificationPreferenceFragment.kt
index db25d46e10..42203fb613 100644
--- a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsOtherNotificationPreferenceFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsOtherNotificationPreferenceFragment.kt
@@ -26,8 +26,7 @@ class VectorSettingsOtherNotificationPreferenceFragment
 
     override val preferenceXmlRes = R.xml.vector_settings_notification_other
 
-    override val prefKeyToPushRuleId: Map<String, String>
-        get() = mapOf(
+    override val prefKeyToPushRuleId = mapOf(
                 "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,
diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsPushRuleNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsPushRuleNotificationPreferenceFragment.kt
index 4e3d8692b7..7f5ed0084d 100644
--- a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsPushRuleNotificationPreferenceFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsPushRuleNotificationPreferenceFragment.kt
@@ -31,16 +31,7 @@ import org.matrix.android.sdk.api.pushrules.rest.PushRuleAndKind
 abstract class VectorSettingsPushRuleNotificationPreferenceFragment
     : VectorSettingsBaseFragment() {
 
-    /**
-     * @return the bing rule status boolean
-     */
-    fun ruleStatusIndexFor(ruleAndKind: PushRuleAndKind): Boolean {
-        val rule = ruleAndKind.pushRule
-        if (rule.ruleId == RuleIds.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) {
-            return rule.shouldNotify() || rule.shouldNotNotify() && !rule.enabled
-        }
-        return rule.enabled && !rule.shouldNotNotify()
-    }
+    abstract val prefKeyToPushRuleId: Map<String, String>
 
     /**
      * Create a push rule with the updated checkbox status.
@@ -90,6 +81,18 @@ abstract class VectorSettingsPushRuleNotificationPreferenceFragment
         }
     }
 
+    /**
+     * @return the bing rule status boolean
+     */
+    private fun ruleStatusIndexFor(ruleAndKind: PushRuleAndKind): Boolean {
+        val rule = ruleAndKind.pushRule
+        if (rule.ruleId == RuleIds.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) {
+            return rule.shouldNotify() || rule.shouldNotNotify() && !rule.enabled
+        }
+        return rule.enabled && !rule.shouldNotNotify()
+    }
+
+
     override fun bindPref() {
         for (preferenceKey in prefKeyToPushRuleId.keys) {
             val preference = findPreference<VectorCheckboxPreference>(preferenceKey)!!
@@ -139,5 +142,4 @@ abstract class VectorSettingsPushRuleNotificationPreferenceFragment
         listView?.adapter?.notifyDataSetChanged()
     }
 
-    abstract val prefKeyToPushRuleId: Map<String, String>
 }
diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml
index 38a2c21f0c..3ead8b009e 100644
--- a/vector/src/main/res/values/strings.xml
+++ b/vector/src/main/res/values/strings.xml
@@ -1087,7 +1087,7 @@
     <string name="settings_notification_advanced">Advanced Notification Settings</string>
     <string name="settings_notification_by_event">Notification importance by event</string>
 
-    <string name="settings_notification_global">Global Notifications</string>
+    <string name="settings_notification_default">Default Notifications</string>
     <string name="settings_notification_mentions_and_keywords">Mentions and Keywords</string>
     <string name="settings_notification_other">Other</string>
 
diff --git a/vector/src/main/res/xml/vector_settings_notification_global.xml b/vector/src/main/res/xml/vector_settings_notification_default.xml
similarity index 94%
rename from vector/src/main/res/xml/vector_settings_notification_global.xml
rename to vector/src/main/res/xml/vector_settings_notification_default.xml
index 64d0c131b7..fb565d2230 100644
--- a/vector/src/main/res/xml/vector_settings_notification_global.xml
+++ b/vector/src/main/res/xml/vector_settings_notification_default.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
     <im.vector.app.core.preference.VectorPreferenceCategory
-        android:key="SETTINGS_OTHER"
+        android:key="SETTINGS_DEFAULT"
         android:title="@string/settings_notification_notify_me_for">
 
         <im.vector.app.core.preference.VectorCheckboxPreference
diff --git a/vector/src/main/res/xml/vector_settings_notifications.xml b/vector/src/main/res/xml/vector_settings_notifications.xml
index 58be182138..1d184ad650 100644
--- a/vector/src/main/res/xml/vector_settings_notifications.xml
+++ b/vector/src/main/res/xml/vector_settings_notifications.xml
@@ -31,10 +31,10 @@
 
         <im.vector.app.core.preference.VectorPreference
             android:dependency="SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY"
-            android:key="SETTINGS_NOTIFICATION_GLOBAL_PREFERENCE_KEY"
+            android:key="SETTINGS_NOTIFICATION_DEFAULT_PREFERENCE_KEY"
             android:persistent="false"
-            android:title="@string/settings_notification_global"
-            app:fragment="im.vector.app.features.settings.notifications.VectorSettingsGlobalNotificationPreferenceFragment"
+            android:title="@string/settings_notification_default"
+            app:fragment="im.vector.app.features.settings.notifications.VectorSettingsDefaultNotificationPreferenceFragment"
             app:isPreferenceVisible="@bool/useNotificationSettingsV2"/>
 
         <im.vector.app.core.preference.VectorPreference

From 60b351cddda21fda655f4603f7a03c3c60f55504 Mon Sep 17 00:00:00 2001
From: David Langley <langley.dave@gmail.com>
Date: Tue, 27 Jul 2021 20:36:41 +0100
Subject: [PATCH 08/21] fic towncrier text

---
 changelog.d/3646.feature | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/changelog.d/3646.feature b/changelog.d/3646.feature
index ba2e870052..c44a5fa58f 100644
--- a/changelog.d/3646.feature
+++ b/changelog.d/3646.feature
@@ -1 +1 @@
-Reorganise Advanced Notifications in to Global Notifications, Keywords and Mentions, Other (This feature is hidden in the release ui until a future release date.)
\ No newline at end of file
+Reorganise Advanced Notifications in to Default Notifications, Keywords and Mentions, Other (This feature is hidden in the release ui until a future release date.)
\ No newline at end of file

From 7405d501f6d7020abefce27e301309d834c55608 Mon Sep 17 00:00:00 2001
From: David Langley <langley.dave@gmail.com>
Date: Tue, 27 Jul 2021 20:38:13 +0100
Subject: [PATCH 09/21] lint

---
 .../app/features/settings/notifications/NotificationIndex.kt    | 1 -
 .../app/features/settings/notifications/PushRuleDefinitions.kt  | 2 --
 2 files changed, 3 deletions(-)

diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/NotificationIndex.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/NotificationIndex.kt
index 678a4e14c2..10bf6f7762 100644
--- a/vector/src/main/java/im/vector/app/features/settings/notifications/NotificationIndex.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/notifications/NotificationIndex.kt
@@ -39,7 +39,6 @@ val PushRule.notificationIndex: NotificationIndex? get() =
         ruleMatches(this, targetRule)
     }
 
-
 private fun ruleMatches(rule: PushRule, targetRule: PushRule): Boolean {
     // Rules match if both are disabled, or if both are enabled and their highlight/sound/notify actions match up.
     return (!rule.enabled && !targetRule.enabled)
diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/PushRuleDefinitions.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/PushRuleDefinitions.kt
index f3bac188a2..dd9077508e 100644
--- a/vector/src/main/java/im/vector/app/features/settings/notifications/PushRuleDefinitions.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/notifications/PushRuleDefinitions.kt
@@ -17,8 +17,6 @@
 package im.vector.app.features.settings.notifications
 
 import org.matrix.android.sdk.api.pushrules.RuleIds
-import org.matrix.android.sdk.api.pushrules.rest.PushRule
-import org.matrix.android.sdk.api.pushrules.toJson
 
 fun getStandardAction(ruleId: String, index: NotificationIndex): StandardActions? {
     return when (ruleId) {

From 886bd3cc8f06b097723702e5aac849ef70556acb Mon Sep 17 00:00:00 2001
From: David Langley <langley.dave@gmail.com>
Date: Wed, 28 Jul 2021 09:34:15 +0100
Subject: [PATCH 10/21] lint

---
 .../VectorSettingsPushRuleNotificationPreferenceFragment.kt     | 2 --
 1 file changed, 2 deletions(-)

diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsPushRuleNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsPushRuleNotificationPreferenceFragment.kt
index 7f5ed0084d..8019ac4f53 100644
--- a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsPushRuleNotificationPreferenceFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsPushRuleNotificationPreferenceFragment.kt
@@ -92,7 +92,6 @@ abstract class VectorSettingsPushRuleNotificationPreferenceFragment
         return rule.enabled && !rule.shouldNotNotify()
     }
 
-
     override fun bindPref() {
         for (preferenceKey in prefKeyToPushRuleId.keys) {
             val preference = findPreference<VectorCheckboxPreference>(preferenceKey)!!
@@ -141,5 +140,4 @@ abstract class VectorSettingsPushRuleNotificationPreferenceFragment
     private fun refreshDisplay() {
         listView?.adapter?.notifyDataSetChanged()
     }
-
 }

From 756ff3d93805f79ec50467ffb4ac5ae4001d2241 Mon Sep 17 00:00:00 2001
From: David Langley <langley.dave@gmail.com>
Date: Tue, 10 Aug 2021 10:54:13 +0100
Subject: [PATCH 11/21] cleanup unused code and add comments for clarity

---
 .../notifications/NotificationIndex.kt        |  7 +++
 ...sAdvancedNotificationPreferenceFragment.kt |  1 -
 ...sPushRuleNotificationPreferenceFragment.kt | 63 -------------------
 3 files changed, 7 insertions(+), 64 deletions(-)

diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/NotificationIndex.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/NotificationIndex.kt
index 10bf6f7762..27f9302c45 100644
--- a/vector/src/main/java/im/vector/app/features/settings/notifications/NotificationIndex.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/notifications/NotificationIndex.kt
@@ -29,6 +29,10 @@ enum class NotificationIndex(val index: Int) {
     }
 }
 
+/**
+ * Given a push rule determine the NotificationIndex by comparing it to the static push rule definitions.
+ * Used when determining the selected state of the PushRulePreference.
+ */
 val PushRule.notificationIndex: NotificationIndex? get() =
     NotificationIndex.values().firstOrNull {
         // Get the actions for the index
@@ -39,6 +43,9 @@ val PushRule.notificationIndex: NotificationIndex? get() =
         ruleMatches(this, targetRule)
     }
 
+/**
+ * A check to determine if two push rules should be considered a match.
+ */
 private fun ruleMatches(rule: PushRule, targetRule: PushRule): Boolean {
     // Rules match if both are disabled, or if both are enabled and their highlight/sound/notify actions match up.
     return (!rule.enabled && !targetRule.enabled)
diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsAdvancedNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsAdvancedNotificationPreferenceFragment.kt
index 5ffb4d854d..93a788f528 100644
--- a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsAdvancedNotificationPreferenceFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsAdvancedNotificationPreferenceFragment.kt
@@ -38,7 +38,6 @@ class VectorSettingsAdvancedNotificationPreferenceFragment @Inject constructor()
         for (preferenceKey in prefKeyToPushRuleId.keys) {
             val preference = findPreference<VectorPreference>(preferenceKey)
             if (preference is PushRulePreference) {
-                // preference.isEnabled = null != rules && isConnected && pushManager.areDeviceNotificationsAllowed()
                 val ruleAndKind: PushRuleAndKind? = session.getPushRules().findDefaultRule(prefKeyToPushRuleId[preferenceKey])
 
                 if (ruleAndKind == null) {
diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsPushRuleNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsPushRuleNotificationPreferenceFragment.kt
index 8019ac4f53..6f28876e1d 100644
--- a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsPushRuleNotificationPreferenceFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsPushRuleNotificationPreferenceFragment.kt
@@ -22,10 +22,6 @@ import im.vector.app.core.preference.VectorCheckboxPreference
 import im.vector.app.core.utils.toast
 import im.vector.app.features.settings.VectorSettingsBaseFragment
 import kotlinx.coroutines.launch
-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
 
 abstract class VectorSettingsPushRuleNotificationPreferenceFragment
@@ -33,65 +29,6 @@ abstract class VectorSettingsPushRuleNotificationPreferenceFragment
 
     abstract val prefKeyToPushRuleId: Map<String, String>
 
-    /**
-     * Create a push rule with the updated checkbox status.
-     *
-     * @param status boolean checkbox status
-     * @return a push rule with the updated flags
-     */
-    fun createNewRule(ruleAndKind: PushRuleAndKind, status: Boolean): PushRule {
-        val safeRule = ruleAndKind.pushRule
-        val safeKind = ruleAndKind.kind
-        val ruleStatusIndex = ruleStatusIndexFor(ruleAndKind)
-
-        return if (status != ruleStatusIndex) {
-            if (safeRule.ruleId == RuleIds.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) {
-                if (status) {
-                    safeRule.copy(enabled = true)
-                            .setNotify(true)
-                            .setNotificationSound()
-                } else {
-                    safeRule.copy(enabled = true)
-                            .setNotify(false)
-                            .removeNotificationSound()
-                }
-            } else {
-                if (status) {
-                    safeRule.copy(enabled = true)
-                            .setNotify(true)
-                            .setHighlight(safeKind != RuleSetKey.UNDERRIDE
-                                    && safeRule.ruleId != RuleIds.RULE_ID_INVITE_ME)
-                            .setNotificationSound(
-                                    if (safeRule.ruleId == RuleIds.RULE_ID_CALL) {
-                                        Action.ACTION_OBJECT_VALUE_VALUE_RING
-                                    } else {
-                                        Action.ACTION_OBJECT_VALUE_VALUE_DEFAULT
-                                    }
-                            )
-                } else {
-                    if (safeKind == RuleSetKey.UNDERRIDE || safeRule.ruleId == RuleIds.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) {
-                        safeRule.setNotify(false)
-                    } else {
-                        safeRule.copy(enabled = false)
-                    }
-                }
-            }
-        } else {
-            safeRule
-        }
-    }
-
-    /**
-     * @return the bing rule status boolean
-     */
-    private fun ruleStatusIndexFor(ruleAndKind: PushRuleAndKind): Boolean {
-        val rule = ruleAndKind.pushRule
-        if (rule.ruleId == RuleIds.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) {
-            return rule.shouldNotify() || rule.shouldNotNotify() && !rule.enabled
-        }
-        return rule.enabled && !rule.shouldNotNotify()
-    }
-
     override fun bindPref() {
         for (preferenceKey in prefKeyToPushRuleId.keys) {
             val preference = findPreference<VectorCheckboxPreference>(preferenceKey)!!

From bf9a22c1b03cc87946deeeaeae466256a77fa2b4 Mon Sep 17 00:00:00 2001
From: Onuray Sahin <onurays@element.io>
Date: Tue, 10 Aug 2021 13:59:39 +0300
Subject: [PATCH 12/21] Fix flickering lock view.

---
 .../home/room/detail/composer/VoiceMessageRecorderView.kt    | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt
index 48195dc8f1..00ab67656c 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt
@@ -220,6 +220,9 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
             }
             RecordingState.STARTED    -> {
                 showRecordingViews()
+                val translationAmount = distanceX.coerceAtMost(distanceToCancel)
+                views.voiceMessageMicButton.translationX = -translationAmount * rtlXMultiplier
+                views.voiceMessageSlideToCancel.translationX = -translationAmount / 2 * rtlXMultiplier
             }
             RecordingState.NONE       -> Timber.d("VoiceMessageRecorderView shouldn't be in NONE state while moving.")
             RecordingState.PLAYBACK   -> Timber.d("VoiceMessageRecorderView shouldn't be in PLAYBACK state while moving.")
@@ -235,7 +238,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
         if (recordingState == RecordingState.STARTED) {
             // Determine if cancelling or locking for the first move action.
             if (((currentX < firstX && rtlXMultiplier == 1) || (currentX > firstX && rtlXMultiplier == -1))
-                    && distanceX > distanceY) {
+                    && distanceX > distanceY && distanceX > lastDistanceX) {
                 recordingState = RecordingState.CANCELLING
             } else if (currentY < firstY && distanceY > distanceX) {
                 recordingState = RecordingState.LOCKING

From a0730943b494bca4ca97c35aeddbce001ab36b79 Mon Sep 17 00:00:00 2001
From: Onuray Sahin <onurays@element.io>
Date: Tue, 10 Aug 2021 14:17:33 +0300
Subject: [PATCH 13/21] Dynamically set content description of play/pause
 button.

---
 .../home/room/detail/composer/VoiceMessageRecorderView.kt     | 2 ++
 .../home/room/detail/timeline/item/MessageVoiceItem.kt        | 4 ++++
 2 files changed, 6 insertions(+)

diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt
index 00ab67656c..50d8d8e867 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt
@@ -510,12 +510,14 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
             }
             is VoiceMessagePlaybackTracker.Listener.State.Playing   -> {
                 views.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_pause)
+                views.voicePlaybackControlButton.contentDescription = context.getString(R.string.a11y_pause_voice_message)
                 val formattedTimerText = DateUtils.formatElapsedTime((state.playbackTime / 1000).toLong())
                 views.voicePlaybackTime.text = formattedTimerText
             }
             is VoiceMessagePlaybackTracker.Listener.State.Paused,
             is VoiceMessagePlaybackTracker.Listener.State.Idle      -> {
                 views.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_play)
+                views.voicePlaybackControlButton.contentDescription = context.getString(R.string.a11y_play_voice_message)
             }
         }
     }
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt
index dc204da291..fb7d0cabd5 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt
@@ -71,6 +71,7 @@ abstract class MessageVoiceItem : AbsMessageItem<MessageVoiceItem.Holder>() {
             contentUploadStateTrackerBinder.bind(attributes.informationData.eventId, izLocalFile, holder.progressLayout)
         } else {
             holder.voicePlaybackControlButton.setImageResource(R.drawable.ic_cross)
+            holder.voicePlaybackControlButton.contentDescription = holder.view.context.getString(R.string.error_voice_message_unable_to_play)
             holder.progressLayout.isVisible = false
         }
 
@@ -98,16 +99,19 @@ abstract class MessageVoiceItem : AbsMessageItem<MessageVoiceItem.Holder>() {
 
     private fun renderIdleState(holder: Holder) {
         holder.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_play)
+        holder.voicePlaybackControlButton.contentDescription = holder.view.context.getString(R.string.a11y_play_voice_message)
         holder.voicePlaybackTime.text = formatPlaybackTime(duration)
     }
 
     private fun renderPlayingState(holder: Holder, state: VoiceMessagePlaybackTracker.Listener.State.Playing) {
         holder.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_pause)
+        holder.voicePlaybackControlButton.contentDescription = holder.view.context.getString(R.string.a11y_pause_voice_message)
         holder.voicePlaybackTime.text = formatPlaybackTime(state.playbackTime)
     }
 
     private fun renderPausedState(holder: Holder, state: VoiceMessagePlaybackTracker.Listener.State.Paused) {
         holder.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_play)
+        holder.voicePlaybackControlButton.contentDescription = holder.view.context.getString(R.string.a11y_play_voice_message)
         holder.voicePlaybackTime.text = formatPlaybackTime(state.playbackTime)
     }
 

From bf1db5dcf9af1f8591627e4495ec8927aa8eee3e Mon Sep 17 00:00:00 2001
From: Onuray Sahin <onurays@element.io>
Date: Tue, 10 Aug 2021 14:36:01 +0300
Subject: [PATCH 14/21] Remove content description of mic button if it is not
 visible.

---
 .../room/detail/composer/VoiceMessageRecorderView.kt   | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt
index 50d8d8e867..033020bbce 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt
@@ -20,6 +20,7 @@ import android.content.Context
 import android.text.format.DateUtils
 import android.util.AttributeSet
 import android.view.MotionEvent
+import android.view.View
 import androidx.constraintlayout.widget.ConstraintLayout
 import androidx.core.view.isInvisible
 import androidx.core.view.isVisible
@@ -87,6 +88,15 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
         initListeners()
     }
 
+    override fun onVisibilityChanged(changedView: View, visibility: Int) {
+        super.onVisibilityChanged(changedView, visibility)
+        if (changedView == this && visibility == VISIBLE) {
+            views.voiceMessageMicButton.contentDescription = context.getString(R.string.a11y_start_voice_message)
+        } else {
+            views.voiceMessageMicButton.contentDescription = ""
+        }
+    }
+
     fun initVoiceRecordingViews() {
         recordingState = RecordingState.NONE
 

From 296a1c47702a5228c612df2c98c02e01bc75208f Mon Sep 17 00:00:00 2001
From: Onuray Sahin <onurays@element.io>
Date: Tue, 10 Aug 2021 14:43:16 +0300
Subject: [PATCH 15/21] Vibrate when the recording is canceled.

---
 .../home/room/detail/composer/VoiceMessageRecorderView.kt     | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt
index 033020bbce..f059d4285e 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt
@@ -428,6 +428,10 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
         if (recordingState == RecordingState.CANCELLED || recordingState == RecordingState.NONE) {
             hideToast()
         }
+
+        if (isCancelled.orFalse()) {
+            vibrate(context)
+        }
     }
 
     private fun resetMicButtonUi() {

From 0cd0484b41bd714502a063ca516ce7722f3c8a3e Mon Sep 17 00:00:00 2001
From: Onuray Sahin <onurays@element.io>
Date: Tue, 10 Aug 2021 14:54:03 +0300
Subject: [PATCH 16/21] Fix flickering between locking states.

---
 .../home/room/detail/composer/VoiceMessageRecorderView.kt       | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt
index f059d4285e..96a066b295 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt
@@ -250,7 +250,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
             if (((currentX < firstX && rtlXMultiplier == 1) || (currentX > firstX && rtlXMultiplier == -1))
                     && distanceX > distanceY && distanceX > lastDistanceX) {
                 recordingState = RecordingState.CANCELLING
-            } else if (currentY < firstY && distanceY > distanceX) {
+            } else if (currentY < firstY && distanceY > distanceX && distanceY > lastDistanceY) {
                 recordingState = RecordingState.LOCKING
             }
         } else if (recordingState == RecordingState.CANCELLING) {

From 9f4a45911656c0f873027fc4c83958b62057444d Mon Sep 17 00:00:00 2001
From: Onuray Sahin <onurays@element.io>
Date: Tue, 10 Aug 2021 15:40:04 +0300
Subject: [PATCH 17/21] Fix cannot draw waveform while recording after onPause.

---
 .../vector/app/features/home/room/detail/RoomDetailFragment.kt | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
index 6a8b4fa863..c37f1840ac 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
@@ -1044,6 +1044,9 @@ class RoomDetailFragment @Inject constructor(
         notificationDrawerManager.setCurrentRoom(roomDetailArgs.roomId)
         roomDetailPendingActionStore.data?.let { handlePendingAction(it) }
         roomDetailPendingActionStore.data = null
+
+        // Removed listeners should be set again
+        setupVoiceMessageView()
     }
 
     private fun handlePendingAction(roomDetailPendingAction: RoomDetailPendingAction) {

From 5cc9c6231b372143d326369ffc0f6bea043ebfbe Mon Sep 17 00:00:00 2001
From: Onuray Sahin <onurays@element.io>
Date: Tue, 10 Aug 2021 15:44:09 +0300
Subject: [PATCH 18/21] Changelog added.

---
 changelog.d/3798.bugfix | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 changelog.d/3798.bugfix

diff --git a/changelog.d/3798.bugfix b/changelog.d/3798.bugfix
new file mode 100644
index 0000000000..92374d94d6
--- /dev/null
+++ b/changelog.d/3798.bugfix
@@ -0,0 +1 @@
+Voice Message - UI Improvements
\ No newline at end of file

From 45077c69f771951fc9924b8cd8b017b847b81cd6 Mon Sep 17 00:00:00 2001
From: David Langley <langley.dave@gmail.com>
Date: Wed, 11 Aug 2021 09:59:23 +0100
Subject: [PATCH 19/21] remove NotificationIndex Int index

---
 .../settings/notifications/NotificationIndex.kt      | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/NotificationIndex.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/NotificationIndex.kt
index 27f9302c45..29d316bb76 100644
--- a/vector/src/main/java/im/vector/app/features/settings/notifications/NotificationIndex.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/notifications/NotificationIndex.kt
@@ -19,14 +19,10 @@ package im.vector.app.features.settings.notifications
 import org.matrix.android.sdk.api.pushrules.rest.PushRule
 import org.matrix.android.sdk.api.pushrules.toJson
 
-enum class NotificationIndex(val index: Int) {
-    OFF(0),
-    SILENT(1),
-    NOISY(2);
-
-    companion object {
-        fun fromInt(index: Int) = values().first { it.index == index }
-    }
+enum class NotificationIndex {
+    OFF,
+    SILENT,
+    NOISY;
 }
 
 /**

From c2401e04b4966a76de2b058f1583431d69ee2134 Mon Sep 17 00:00:00 2001
From: Onuray Sahin <onurays@element.io>
Date: Wed, 11 Aug 2021 14:54:29 +0300
Subject: [PATCH 20/21] Fix collapsing mic and send buttons.

---
 .../vector/app/features/home/room/detail/RoomDetailFragment.kt   | 1 -
 1 file changed, 1 deletion(-)

diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
index c37f1840ac..e50d6c8df3 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
@@ -1321,7 +1321,6 @@ class RoomDetailFragment @Inject constructor(
         if (text.isNotBlank()) {
             // We collapse ASAP, if not there will be a slight annoying delay
             views.composerLayout.collapse(true)
-            views.voiceMessageRecorderView.isVisible = vectorPreferences.labsUseVoiceMessage()
             lockSendButton = true
             roomDetailViewModel.handle(RoomDetailAction.SendMessage(text, vectorPreferences.isMarkdownEnabled()))
             emojiPopup.dismiss()

From a8f4b318c18c067e9d63edfc2d87f7bf9745c5e5 Mon Sep 17 00:00:00 2001
From: Onuray Sahin <onurays@element.io>
Date: Wed, 11 Aug 2021 14:59:21 +0300
Subject: [PATCH 21/21] Fix tice vibration after cancelling the voice record.

---
 .../home/room/detail/composer/VoiceMessageRecorderView.kt    | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt
index 96a066b295..47e72b46f7 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt
@@ -219,6 +219,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
             }
             RecordingState.CANCELLED  -> {
                 hideRecordingViews(isCancelled = true)
+                vibrate(context)
             }
             RecordingState.LOCKED     -> {
                 if (isRecordingStateChanged) { // Do not update views if it was already in locked state.
@@ -428,10 +429,6 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
         if (recordingState == RecordingState.CANCELLED || recordingState == RecordingState.NONE) {
             hideToast()
         }
-
-        if (isCancelled.orFalse()) {
-            vibrate(context)
-        }
     }
 
     private fun resetMicButtonUi() {