diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml
new file mode 100644
index 0000000000..e95387dd6c
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug.yml
@@ -0,0 +1,69 @@
+name: Bug report for the Element Android app
+description: Report any issues that you have found with the Element app. Please [check open issues](https://github.com/vector-im/element-android/issues) first, in case it has already been reported.
+labels: [T-Defect]
+body:
+  - type: markdown
+    attributes:
+      value: |
+        Thanks for taking the time to fill out this bug report!
+
+        Please report security issues by email to security@matrix.org
+  - type: textarea
+    id: reproduction-steps
+    attributes:
+      label: Steps to reproduce
+      description: Please attach screenshots, videos or logs if you can.
+      placeholder: Tell us what you see!
+      value: |
+        1. Where are you starting? What can you see?
+        2. What do you click?
+        3. More steps…
+    validations:
+      required: true
+  - type: textarea
+    id: expected-result
+    attributes:
+      label: What did you expect?
+      placeholder: Tell us what you expected to happen in as much detail as you can.
+    validations:
+      required: true
+  - type: textarea
+    id: actual-result
+    attributes:
+      label: What happened?
+      placeholder: Tell us what went wrong
+    validations:
+      required: true
+  - type: input
+    id: device
+    attributes:
+      label: Your phone model
+      placeholder: e.g. Samsung S6
+    validations:
+      required: false
+  - type: input
+    id: os
+    attributes:
+      label: Operating system version
+      placeholder: e.g. Android 10.0
+    validations:
+      required: false
+  - type: input
+    id: version
+    attributes:
+      label: Application version and app store
+      description: You can find the version information in Settings -> Help & About. 
+      placeholder: e.g. Element version 1.7.34, olm version 3.2.3 from F-Droid
+    validations:
+      required: false
+  - type: dropdown
+    id: rageshake
+    attributes:
+      label: Have you submitted a rageshake?
+      description:  |
+        Did you know that you can shake your phone to submit logs for this issue? Trigger the defect, then shake your phone and you will see a popup asking if you would like to open the bug report screen. Click YES, and describe the issue, mentioning that you have also filed a bug. Submit the report to send anonymous logs to the developers.
+      options:
+        - 'Yes'
+        - 'No'
+    validations:
+      required: true
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index d7c3506fa0..0000000000
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,34 +0,0 @@
----
-name: Bug report
-about: Create a report to help us improve Element
-title: ''
-labels: ''
-assignees: ''
-
----
-
-#### Describe the bug
-A clear and concise description of what the bug is.
-
-#### To Reproduce
-Steps to reproduce the behavior:
-1. Go to '...'
-2. Click on '....'
-3. Scroll down to '....'
-4. See error
-
-#### Expected behavior
-A clear and concise description of what you expected to happen.
-
-#### Screenshots
-If applicable, add screenshots to help explain your problem.
-
-#### Smartphone (please complete the following information):
- - Device: [e.g. Samsung S6]
- - OS: [e.g. Android 6.0]
-
-#### Additional context
- - App version and store [e.g. 1.0.0 - F-Droid]
- - Homeserver: [e.g. matrix.org]
-
-Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/enhancement.yml b/.github/ISSUE_TEMPLATE/enhancement.yml
new file mode 100644
index 0000000000..5d9cfb3c88
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/enhancement.yml
@@ -0,0 +1,36 @@
+name: Enhancement request
+description: Do you have a suggestion or feature request?
+labels: [T-Enhancement]
+body:
+  - type: markdown
+    attributes:
+      value: |
+        Thank you for taking the time to propose a new feature or make a suggestion.
+  - type: textarea
+    id: usecase
+    attributes:
+      label: Your use case
+      description: What would you like to be able to do? Please feel welcome to include screenshots or mock ups.
+      placeholder: Tell us what you would like to do!
+      value: |
+        #### What would you like to do?
+
+        #### Why would you like to do it?
+
+        #### How would you like to achieve it?
+    validations:
+      required: true
+  - type: textarea
+    id: alternative
+    attributes:
+      label: Have you considered any alternatives?
+      placeholder: A clear and concise description of any alternative solutions or features you've considered.
+    validations:
+      required: false
+  - type: textarea
+    id: additional-context
+    attributes:
+      label: Additional context
+      placeholder: Is there anything else you'd like to add?
+    validations:
+      required: false
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
deleted file mode 100644
index da96d461c5..0000000000
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-name: Feature request
-about: Suggest an idea for this project
-title: ''
-labels: type:suggestion
-assignees: ''
-
----
-
-#### Is your feature request related to a problem? Please describe.
-A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
-
-#### Describe the solution you'd like.
-A clear and concise description of what you want to happen.
-
-#### Describe alternatives you've considered.
-A clear and concise description of any alternative solutions or features you've considered.
-
-#### Additional context
-Add any other context or screenshots about the feature request here.
diff --git a/changelog.d/1823.bugfix b/changelog.d/1823.bugfix
new file mode 100644
index 0000000000..8252e1826f
--- /dev/null
+++ b/changelog.d/1823.bugfix
@@ -0,0 +1 @@
+- Add mxid to autocomplete suggestion if more than one user in a room has the same displayname
diff --git a/changelog.d/3853.feature b/changelog.d/3853.feature
new file mode 100644
index 0000000000..86c19d2c22
--- /dev/null
+++ b/changelog.d/3853.feature
@@ -0,0 +1 @@
+Call: show dialog for some ended reasons.
\ No newline at end of file
diff --git a/changelog.d/3887.bugfix b/changelog.d/3887.bugfix
new file mode 100644
index 0000000000..eecd2cea19
--- /dev/null
+++ b/changelog.d/3887.bugfix
@@ -0,0 +1 @@
+Message edition is not rendered in e2e rooms after pagination
\ No newline at end of file
diff --git a/changelog.d/pr-3883.misc b/changelog.d/pr-3883.misc
new file mode 100644
index 0000000000..468e5e4927
--- /dev/null
+++ b/changelog.d/pr-3883.misc
@@ -0,0 +1 @@
+Issue templates: modernise and sync with element-web
diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle
index e30b63e751..90be941b6f 100644
--- a/matrix-sdk-android/build.gradle
+++ b/matrix-sdk-android/build.gradle
@@ -169,7 +169,7 @@ dependencies {
     implementation 'com.otaliastudios:transcoder:0.10.3'
 
     // Phone number https://github.com/google/libphonenumber
-    implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.30'
+    implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.31'
 
     testImplementation 'junit:junit:4.13.2'
     testImplementation 'org.robolectric:robolectric:4.5.1'
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/EventInsertLiveObserver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/EventInsertLiveObserver.kt
index 88aa432fb3..758c7aa5b9 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/EventInsertLiveObserver.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/EventInsertLiveObserver.kt
@@ -17,6 +17,9 @@
 package org.matrix.android.sdk.internal.database
 
 import com.zhuinden.monarchy.Monarchy
+import io.realm.RealmConfiguration
+import io.realm.RealmResults
+import kotlinx.coroutines.launch
 import org.matrix.android.sdk.internal.database.mapper.asDomain
 import org.matrix.android.sdk.internal.database.model.EventEntity
 import org.matrix.android.sdk.internal.database.model.EventInsertEntity
@@ -24,20 +27,15 @@ import org.matrix.android.sdk.internal.database.model.EventInsertEntityFields
 import org.matrix.android.sdk.internal.database.query.where
 import org.matrix.android.sdk.internal.di.SessionDatabase
 import org.matrix.android.sdk.internal.session.EventInsertLiveProcessor
-import io.realm.RealmConfiguration
-import io.realm.RealmResults
-import kotlinx.coroutines.launch
-import org.matrix.android.sdk.internal.crypto.EventDecryptor
 import timber.log.Timber
 import javax.inject.Inject
 
 internal class EventInsertLiveObserver @Inject constructor(@SessionDatabase realmConfiguration: RealmConfiguration,
-                                                           private val processors: Set<@JvmSuppressWildcards EventInsertLiveProcessor>,
-                                                           private val eventDecryptor: EventDecryptor)
+                                                           private val processors: Set<@JvmSuppressWildcards EventInsertLiveProcessor>)
     : RealmLiveEntityObserver<EventInsertEntity>(realmConfiguration) {
 
-    override val query = Monarchy.Query<EventInsertEntity> {
-        it.where(EventInsertEntity::class.java)
+    override val query = Monarchy.Query {
+        it.where(EventInsertEntity::class.java).equalTo(EventInsertEntityFields.CAN_BE_PROCESSED, true)
     }
 
     override fun onChange(results: RealmResults<EventInsertEntity>) {
@@ -86,23 +84,6 @@ internal class EventInsertLiveObserver @Inject constructor(@SessionDatabase real
         }
     }
 
-//    private fun decryptIfNeeded(event: Event) {
-//        if (event.isEncrypted() && event.mxDecryptionResult == null) {
-//            try {
-//                val result = eventDecryptor.decryptEvent(event, event.roomId ?: "")
-//                event.mxDecryptionResult = OlmDecryptionResult(
-//                        payload = result.clearEvent,
-//                        senderKey = result.senderCurve25519Key,
-//                        keysClaimed = result.claimedEd25519Key?.let { k -> mapOf("ed25519" to k) },
-//                        forwardingCurve25519KeyChain = result.forwardingCurve25519KeyChain
-//                )
-//            } catch (e: MXCryptoError) {
-//                Timber.v("Failed to decrypt event")
-//                // TODO -> we should keep track of this and retry, or some processing will never be handled
-//            }
-//        }
-//    }
-
     private fun shouldProcess(eventInsertEntity: EventInsertEntity): Boolean {
         return processors.any {
             it.shouldProcess(eventInsertEntity.eventId, eventInsertEntity.eventType, eventInsertEntity.insertType)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt
index 28ae4d8bfd..aa96ca5e1a 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt
@@ -29,6 +29,7 @@ import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntityFie
 import org.matrix.android.sdk.internal.database.model.EditAggregatedSummaryEntityFields
 import org.matrix.android.sdk.internal.database.model.EditionOfEventFields
 import org.matrix.android.sdk.internal.database.model.EventEntityFields
+import org.matrix.android.sdk.internal.database.model.EventInsertEntityFields
 import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntityFields
 import org.matrix.android.sdk.internal.database.model.PendingThreePidEntityFields
 import org.matrix.android.sdk.internal.database.model.PreviewUrlCacheEntityFields
@@ -46,7 +47,7 @@ import timber.log.Timber
 
 internal object RealmSessionStoreMigration : RealmMigration {
 
-    const val SESSION_STORE_SCHEMA_VERSION = 16L
+    const val SESSION_STORE_SCHEMA_VERSION = 17L
 
     override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
         Timber.v("Migrating Realm Session from $oldVersion to $newVersion")
@@ -67,6 +68,7 @@ internal object RealmSessionStoreMigration : RealmMigration {
         if (oldVersion <= 13) migrateTo14(realm)
         if (oldVersion <= 14) migrateTo15(realm)
         if (oldVersion <= 15) migrateTo16(realm)
+        if (oldVersion <= 16) migrateTo17(realm)
     }
 
     private fun migrateTo1(realm: DynamicRealm) {
@@ -330,4 +332,10 @@ internal object RealmSessionStoreMigration : RealmMigration {
                     obj.setLong(HomeServerCapabilitiesEntityFields.LAST_UPDATED_TIMESTAMP, 0)
                 }
     }
+
+    private fun migrateTo17(realm: DynamicRealm) {
+        Timber.d("Step 16 -> 17")
+        realm.schema.get("EventInsertEntity")
+                ?.addField(EventInsertEntityFields.CAN_BE_PROCESSED, Boolean::class.java)
+    }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EventEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EventEntity.kt
index c9edbcd889..4dc8712afb 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EventEntity.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EventEntity.kt
@@ -22,6 +22,7 @@ import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult
 import org.matrix.android.sdk.internal.di.MoshiProvider
 import io.realm.RealmObject
 import io.realm.annotations.Index
+import org.matrix.android.sdk.internal.extensions.assertIsManaged
 
 internal open class EventEntity(@Index var eventId: String = "",
                                 @Index var roomId: String = "",
@@ -56,15 +57,22 @@ internal open class EventEntity(@Index var eventId: String = "",
     companion object
 
     fun setDecryptionResult(result: MXEventDecryptionResult) {
+        assertIsManaged()
         val decryptionResult = OlmDecryptionResult(
                 payload = result.clearEvent,
                 senderKey = result.senderCurve25519Key,
                 keysClaimed = result.claimedEd25519Key?.let { mapOf("ed25519" to it) },
                 forwardingCurve25519KeyChain = result.forwardingCurve25519KeyChain
         )
-        val adapter = MoshiProvider.providesMoshi().adapter<OlmDecryptionResult>(OlmDecryptionResult::class.java)
+        val adapter = MoshiProvider.providesMoshi().adapter(OlmDecryptionResult::class.java)
         decryptionResultJson = adapter.toJson(decryptionResult)
         decryptionErrorCode = null
         decryptionErrorReason = null
+
+        // If we have an EventInsertEntity for the eventId we make sures it can be processed now.
+        realm.where(EventInsertEntity::class.java)
+                .equalTo(EventInsertEntityFields.EVENT_ID, eventId)
+                .findFirst()
+                ?.canBeProcessed = true
     }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EventInsertEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EventInsertEntity.kt
index f4426207be..5cfd306d2f 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EventInsertEntity.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EventInsertEntity.kt
@@ -23,7 +23,12 @@ import io.realm.RealmObject
  * in EventEntity table.
  */
 internal open class EventInsertEntity(var eventId: String = "",
-                                      var eventType: String = ""
+                                      var eventType: String = "",
+                                      /**
+                                       * This flag will be used to filter EventInsertEntity in EventInsertLiveObserver.
+                                       * Currently it's set to false when the event content is encrypted.
+                                       */
+                                      var canBeProcessed: Boolean = true
 ) : RealmObject() {
 
     private var insertTypeStr: String = EventInsertType.INCREMENTAL_SYNC.name
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/EventEntityQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/EventEntityQueries.kt
index 0bf62a19fe..57e24cf88f 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/EventEntityQueries.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/EventEntityQueries.kt
@@ -24,6 +24,7 @@ import io.realm.Realm
 import io.realm.RealmList
 import io.realm.RealmQuery
 import io.realm.kotlin.where
+import org.matrix.android.sdk.api.session.events.model.EventType
 
 internal fun EventEntity.copyToRealmOrIgnore(realm: Realm, insertType: EventInsertType): EventEntity {
     val eventEntity = realm.where<EventEntity>()
@@ -31,7 +32,8 @@ internal fun EventEntity.copyToRealmOrIgnore(realm: Realm, insertType: EventInse
             .equalTo(EventEntityFields.ROOM_ID, roomId)
             .findFirst()
     return if (eventEntity == null) {
-        val insertEntity = EventInsertEntity(eventId = eventId, eventType = type).apply {
+        val canBeProcessed = type != EventType.ENCRYPTED || decryptionResultJson != null
+        val insertEntity = EventInsertEntity(eventId = eventId, eventType = type, canBeProcessed = canBeProcessed).apply {
             this.insertType = insertType
         }
         realm.insert(insertEntity)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RetrofitExtensions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RetrofitExtensions.kt
index 2116063626..71ba71b915 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RetrofitExtensions.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RetrofitExtensions.kt
@@ -86,13 +86,16 @@ private fun toFailure(errorBody: ResponseBody?, httpCode: Int, globalErrorReceiv
         val matrixError = matrixErrorAdapter.fromJson(errorBodyStr)
 
         if (matrixError != null) {
-            if (matrixError.code == MatrixError.M_CONSENT_NOT_GIVEN && !matrixError.consentUri.isNullOrBlank()) {
-                // Also send this error to the globalErrorReceiver, for a global management
-                globalErrorReceiver?.handleGlobalError(GlobalError.ConsentNotGivenError(matrixError.consentUri))
-            } else if (httpCode == HttpURLConnection.HTTP_UNAUTHORIZED /* 401 */
-                    && matrixError.code == MatrixError.M_UNKNOWN_TOKEN) {
-                // Also send this error to the globalErrorReceiver, for a global management
-                globalErrorReceiver?.handleGlobalError(GlobalError.InvalidToken(matrixError.isSoftLogout.orFalse()))
+            when {
+                matrixError.code == MatrixError.M_CONSENT_NOT_GIVEN && !matrixError.consentUri.isNullOrBlank() -> {
+                    // Also send this error to the globalErrorReceiver, for a global management
+                    globalErrorReceiver?.handleGlobalError(GlobalError.ConsentNotGivenError(matrixError.consentUri))
+                }
+                httpCode == HttpURLConnection.HTTP_UNAUTHORIZED /* 401 */
+                        && matrixError.code == MatrixError.M_UNKNOWN_TOKEN                                     -> {
+                    // Also send this error to the globalErrorReceiver, for a global management
+                    globalErrorReceiver?.handleGlobalError(GlobalError.InvalidToken(matrixError.isSoftLogout.orFalse()))
+                }
             }
 
             return Failure.ServerError(matrixError, httpCode)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt
index e98e5646af..13095fbd58 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt
@@ -77,7 +77,7 @@ internal class LocalEchoRepository @Inject constructor(@SessionDatabase private
         val timelineEvent = timelineEventMapper.map(timelineEventEntity)
         timelineInput.onLocalEchoCreated(roomId = roomId, timelineEvent = timelineEvent)
         taskExecutor.executorScope.asyncTransaction(monarchy) { realm ->
-            val eventInsertEntity = EventInsertEntity(event.eventId, event.type).apply {
+            val eventInsertEntity = EventInsertEntity(event.eventId, event.type, canBeProcessed = true).apply {
                 this.insertType = EventInsertType.LOCAL_ECHO
             }
             realm.insert(eventInsertEntity)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineEventDecryptor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineEventDecryptor.kt
index 3517f26c5d..721dae0b1b 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineEventDecryptor.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineEventDecryptor.kt
@@ -106,7 +106,8 @@ internal class TimelineEventDecryptor @Inject constructor(
             val result = cryptoService.decryptEvent(request.event, timelineId)
             Timber.v("Successfully decrypted event ${event.eventId}")
             realm.executeTransaction {
-                EventEntity.where(it, eventId = event.eventId ?: "")
+                val eventId = event.eventId ?: ""
+                EventEntity.where(it, eventId = eventId)
                         .findFirst()
                         ?.setDecryptionResult(result)
             }
diff --git a/vector/build.gradle b/vector/build.gradle
index b47b3ddb61..c1bf57ac57 100644
--- a/vector/build.gradle
+++ b/vector/build.gradle
@@ -143,8 +143,10 @@ android {
         resValue "bool", "useLoginV2", "false"
 
         // NotificationSettingsV2 is disabled. To be released in conjunction with iOS/Web
-        resValue "bool", "useNotificationSettingsV1", "true"
-        resValue "bool", "useNotificationSettingsV2", "false"
+        def useNotificationSettingsV2 = false
+        buildConfigField "Boolean", "USE_NOTIFICATION_SETTINGS_V2", "${useNotificationSettingsV2}"
+        resValue "bool", "useNotificationSettingsV1", "${!useNotificationSettingsV2}"
+        resValue "bool", "useNotificationSettingsV2", "${useNotificationSettingsV2}"
 
         buildConfigField "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy", "outboundSessionKeySharingStrategy", "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy.WhenTyping"
 
@@ -366,7 +368,7 @@ dependencies {
     implementation 'com.facebook.stetho:stetho:1.6.0'
 
     // Phone number https://github.com/google/libphonenumber
-    implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.30'
+    implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.31'
 
     // rx
     implementation 'io.reactivex.rxjava2:rxkotlin:2.4.0'
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 cce0c2a66f..6b42f1e428 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
@@ -106,6 +106,7 @@ import im.vector.app.features.roomprofile.RoomProfileFragment
 import im.vector.app.features.roomprofile.alias.RoomAliasFragment
 import im.vector.app.features.roomprofile.banned.RoomBannedMemberListFragment
 import im.vector.app.features.roomprofile.members.RoomMemberListFragment
+import im.vector.app.features.roomprofile.notifications.RoomNotificationSettingsFragment
 import im.vector.app.features.roomprofile.permissions.RoomPermissionsFragment
 import im.vector.app.features.roomprofile.settings.RoomSettingsFragment
 import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleChooseRestrictedFragment
@@ -717,6 +718,11 @@ interface FragmentModule {
     @FragmentKey(RoomBannedMemberListFragment::class)
     fun bindRoomBannedMemberListFragment(fragment: RoomBannedMemberListFragment): Fragment
 
+    @Binds
+    @IntoMap
+    @FragmentKey(RoomNotificationSettingsFragment::class)
+    fun bindRoomNotificationSettingsFragment(fragment: RoomNotificationSettingsFragment): Fragment
+
     @Binds
     @IntoMap
     @FragmentKey(SearchFragment::class)
diff --git a/vector/src/main/java/im/vector/app/core/epoxy/profiles/notifications/NotificationSettingsFooterItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/profiles/notifications/NotificationSettingsFooterItem.kt
new file mode 100644
index 0000000000..4608f2b1ce
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/epoxy/profiles/notifications/NotificationSettingsFooterItem.kt
@@ -0,0 +1,62 @@
+/*
+ * 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.epoxy.profiles.notifications
+
+import android.widget.TextView
+import com.airbnb.epoxy.EpoxyAttribute
+import com.airbnb.epoxy.EpoxyModelClass
+import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
+import im.vector.app.core.epoxy.VectorEpoxyHolder
+import im.vector.app.core.epoxy.VectorEpoxyModel
+import im.vector.app.core.extensions.setTextWithColoredPart
+
+@EpoxyModelClass(layout = R.layout.item_notifications_footer)
+abstract class NotificationSettingsFooterItem : VectorEpoxyModel<NotificationSettingsFooterItem.Holder>() {
+
+    @EpoxyAttribute
+    var encrypted: Boolean = false
+
+    @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
+    var clickListener: ClickListener? = null
+
+    override fun bind(holder: Holder) {
+        super.bind(holder)
+        val accountSettingsString = holder.view.context.getString(R.string.room_settings_room_notifications_account_settings)
+        val manageNotificationsString = holder.view.context.getString(
+                R.string.room_settings_room_notifications_manage_notifications,
+                accountSettingsString
+        )
+        val manageNotificationsBuilder = StringBuilder(manageNotificationsString)
+        if (encrypted) {
+            val encryptionNotice = holder.view.context.getString(R.string.room_settings_room_notifications_encryption_notice)
+            manageNotificationsBuilder.appendLine().append(encryptionNotice)
+        }
+
+        holder.textView.setTextWithColoredPart(
+                manageNotificationsBuilder.toString(),
+                accountSettingsString,
+                underline = true
+        ) {
+            clickListener?.invoke(holder.textView)
+        }
+    }
+
+    class Holder : VectorEpoxyHolder() {
+        val textView by bind<TextView>(R.id.footerText)
+    }
+}
diff --git a/vector/src/main/java/im/vector/app/core/epoxy/profiles/notifications/RadioButtonItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/profiles/notifications/RadioButtonItem.kt
new file mode 100644
index 0000000000..37d16ab6b1
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/epoxy/profiles/notifications/RadioButtonItem.kt
@@ -0,0 +1,69 @@
+/*
+ * 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.epoxy.profiles.notifications
+
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.annotation.StringRes
+import androidx.core.content.ContextCompat
+import com.airbnb.epoxy.EpoxyAttribute
+import com.airbnb.epoxy.EpoxyModelClass
+import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
+import im.vector.app.core.epoxy.VectorEpoxyHolder
+import im.vector.app.core.epoxy.VectorEpoxyModel
+import im.vector.app.core.epoxy.onClick
+
+@EpoxyModelClass(layout = R.layout.item_radio)
+abstract class RadioButtonItem : VectorEpoxyModel<RadioButtonItem.Holder>() {
+
+    @EpoxyAttribute
+    var title: CharSequence? = null
+
+    @StringRes
+    @EpoxyAttribute
+    var titleRes: Int? = null
+
+    @EpoxyAttribute
+    var selected = false
+
+    @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
+    lateinit var listener: ClickListener
+
+    override fun bind(holder: Holder) {
+        super.bind(holder)
+        holder.view.onClick(listener)
+        if (titleRes != null) {
+            holder.titleText.setText(titleRes!!)
+        } else {
+            holder.titleText.text = title
+        }
+
+        if (selected) {
+            holder.radioImage.setImageDrawable(ContextCompat.getDrawable(holder.view.context, R.drawable.ic_radio_on))
+            holder.radioImage.contentDescription = holder.view.context.getString(R.string.a11y_checked)
+        } else {
+            holder.radioImage.setImageDrawable(ContextCompat.getDrawable(holder.view.context, R.drawable.ic_radio_off))
+            holder.radioImage.contentDescription = holder.view.context.getString(R.string.a11y_unchecked)
+        }
+    }
+
+    class Holder : VectorEpoxyHolder() {
+        val titleText by bind<TextView>(R.id.actionTitle)
+        val radioImage by bind<ImageView>(R.id.radioIcon)
+    }
+}
diff --git a/vector/src/main/java/im/vector/app/core/epoxy/profiles/notifications/TextHeaderItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/profiles/notifications/TextHeaderItem.kt
new file mode 100644
index 0000000000..2dfe7be2e6
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/epoxy/profiles/notifications/TextHeaderItem.kt
@@ -0,0 +1,50 @@
+/*
+ * 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.epoxy.profiles.notifications
+
+import android.widget.TextView
+import androidx.annotation.StringRes
+import com.airbnb.epoxy.EpoxyAttribute
+import com.airbnb.epoxy.EpoxyModelClass
+import im.vector.app.R
+import im.vector.app.core.epoxy.VectorEpoxyHolder
+import im.vector.app.core.epoxy.VectorEpoxyModel
+
+@EpoxyModelClass(layout = R.layout.item_text_header)
+abstract class TextHeaderItem : VectorEpoxyModel<TextHeaderItem.Holder>() {
+
+    @EpoxyAttribute
+    var text: String? = null
+
+    @StringRes
+    @EpoxyAttribute
+    var textRes: Int? = null
+
+    override fun bind(holder: Holder) {
+        super.bind(holder)
+        val textResource = textRes
+        if (textResource != null) {
+            holder.textView.setText(textResource)
+        } else {
+            holder.textView.text = text
+        }
+    }
+
+    class Holder : VectorEpoxyHolder() {
+        val textView by bind<TextView>(R.id.headerText)
+    }
+}
diff --git a/vector/src/main/java/im/vector/app/core/extensions/TextView.kt b/vector/src/main/java/im/vector/app/core/extensions/TextView.kt
index bb991ac32c..1c424f7071 100644
--- a/vector/src/main/java/im/vector/app/core/extensions/TextView.kt
+++ b/vector/src/main/java/im/vector/app/core/extensions/TextView.kt
@@ -65,6 +65,23 @@ fun TextView.setTextWithColoredPart(@StringRes fullTextRes: Int,
     val coloredPart = resources.getString(coloredTextRes)
     // Insert colored part into the full text
     val fullText = resources.getString(fullTextRes, coloredPart)
+
+    setTextWithColoredPart(fullText, coloredPart, colorAttribute, underline, onClick)
+}
+
+/**
+ * Set text with a colored part
+ * @param fullText The full text.
+ * @param coloredPart The colored part of the text
+ * @param colorAttribute attribute of the color. Default to colorPrimary
+ * @param underline true to also underline the text. Default to false
+ * @param onClick attributes to handle click on the colored part if needed
+ */
+fun TextView.setTextWithColoredPart(fullText: String,
+                                    coloredPart: String,
+                                    @AttrRes colorAttribute: Int = R.attr.colorPrimary,
+                                    underline: Boolean = false,
+                                    onClick: (() -> Unit)? = null) {
     val color = ThemeUtils.getColor(context, colorAttribute)
 
     val foregroundSpan = ForegroundColorSpan(color)
diff --git a/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberPresenter.kt b/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberPresenter.kt
index ecc607f08d..aa0c10e0a2 100644
--- a/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberPresenter.kt
+++ b/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberPresenter.kt
@@ -71,6 +71,23 @@ class AutocompleteMemberPresenter @AssistedInject constructor(context: Context,
         val members = room.getRoomMembers(queryParams)
                 .asSequence()
                 .sortedBy { it.displayName }
+                .disambiguate()
         controller.setData(members.toList())
     }
 }
+
+private fun Sequence<RoomMemberSummary>.disambiguate(): Sequence<RoomMemberSummary> {
+    val displayNames = hashMapOf<String, Int>().also { map ->
+        for (item in this) {
+            item.displayName?.lowercase()?.also { displayName ->
+                map[displayName] = map.getOrPut(displayName, { 0 }) + 1
+            }
+        }
+    }
+
+    return map { roomMemberSummary ->
+        if (displayNames[roomMemberSummary.displayName?.lowercase()] ?: 0 > 1) {
+            roomMemberSummary.copy(displayName = roomMemberSummary.displayName + " " + roomMemberSummary.userId)
+        } else roomMemberSummary
+    }
+}
diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt
index d3719a22a6..f71dcc0635 100644
--- a/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt
@@ -30,6 +30,7 @@ import android.util.Rational
 import android.view.MenuItem
 import android.view.View
 import android.view.WindowManager
+import androidx.annotation.StringRes
 import androidx.core.content.ContextCompat
 import androidx.core.content.getSystemService
 import androidx.core.view.isInvisible
@@ -66,6 +67,7 @@ import org.matrix.android.sdk.api.logger.LoggerTag
 import org.matrix.android.sdk.api.session.call.CallState
 import org.matrix.android.sdk.api.session.call.MxPeerConnectionState
 import org.matrix.android.sdk.api.session.call.TurnServerResponse
+import org.matrix.android.sdk.api.session.room.model.call.EndCallReason
 import org.webrtc.EglBase
 import org.webrtc.RendererCommon
 import timber.log.Timber
@@ -136,6 +138,12 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
             renderState(it)
         }
 
+        callViewModel.asyncSubscribe(this, VectorCallViewState::callState) {
+            if (it is CallState.Ended) {
+                handleCallEnded(it)
+            }
+        }
+
         callViewModel.viewEvents
                 .observe()
                 .observeOn(AndroidSchedulers.mainThread())
@@ -321,9 +329,16 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
                 }
             }
             is CallState.Ended     -> {
-                finish()
+                views.fullscreenRenderer.isVisible = false
+                views.pipRendererWrapper.isVisible = false
+                views.callInfoGroup.isVisible = true
+                views.callToolbar.setSubtitle(R.string.call_ended)
+                configureCallInfo(state)
             }
-            null                   -> {
+            else                   -> {
+                views.fullscreenRenderer.isVisible = false
+                views.pipRendererWrapper.isVisible = false
+                views.callInfoGroup.isInvisible = true
             }
         }
     }
@@ -343,7 +358,6 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
             is CallState.Answering -> {
                 views.fullscreenRenderer.isVisible = false
                 views.callInfoGroup.isVisible = false
-                // showLoading()
             }
             is CallState.Connected -> {
                 if (callState.iceConnectionState == MxPeerConnectionState.CONNECTED) {
@@ -358,17 +372,47 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
                         views.callInfoGroup.isVisible = false
                     }
                 } else {
-                    // showLoading()
+                    views.callInfoGroup.isVisible = false
                 }
             }
-            is CallState.Ended     -> {
-                finish()
-            }
-            null                   -> {
+            else                   -> {
+                views.fullscreenRenderer.isVisible = false
+                views.callInfoGroup.isVisible = false
             }
         }
     }
 
+    private fun handleCallEnded(callState: CallState.Ended) {
+        if (isInPictureInPictureModeSafe()) {
+            val startIntent = Intent(this, VectorCallActivity::class.java).apply {
+                flags = Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
+            }
+            startActivity(startIntent)
+        }
+        when (callState.reason) {
+            EndCallReason.USER_BUSY      -> {
+                showEndCallDialog(R.string.call_ended_user_busy_title, R.string.call_ended_user_busy_description)
+            }
+            EndCallReason.INVITE_TIMEOUT -> {
+                showEndCallDialog(R.string.call_ended_invite_timeout_title, R.string.call_error_user_not_responding)
+            }
+            else                         -> {
+                finish()
+            }
+        }
+    }
+
+    private fun showEndCallDialog(@StringRes title: Int, @StringRes description: Int) {
+        MaterialAlertDialogBuilder(this)
+                .setTitle(title)
+                .setMessage(description)
+                .setNegativeButton(R.string.ok, null)
+                .setOnDismissListener {
+                    finish()
+                }
+                .show()
+    }
+
     private fun configureCallInfo(state: VectorCallViewState, blurAvatar: Boolean = false) {
         state.callInfo?.opponentUserItem?.let {
             val colorFilter = ContextCompat.getColor(this, R.color.bg_call_screen_blur)
@@ -473,9 +517,6 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
     private fun handleViewEvents(event: VectorCallViewEvents?) {
         Timber.tag(loggerTag.value).v("handleViewEvents $event")
         when (event) {
-            VectorCallViewEvents.DismissNoCall             -> {
-                finish()
-            }
             is VectorCallViewEvents.ConnectionTimeout      -> {
                 onErrorTimoutConnect(event.turn)
             }
@@ -498,7 +539,7 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
         // TODO ask to use default stun, etc...
         MaterialAlertDialogBuilder(this)
                 .setTitle(R.string.call_failed_no_connection)
-                .setMessage(getString(R.string.call_failed_no_connection_description))
+                .setMessage(R.string.call_failed_no_connection_description)
                 .setNegativeButton(R.string.ok) { _, _ ->
                     callViewModel.handle(VectorCallViewActions.EndCall)
                 }
diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallViewEvents.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallViewEvents.kt
index 91c3154d0a..9f19429c00 100644
--- a/vector/src/main/java/im/vector/app/features/call/VectorCallViewEvents.kt
+++ b/vector/src/main/java/im/vector/app/features/call/VectorCallViewEvents.kt
@@ -22,7 +22,6 @@ import org.matrix.android.sdk.api.session.call.TurnServerResponse
 
 sealed class VectorCallViewEvents : VectorViewEvents {
 
-    object DismissNoCall : VectorCallViewEvents()
     data class ConnectionTimeout(val turn: TurnServerResponse?) : VectorCallViewEvents()
     data class ShowSoundDeviceChooser(
             val available: Set<CallAudioManager.Device>,
diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt
index cfe66c187e..63ba83bdbc 100644
--- a/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt
@@ -137,9 +137,7 @@ class VectorCallViewModel @AssistedInject constructor(
     private val currentCallListener = object : WebRtcCallManager.CurrentCallListener {
 
         override fun onCurrentCallChange(call: WebRtcCall?) {
-            if (call == null) {
-                _viewEvents.post(VectorCallViewEvents.DismissNoCall)
-            } else {
+            if (call != null) {
                 updateOtherKnownCall(call)
             }
         }
diff --git a/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCall.kt b/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCall.kt
index db4b313f86..2d39fda2e3 100644
--- a/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCall.kt
+++ b/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCall.kt
@@ -39,7 +39,9 @@ import io.reactivex.disposables.Disposable
 import io.reactivex.subjects.PublishSubject
 import io.reactivex.subjects.ReplaySubject
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Deferred
 import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.async
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
@@ -91,6 +93,7 @@ private const val STREAM_ID = "userMedia"
 private const val AUDIO_TRACK_ID = "${STREAM_ID}a0"
 private const val VIDEO_TRACK_ID = "${STREAM_ID}v0"
 private val DEFAULT_AUDIO_CONSTRAINTS = MediaConstraints()
+private const val INVITE_TIMEOUT_IN_MS = 60_000L
 
 private val loggerTag = LoggerTag("WebRtcCall", LoggerTag.VOIP)
 
@@ -165,6 +168,8 @@ class WebRtcCall(
         }
     }
 
+    private var inviteTimeout: Deferred<Unit>? = null
+
     // Mute status
     var micMuted = false
         private set
@@ -239,6 +244,10 @@ class WebRtcCall(
                 if (mxCall.state == CallState.CreateOffer) {
                     // send offer to peer
                     mxCall.offerSdp(sessionDescription.description)
+                    inviteTimeout = async {
+                        delay(INVITE_TIMEOUT_IN_MS)
+                        endCall(EndCallReason.INVITE_TIMEOUT)
+                    }
                 } else {
                     mxCall.negotiate(sessionDescription.description, SdpType.OFFER)
                 }
@@ -807,7 +816,7 @@ class WebRtcCall(
                 return@launch
             }
             val reject = mxCall.state is CallState.LocalRinging
-            terminate(EndCallReason.USER_HANGUP, reject)
+            terminate(reason, reject)
             if (reject) {
                 mxCall.reject()
             } else {
@@ -824,6 +833,8 @@ class WebRtcCall(
             val cameraManager = context.getSystemService<CameraManager>()!!
             cameraManager.unregisterAvailabilityCallback(cameraAvailabilityCallback)
         }
+        inviteTimeout?.cancel()
+        inviteTimeout = null
         mxCall.state = CallState.Ended(reason ?: EndCallReason.USER_HANGUP)
         release()
         onCallEnded(callId, reason ?: EndCallReason.USER_HANGUP, rejected)
@@ -845,6 +856,8 @@ class WebRtcCall(
     }
 
     fun onCallAnswerReceived(callAnswerContent: CallAnswerContent) {
+        inviteTimeout?.cancel()
+        inviteTimeout = null
         sessionScope?.launch(dispatcher) {
             Timber.tag(loggerTag.value).v("onCallAnswerReceived ${callAnswerContent.callId}")
             val sdp = SessionDescription(SessionDescription.Type.ANSWER, callAnswerContent.answer.sdp)
diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt
index 4a563b563a..9ae6d4c39f 100644
--- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt
@@ -143,6 +143,8 @@ class HomeActivity :
         }
     }
 
+    override fun getCoordinatorLayout() = views.coordinatorLayout
+
     override fun getBinding() = ActivityHomeBinding.inflate(layoutInflater)
 
     override fun injectWith(injector: ScreenComponent) {
diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionViewState.kt b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionViewState.kt
new file mode 100644
index 0000000000..d063e07ed7
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionViewState.kt
@@ -0,0 +1,24 @@
+/*
+ * 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.home.room.list.actions
+
+import im.vector.app.features.roomprofile.notifications.RoomNotificationSettingsViewState
+
+data class RoomListQuickActionViewState(
+        val roomListActionsArgs: RoomListActionsArgs,
+        val notificationSettingsViewState: RoomNotificationSettingsViewState
+)
diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsBottomSheet.kt b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsBottomSheet.kt
index 94f9aaf496..8c1bdc086f 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsBottomSheet.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsBottomSheet.kt
@@ -22,15 +22,23 @@ import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
 import androidx.recyclerview.widget.RecyclerView
+import com.airbnb.mvrx.args
 import com.airbnb.mvrx.fragmentViewModel
 import com.airbnb.mvrx.withState
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import im.vector.app.R
 import im.vector.app.core.di.ScreenComponent
+import im.vector.app.core.error.ErrorFormatter
 import im.vector.app.core.extensions.cleanup
 import im.vector.app.core.extensions.configureWith
 import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
 import im.vector.app.databinding.BottomSheetGenericListBinding
 import im.vector.app.features.navigation.Navigator
+import im.vector.app.features.roomprofile.notifications.RoomNotificationSettingsAction
+import im.vector.app.features.roomprofile.notifications.RoomNotificationSettingsViewEvents
+import im.vector.app.features.roomprofile.notifications.RoomNotificationSettingsViewModel
 import kotlinx.parcelize.Parcelize
+import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
 import javax.inject.Inject
 
 @Parcelize
@@ -54,11 +62,13 @@ class RoomListQuickActionsBottomSheet :
 
     private lateinit var sharedActionViewModel: RoomListQuickActionsSharedActionViewModel
     @Inject lateinit var sharedViewPool: RecyclerView.RecycledViewPool
-    @Inject lateinit var roomListActionsViewModelFactory: RoomListQuickActionsViewModel.Factory
+    @Inject lateinit var roomNotificationSettingsViewModelFactory: RoomNotificationSettingsViewModel.Factory
     @Inject lateinit var roomListActionsEpoxyController: RoomListQuickActionsEpoxyController
     @Inject lateinit var navigator: Navigator
+    @Inject lateinit var errorFormatter: ErrorFormatter
 
-    private val viewModel: RoomListQuickActionsViewModel by fragmentViewModel(RoomListQuickActionsViewModel::class)
+    private val roomListActionsArgs: RoomListActionsArgs by args()
+    private val viewModel: RoomNotificationSettingsViewModel by fragmentViewModel(RoomNotificationSettingsViewModel::class)
 
     override val showExpanded = true
 
@@ -80,6 +90,12 @@ class RoomListQuickActionsBottomSheet :
                 disableItemAnimation = true
         )
         roomListActionsEpoxyController.listener = this
+
+        viewModel.observeViewEvents {
+            when (it) {
+                is RoomNotificationSettingsViewEvents.Failure -> displayErrorDialog(it.throwable)
+            }
+        }
     }
 
     override fun onDestroyView() {
@@ -89,7 +105,11 @@ class RoomListQuickActionsBottomSheet :
     }
 
     override fun invalidate() = withState(viewModel) {
-        roomListActionsEpoxyController.setData(it)
+        val roomListViewState = RoomListQuickActionViewState(
+                roomListActionsArgs,
+                it
+        )
+        roomListActionsEpoxyController.setData(roomListViewState)
         super.invalidate()
     }
 
@@ -103,6 +123,10 @@ class RoomListQuickActionsBottomSheet :
         }
     }
 
+    override fun didSelectRoomNotificationState(roomNotificationState: RoomNotificationState) {
+        viewModel.handle(RoomNotificationSettingsAction.SelectNotificationState(roomNotificationState))
+    }
+
     companion object {
         fun newInstance(roomId: String, mode: RoomListActionsArgs.Mode): RoomListQuickActionsBottomSheet {
             return RoomListQuickActionsBottomSheet().apply {
@@ -110,4 +134,12 @@ class RoomListQuickActionsBottomSheet :
             }
         }
     }
+
+    private fun displayErrorDialog(throwable: Throwable) {
+        MaterialAlertDialogBuilder(requireActivity())
+                .setTitle(R.string.dialog_title_error)
+                .setMessage(errorFormatter.toHumanReadable(throwable))
+                .setPositiveButton(R.string.ok, null)
+                .show()
+    }
 }
diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt
index 4604159338..7e39156b18 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt
@@ -15,13 +15,19 @@
  */
 package im.vector.app.features.home.room.list.actions
 
+import androidx.annotation.StringRes
 import com.airbnb.epoxy.TypedEpoxyController
+import im.vector.app.BuildConfig
+import im.vector.app.R
 import im.vector.app.core.epoxy.bottomSheetDividerItem
 import im.vector.app.core.epoxy.bottomsheet.bottomSheetActionItem
 import im.vector.app.core.epoxy.bottomsheet.bottomSheetRoomPreviewItem
+import im.vector.app.core.epoxy.profiles.notifications.radioButtonItem
 import im.vector.app.core.resources.ColorProvider
 import im.vector.app.core.resources.StringProvider
 import im.vector.app.features.home.AvatarRenderer
+import im.vector.app.features.roomprofile.notifications.notificationOptions
+import im.vector.app.features.roomprofile.notifications.notificationStateMapped
 import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
 import org.matrix.android.sdk.api.util.toMatrixItem
 import javax.inject.Inject
@@ -33,16 +39,19 @@ class RoomListQuickActionsEpoxyController @Inject constructor(
         private val avatarRenderer: AvatarRenderer,
         private val colorProvider: ColorProvider,
         private val stringProvider: StringProvider
-) : TypedEpoxyController<RoomListQuickActionsState>() {
+) : TypedEpoxyController<RoomListQuickActionViewState>() {
 
     var listener: Listener? = null
 
-    override fun buildModels(state: RoomListQuickActionsState) {
-        val roomSummary = state.roomSummary() ?: return
+    override fun buildModels(state: RoomListQuickActionViewState) {
+        val notificationViewState = state.notificationSettingsViewState
+        val roomSummary = notificationViewState.roomSummary() ?: return
         val host = this
-        val showAll = state.mode == RoomListActionsArgs.Mode.FULL
+        val isV2 = BuildConfig.USE_NOTIFICATION_SETTINGS_V2
+        // V2 always shows full details as we no longer display the sheet from RoomProfile > Notifications
+        val showFull = state.roomListActionsArgs.mode == RoomListActionsArgs.Mode.FULL || isV2
 
-        if (showAll) {
+        if (showFull) {
             // Preview, favorite, settings
             bottomSheetRoomPreviewItem {
                 id("room_preview")
@@ -63,17 +72,38 @@ class RoomListQuickActionsEpoxyController @Inject constructor(
             }
         }
 
-        val selectedRoomState = state.roomNotificationState()
-        RoomListQuickActionsSharedAction.NotificationsAllNoisy(roomSummary.roomId).toBottomSheetItem(0, selectedRoomState)
-        RoomListQuickActionsSharedAction.NotificationsAll(roomSummary.roomId).toBottomSheetItem(1, selectedRoomState)
-        RoomListQuickActionsSharedAction.NotificationsMentionsOnly(roomSummary.roomId).toBottomSheetItem(2, selectedRoomState)
-        RoomListQuickActionsSharedAction.NotificationsMute(roomSummary.roomId).toBottomSheetItem(3, selectedRoomState)
+        if (isV2) {
+            notificationViewState.notificationOptions.forEach {  notificationState ->
+                val title = titleForNotificationState(notificationState)
+                radioButtonItem {
+                    id(notificationState.name)
+                    titleRes(title)
+                    selected(notificationViewState.notificationStateMapped() == notificationState)
+                    listener {
+                    host.listener?.didSelectRoomNotificationState(notificationState)
+                    }
+                }
+            }
+        } else {
+            val selectedRoomState = notificationViewState.notificationState()
+            RoomListQuickActionsSharedAction.NotificationsAllNoisy(roomSummary.roomId).toBottomSheetItem(0, selectedRoomState)
+            RoomListQuickActionsSharedAction.NotificationsAll(roomSummary.roomId).toBottomSheetItem(1, selectedRoomState)
+            RoomListQuickActionsSharedAction.NotificationsMentionsOnly(roomSummary.roomId).toBottomSheetItem(2, selectedRoomState)
+            RoomListQuickActionsSharedAction.NotificationsMute(roomSummary.roomId).toBottomSheetItem(3, selectedRoomState)
+        }
 
-        if (showAll) {
-            RoomListQuickActionsSharedAction.Leave(roomSummary.roomId).toBottomSheetItem(5)
+        if (showFull) {
+            RoomListQuickActionsSharedAction.Leave(roomSummary.roomId, showIcon = !isV2).toBottomSheetItem(5)
         }
     }
 
+    @StringRes
+    private fun titleForNotificationState(notificationState: RoomNotificationState): Int? = when (notificationState) {
+        RoomNotificationState.ALL_MESSAGES_NOISY -> R.string.room_settings_all_messages
+        RoomNotificationState.MENTIONS_ONLY      -> R.string.room_settings_mention_and_keyword_only
+        RoomNotificationState.MUTE               -> R.string.room_settings_none
+        else -> null
+    }
     private fun RoomListQuickActionsSharedAction.toBottomSheetItem(index: Int, roomNotificationState: RoomNotificationState? = null) {
         val host = this@RoomListQuickActionsEpoxyController
         val selected = when (this) {
@@ -86,7 +116,11 @@ class RoomListQuickActionsEpoxyController @Inject constructor(
         return bottomSheetActionItem {
             id("action_$index")
             selected(selected)
-            iconRes(iconResId)
+            if (iconResId != null) {
+                iconRes(iconResId)
+            } else {
+                showIcon(false)
+            }
             textRes(titleRes)
             destructive(this@toBottomSheetItem.destructive)
             listener { host.listener?.didSelectMenuAction(this@toBottomSheetItem) }
@@ -95,5 +129,6 @@ class RoomListQuickActionsEpoxyController @Inject constructor(
 
     interface Listener {
         fun didSelectMenuAction(quickAction: RoomListQuickActionsSharedAction)
+        fun didSelectRoomNotificationState(roomNotificationState: RoomNotificationState)
     }
 }
diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsSharedAction.kt b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsSharedAction.kt
index 075dca0c52..6f93599d02 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsSharedAction.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsSharedAction.kt
@@ -23,7 +23,7 @@ import im.vector.app.core.platform.VectorSharedAction
 
 sealed class RoomListQuickActionsSharedAction(
         @StringRes val titleRes: Int,
-        @DrawableRes val iconResId: Int,
+        @DrawableRes val iconResId: Int?,
         val destructive: Boolean = false)
     : VectorSharedAction {
 
@@ -60,9 +60,9 @@ sealed class RoomListQuickActionsSharedAction(
             R.string.room_list_quick_actions_favorite_add,
             R.drawable.ic_star_24dp)
 
-    data class Leave(val roomId: String) : RoomListQuickActionsSharedAction(
+    data class Leave(val roomId: String, val showIcon: Boolean = true) : RoomListQuickActionsSharedAction(
             R.string.room_list_quick_actions_leave,
-            R.drawable.ic_room_actions_leave,
+            if (showIcon) R.drawable.ic_room_actions_leave else null,
             true
     )
 }
diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsState.kt b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsState.kt
deleted file mode 100644
index 2731620cec..0000000000
--- a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsState.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2019 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.home.room.list.actions
-
-import com.airbnb.mvrx.Async
-import com.airbnb.mvrx.MvRxState
-import com.airbnb.mvrx.Uninitialized
-import org.matrix.android.sdk.api.session.room.model.RoomSummary
-import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
-
-data class RoomListQuickActionsState(
-        val roomId: String,
-        val mode: RoomListActionsArgs.Mode,
-        val roomSummary: Async<RoomSummary> = Uninitialized,
-        val roomNotificationState: Async<RoomNotificationState> = Uninitialized
-) : MvRxState {
-
-    constructor(args: RoomListActionsArgs) : this(roomId = args.roomId, mode = args.mode)
-}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsViewModel.kt
deleted file mode 100644
index 75e9459d2c..0000000000
--- a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsViewModel.kt
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2019 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.home.room.list.actions
-
-import com.airbnb.mvrx.FragmentViewModelContext
-import com.airbnb.mvrx.MvRxViewModelFactory
-import com.airbnb.mvrx.ViewModelContext
-import dagger.assisted.Assisted
-import dagger.assisted.AssistedInject
-import dagger.assisted.AssistedFactory
-import im.vector.app.core.platform.EmptyAction
-import im.vector.app.core.platform.EmptyViewEvents
-import im.vector.app.core.platform.VectorViewModel
-import org.matrix.android.sdk.api.session.Session
-import org.matrix.android.sdk.rx.rx
-import org.matrix.android.sdk.rx.unwrap
-
-class RoomListQuickActionsViewModel @AssistedInject constructor(@Assisted initialState: RoomListQuickActionsState,
-                                                                session: Session
-) : VectorViewModel<RoomListQuickActionsState, EmptyAction, EmptyViewEvents>(initialState) {
-
-    @AssistedFactory
-    interface Factory {
-        fun create(initialState: RoomListQuickActionsState): RoomListQuickActionsViewModel
-    }
-
-    companion object : MvRxViewModelFactory<RoomListQuickActionsViewModel, RoomListQuickActionsState> {
-
-        @JvmStatic
-        override fun create(viewModelContext: ViewModelContext, state: RoomListQuickActionsState): RoomListQuickActionsViewModel? {
-            val fragment: RoomListQuickActionsBottomSheet = (viewModelContext as FragmentViewModelContext).fragment()
-            return fragment.roomListActionsViewModelFactory.create(state)
-        }
-    }
-
-    private val room = session.getRoom(initialState.roomId)!!
-
-    init {
-        observeRoomSummary()
-        observeNotificationState()
-    }
-
-    private fun observeNotificationState() {
-        room
-                .rx()
-                .liveNotificationState()
-                .execute {
-                    copy(roomNotificationState = it)
-                }
-    }
-
-    private fun observeRoomSummary() {
-        room
-                .rx()
-                .liveRoomSummary()
-                .unwrap()
-                .execute {
-                    copy(roomSummary = it)
-                }
-    }
-
-    override fun handle(action: EmptyAction) {
-        // No op
-    }
-}
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileActivity.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileActivity.kt
index 07ba442621..d28878283f 100644
--- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileActivity.kt
@@ -39,6 +39,7 @@ import im.vector.app.features.roomprofile.banned.RoomBannedMemberListFragment
 import im.vector.app.features.roomprofile.members.RoomMemberListFragment
 import im.vector.app.features.roomprofile.settings.RoomSettingsFragment
 import im.vector.app.features.roomprofile.alias.RoomAliasFragment
+import im.vector.app.features.roomprofile.notifications.RoomNotificationSettingsFragment
 import im.vector.app.features.roomprofile.permissions.RoomPermissionsFragment
 import im.vector.app.features.roomprofile.uploads.RoomUploadsFragment
 import javax.inject.Inject
@@ -107,12 +108,13 @@ class RoomProfileActivity :
                 .observe()
                 .subscribe { sharedAction ->
                     when (sharedAction) {
-                        RoomProfileSharedAction.OpenRoomMembers             -> openRoomMembers()
-                        RoomProfileSharedAction.OpenRoomSettings            -> openRoomSettings()
-                        RoomProfileSharedAction.OpenRoomAliasesSettings     -> openRoomAlias()
-                        RoomProfileSharedAction.OpenRoomPermissionsSettings -> openRoomPermissions()
-                        RoomProfileSharedAction.OpenRoomUploads             -> openRoomUploads()
-                        RoomProfileSharedAction.OpenBannedRoomMembers       -> openBannedRoomMembers()
+                        RoomProfileSharedAction.OpenRoomMembers                 -> openRoomMembers()
+                        RoomProfileSharedAction.OpenRoomSettings                -> openRoomSettings()
+                        RoomProfileSharedAction.OpenRoomAliasesSettings         -> openRoomAlias()
+                        RoomProfileSharedAction.OpenRoomPermissionsSettings     -> openRoomPermissions()
+                        RoomProfileSharedAction.OpenRoomUploads                 -> openRoomUploads()
+                        RoomProfileSharedAction.OpenBannedRoomMembers        -> openBannedRoomMembers()
+                        RoomProfileSharedAction.OpenRoomNotificationSettings -> openRoomNotificationSettings()
                     }.exhaustive
                 }
                 .disposeOnDestroy()
@@ -162,6 +164,10 @@ class RoomProfileActivity :
         addFragmentToBackstack(R.id.simpleFragmentContainer, RoomBannedMemberListFragment::class.java, roomProfileArgs)
     }
 
+    private fun openRoomNotificationSettings() {
+        addFragmentToBackstack(R.id.simpleFragmentContainer, RoomNotificationSettingsFragment::class.java, roomProfileArgs)
+    }
+
     override fun configure(toolbar: MaterialToolbar) {
         configureToolbar(toolbar)
     }
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt
index 14ddf896ca..4b37d038b5 100644
--- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt
@@ -30,6 +30,7 @@ import com.airbnb.mvrx.args
 import com.airbnb.mvrx.fragmentViewModel
 import com.airbnb.mvrx.withState
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import im.vector.app.BuildConfig
 import im.vector.app.R
 import im.vector.app.core.animations.AppBarStateChangeListener
 import im.vector.app.core.animations.MatrixItemAppBarStateChangeListener
@@ -253,9 +254,13 @@ class RoomProfileFragment @Inject constructor(
     }
 
     override fun onNotificationsClicked() {
-        RoomListQuickActionsBottomSheet
-                .newInstance(roomProfileArgs.roomId, RoomListActionsArgs.Mode.NOTIFICATIONS)
-                .show(childFragmentManager, "ROOM_PROFILE_NOTIFICATIONS")
+        if (BuildConfig.USE_NOTIFICATION_SETTINGS_V2) {
+            roomProfileSharedActionViewModel.post(RoomProfileSharedAction.OpenRoomNotificationSettings)
+        } else {
+            RoomListQuickActionsBottomSheet
+                    .newInstance(roomProfileArgs.roomId, RoomListActionsArgs.Mode.NOTIFICATIONS)
+                    .show(childFragmentManager, "ROOM_PROFILE_NOTIFICATIONS")
+        }
     }
 
     override fun onUploadsClicked() {
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileSharedAction.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileSharedAction.kt
index 2a5775d1af..eb4ab56634 100644
--- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileSharedAction.kt
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileSharedAction.kt
@@ -28,4 +28,5 @@ sealed class RoomProfileSharedAction : VectorSharedAction {
     object OpenRoomUploads : RoomProfileSharedAction()
     object OpenRoomMembers : RoomProfileSharedAction()
     object OpenBannedRoomMembers : RoomProfileSharedAction()
+    object OpenRoomNotificationSettings : RoomProfileSharedAction()
 }
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsAction.kt b/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsAction.kt
new file mode 100644
index 0000000000..10c8861183
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsAction.kt
@@ -0,0 +1,24 @@
+/*
+ * 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.roomprofile.notifications
+
+import im.vector.app.core.platform.VectorViewModelAction
+import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
+
+sealed class RoomNotificationSettingsAction : VectorViewModelAction {
+    data class SelectNotificationState(val notificationState: RoomNotificationState): RoomNotificationSettingsAction()
+}
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsController.kt
new file mode 100644
index 0000000000..9a2085a7e8
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsController.kt
@@ -0,0 +1,76 @@
+/*
+ * 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.roomprofile.notifications
+
+import androidx.annotation.StringRes
+import com.airbnb.epoxy.TypedEpoxyController
+import im.vector.app.R
+import im.vector.app.core.epoxy.profiles.notifications.notificationSettingsFooterItem
+import im.vector.app.core.epoxy.profiles.notifications.radioButtonItem
+import im.vector.app.core.epoxy.profiles.notifications.textHeaderItem
+import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
+import javax.inject.Inject
+
+class RoomNotificationSettingsController @Inject constructor() : TypedEpoxyController<RoomNotificationSettingsViewState>() {
+
+    interface Callback {
+        fun didSelectRoomNotificationState(roomNotificationState: RoomNotificationState)
+        fun didSelectAccountSettingsLink()
+    }
+
+    var callback: Callback? = null
+
+    init {
+        setData(null)
+    }
+
+    override fun buildModels(data: RoomNotificationSettingsViewState?) {
+        val host = this
+        data ?: return
+
+        textHeaderItem {
+            id("roomNotificationSettingsHeader")
+            textRes(R.string.room_settings_room_notifications_notify_me)
+        }
+        data.notificationOptions.forEach {  notificationState ->
+            val title = titleForNotificationState(notificationState)
+            radioButtonItem {
+                id(notificationState.name)
+                titleRes(title)
+                selected(data.notificationStateMapped() == notificationState)
+                listener {
+                    host.callback?.didSelectRoomNotificationState(notificationState)
+                }
+            }
+        }
+        notificationSettingsFooterItem {
+            id("roomNotificationSettingsFooter")
+            encrypted(data.roomSummary()?.isEncrypted == true)
+            clickListener {
+                host.callback?.didSelectAccountSettingsLink()
+            }
+        }
+    }
+
+    @StringRes
+    private fun titleForNotificationState(notificationState: RoomNotificationState): Int? = when (notificationState) {
+        RoomNotificationState.ALL_MESSAGES_NOISY -> R.string.room_settings_all_messages
+        RoomNotificationState.MENTIONS_ONLY      -> R.string.room_settings_mention_and_keyword_only
+        RoomNotificationState.MUTE               -> R.string.room_settings_none
+        else -> null
+    }
+}
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsFragment.kt
new file mode 100644
index 0000000000..ce0fde32c6
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsFragment.kt
@@ -0,0 +1,99 @@
+/*
+ * 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.roomprofile.notifications
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.core.view.isVisible
+import com.airbnb.mvrx.fragmentViewModel
+import com.airbnb.mvrx.withState
+import im.vector.app.R
+import im.vector.app.core.extensions.cleanup
+import im.vector.app.core.extensions.configureWith
+import im.vector.app.core.platform.VectorBaseFragment
+import im.vector.app.databinding.FragmentRoomSettingGenericBinding
+import im.vector.app.features.home.AvatarRenderer
+import im.vector.app.features.settings.VectorSettingsActivity
+import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
+import org.matrix.android.sdk.api.util.toMatrixItem
+import javax.inject.Inject
+
+class RoomNotificationSettingsFragment @Inject constructor(
+        val viewModelFactory: RoomNotificationSettingsViewModel.Factory,
+        private val roomNotificationSettingsController: RoomNotificationSettingsController,
+        private val avatarRenderer: AvatarRenderer
+) : VectorBaseFragment<FragmentRoomSettingGenericBinding>(),
+        RoomNotificationSettingsController.Callback {
+
+    private val viewModel: RoomNotificationSettingsViewModel by fragmentViewModel()
+
+    override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentRoomSettingGenericBinding {
+        return FragmentRoomSettingGenericBinding.inflate(inflater, container, false)
+    }
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+        setupToolbar(views.roomSettingsToolbar)
+        roomNotificationSettingsController.callback = this
+        views.roomSettingsRecyclerView.configureWith(roomNotificationSettingsController, hasFixedSize = true)
+        setupWaitingView()
+        observeViewEvents()
+    }
+
+    override fun onDestroyView() {
+        views.roomSettingsRecyclerView.cleanup()
+        roomNotificationSettingsController.callback = null
+        super.onDestroyView()
+    }
+
+    private fun setupWaitingView() {
+        views.waitingView.waitingStatusText.setText(R.string.please_wait)
+        views.waitingView.waitingStatusText.isVisible = true
+    }
+
+    private fun observeViewEvents() {
+        viewModel.observeViewEvents {
+            when (it) {
+                is RoomNotificationSettingsViewEvents.Failure -> displayErrorDialog(it.throwable)
+            }
+        }
+    }
+
+    override fun invalidate() = withState(viewModel) { viewState ->
+        roomNotificationSettingsController.setData(viewState)
+        views.waitingView.root.isVisible = viewState.isLoading
+        renderRoomSummary(viewState)
+    }
+
+    override fun didSelectRoomNotificationState(roomNotificationState: RoomNotificationState) {
+        viewModel.handle(RoomNotificationSettingsAction.SelectNotificationState(roomNotificationState))
+    }
+
+    override fun didSelectAccountSettingsLink() {
+        navigator.openSettings(requireContext(), VectorSettingsActivity.EXTRA_DIRECT_ACCESS_NOTIFICATIONS)
+    }
+
+    private fun renderRoomSummary(state: RoomNotificationSettingsViewState) {
+        state.roomSummary()?.let {
+            views.roomSettingsToolbarTitleView.text = it.displayName
+            avatarRenderer.render(it.toMatrixItem(), views.roomSettingsToolbarAvatarImageView)
+            views.roomSettingsDecorationToolbarAvatarImageView.render(it.roomEncryptionTrustLevel)
+        }
+    }
+}
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsViewEvents.kt b/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsViewEvents.kt
new file mode 100644
index 0000000000..dda858283b
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsViewEvents.kt
@@ -0,0 +1,23 @@
+/*
+ * 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.roomprofile.notifications
+
+import im.vector.app.core.platform.VectorViewEvents
+
+sealed class RoomNotificationSettingsViewEvents : VectorViewEvents {
+    data class Failure(val throwable: Throwable) : RoomNotificationSettingsViewEvents()
+}
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsViewModel.kt
new file mode 100644
index 0000000000..dd0535f51b
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsViewModel.kt
@@ -0,0 +1,107 @@
+/*
+ * 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.roomprofile.notifications
+
+import androidx.lifecycle.viewModelScope
+import com.airbnb.mvrx.FragmentViewModelContext
+import com.airbnb.mvrx.MvRxViewModelFactory
+import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.ViewModelContext
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import im.vector.app.core.platform.VectorViewModel
+import im.vector.app.features.home.room.list.actions.RoomListQuickActionsBottomSheet
+import kotlinx.coroutines.launch
+import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.rx.rx
+import org.matrix.android.sdk.rx.unwrap
+
+class RoomNotificationSettingsViewModel @AssistedInject constructor(
+        @Assisted initialState: RoomNotificationSettingsViewState,
+        session: Session
+) : VectorViewModel<RoomNotificationSettingsViewState, RoomNotificationSettingsAction, RoomNotificationSettingsViewEvents>(initialState) {
+
+    @AssistedFactory
+    interface Factory {
+        fun create(initialState: RoomNotificationSettingsViewState): RoomNotificationSettingsViewModel
+    }
+
+    companion object : MvRxViewModelFactory<RoomNotificationSettingsViewModel, RoomNotificationSettingsViewState> {
+
+        @JvmStatic
+        override fun create(viewModelContext: ViewModelContext, state: RoomNotificationSettingsViewState): RoomNotificationSettingsViewModel {
+            val fragmentModelContext = (viewModelContext as FragmentViewModelContext)
+            return if (fragmentModelContext.fragment is RoomNotificationSettingsFragment) {
+                val fragment: RoomNotificationSettingsFragment = fragmentModelContext.fragment()
+                fragment.viewModelFactory.create(state)
+            } else {
+                val fragment: RoomListQuickActionsBottomSheet = fragmentModelContext.fragment()
+                fragment.roomNotificationSettingsViewModelFactory.create(state)
+            }
+        }
+    }
+
+    private val room = session.getRoom(initialState.roomId)!!
+
+    init {
+        observeSummary()
+        observeNotificationState()
+    }
+
+    private fun observeSummary() {
+        room.rx().liveRoomSummary()
+                .unwrap()
+                .execute { async ->
+                    copy(roomSummary = async)
+                }
+    }
+
+    private fun observeNotificationState() {
+        room.rx()
+                .liveNotificationState()
+                .execute {
+                    copy(notificationState = it)
+                }
+    }
+
+    override fun handle(action: RoomNotificationSettingsAction) {
+        when (action) {
+            is RoomNotificationSettingsAction.SelectNotificationState -> handleSelectNotificationState(action)
+        }
+    }
+
+    private fun handleSelectNotificationState(action: RoomNotificationSettingsAction.SelectNotificationState) {
+        setState { copy(isLoading = true) }
+        viewModelScope.launch {
+            runCatching {  room.setRoomNotificationState(action.notificationState) }
+                    .fold(
+                            {
+                                setState {
+                                    copy(isLoading = false, notificationState = Success(action.notificationState))
+                                }
+                            },
+                            {
+                                setState {
+                                    copy(isLoading = false)
+                                }
+                                _viewEvents.post(RoomNotificationSettingsViewEvents.Failure(it))
+                            }
+                    )
+        }
+    }
+}
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsViewState.kt b/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsViewState.kt
new file mode 100644
index 0000000000..72e61fba70
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsViewState.kt
@@ -0,0 +1,62 @@
+/*
+ * 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.roomprofile.notifications
+
+import com.airbnb.mvrx.Async
+import com.airbnb.mvrx.MvRxState
+import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.Uninitialized
+import im.vector.app.features.home.room.list.actions.RoomListActionsArgs
+import im.vector.app.features.roomprofile.RoomProfileArgs
+import org.matrix.android.sdk.api.session.room.model.RoomSummary
+import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
+
+data class RoomNotificationSettingsViewState(
+        val roomId: String,
+        val roomSummary: Async<RoomSummary> = Uninitialized,
+        val isLoading: Boolean = false,
+        val notificationState: Async<RoomNotificationState> = Uninitialized
+)  : MvRxState {
+    constructor(args: RoomProfileArgs) : this(roomId = args.roomId)
+    constructor(args: RoomListActionsArgs) : this(roomId = args.roomId)
+}
+
+/**
+ * Used to map this old room notification settings to the new options in v2.
+ */
+val RoomNotificationSettingsViewState.notificationStateMapped: Async<RoomNotificationState>
+    get() {
+        if ((roomSummary()?.isEncrypted == true && notificationState() == RoomNotificationState.MENTIONS_ONLY)
+                || notificationState() == RoomNotificationState.ALL_MESSAGES) {
+            /** if in an encrypted room, mentions notifications are not supported so show "All Messages" as selected.
+             * Also in the new settings there is no notion of notifications without sound so it maps to noisy also
+             */
+            return Success(RoomNotificationState.ALL_MESSAGES_NOISY)
+        }
+        return  notificationState
+    }
+/**
+ * Used to enumerate the new settings in notification settings v2. Notifications without sound and mentions in encrypted rooms not supported.
+ */
+val RoomNotificationSettingsViewState.notificationOptions: List<RoomNotificationState>
+    get() {
+        return if (roomSummary()?.isEncrypted == true) {
+            listOf(RoomNotificationState.ALL_MESSAGES_NOISY, RoomNotificationState.MUTE)
+        } else {
+            listOf(RoomNotificationState.ALL_MESSAGES_NOISY, RoomNotificationState.MENTIONS_ONLY, RoomNotificationState.MUTE)
+        }
+    }
diff --git a/vector/src/main/res/layout/activity_call.xml b/vector/src/main/res/layout/activity_call.xml
index 8088969253..342ae11562 100644
--- a/vector/src/main/res/layout/activity_call.xml
+++ b/vector/src/main/res/layout/activity_call.xml
@@ -167,7 +167,6 @@
         app:layout_constraintTop_toBottomOf="@id/participantNameText"
         tools:text="@string/call_resume_action" />
 
-
     <androidx.constraintlayout.widget.Group
         android:id="@+id/callInfoGroup"
         android:layout_width="wrap_content"
@@ -181,16 +180,4 @@
         android:layout_height="wrap_content"
         app:layout_constraintBottom_toBottomOf="parent" />
 
-    <FrameLayout
-        android:id="@+id/hud_fragment_container"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-
-        <FrameLayout
-            android:id="@+id/call_fragment_container"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent" />
-
-    </FrameLayout>
-
 </androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/vector/src/main/res/layout/item_notifications_footer.xml b/vector/src/main/res/layout/item_notifications_footer.xml
new file mode 100644
index 0000000000..36db166e8f
--- /dev/null
+++ b/vector/src/main/res/layout/item_notifications_footer.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    style="@style/Widget.Vector.TextView.Body"
+    android:id="@+id/footerText"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingStart="@dimen/layout_horizontal_margin"
+    android:paddingTop="@dimen/layout_vertical_margin"
+    android:paddingEnd="@dimen/layout_horizontal_margin"
+    android:paddingBottom="@dimen/layout_vertical_margin"
+    android:textColor="?vctr_content_secondary"
+    tools:text="@string/room_settings_room_notifications_encryption_notice" />
diff --git a/vector/src/main/res/layout/item_radio.xml b/vector/src/main/res/layout/item_radio.xml
new file mode 100644
index 0000000000..4cd5312dc0
--- /dev/null
+++ b/vector/src/main/res/layout/item_radio.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:clickable="true"
+    android:focusable="true"
+    android:minHeight="64dp"
+    android:foreground="?attr/selectableItemBackground"
+    android:paddingStart="@dimen/layout_horizontal_margin"
+    android:paddingEnd="@dimen/layout_horizontal_margin">
+
+    <TextView
+        android:id="@+id/actionTitle"
+        style="@style/Widget.Vector.TextView.Subtitle"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="@dimen/layout_horizontal_margin"
+        android:ellipsize="end"
+        android:maxLines="2"
+        android:textColor="?vctr_content_primary"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toStartOf="@id/radioIcon"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        tools:text="@string/room_settings_all_messages" />
+
+    <ImageView
+        android:id="@+id/radioIcon"
+        android:layout_width="20dp"
+        android:layout_height="20dp"
+        android:contentDescription="@string/a11y_checked"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        tools:ignore="MissingPrefix"
+        tools:src="@drawable/ic_radio_on" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/vector/src/main/res/layout/item_text_header.xml b/vector/src/main/res/layout/item_text_header.xml
new file mode 100644
index 0000000000..3f876e5ece
--- /dev/null
+++ b/vector/src/main/res/layout/item_text_header.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/headerText"
+    style="@style/Widget.Vector.TextView.Subtitle"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingStart="@dimen/layout_horizontal_margin"
+    android:paddingTop="@dimen/layout_vertical_margin"
+    android:paddingEnd="@dimen/layout_horizontal_margin"
+    android:paddingBottom="@dimen/layout_vertical_margin"
+    android:textColor="?vctr_content_secondary"
+    android:textStyle="bold"
+    tools:text="@string/room_settings_room_notifications_notify_me" />
\ No newline at end of file
diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml
index ded6256ccd..c41ff16623 100644
--- a/vector/src/main/res/values/strings.xml
+++ b/vector/src/main/res/values/strings.xml
@@ -752,6 +752,9 @@
     <string name="call_held_by_user">%s held the call</string>
     <string name="call_held_by_you">You held the call</string>
 
+    <string name="call_ended_user_busy_title">User busy</string>
+    <string name="call_ended_user_busy_description">The user you called is busy."</string>
+    <string name="call_ended_invite_timeout_title">No answer</string>
     <string name="call_error_user_not_responding">The remote side failed to pick up.</string>
     <string name="call_error_ice_failed">Media Connection Failed</string>
     <string name="call_error_camera_init_failed">Cannot initialize the camera</string>
@@ -1051,6 +1054,8 @@
     <string name="room_settings_all_messages">All messages</string>
     <string name="room_settings_mention_only">Mentions only</string>
     <string name="room_settings_mute">Mute</string>
+    <string name="room_settings_mention_and_keyword_only">Mentions &amp; Keywords only</string>
+    <string name="room_settings_none">None</string>
     <string name="room_settings_favourite">Favourite</string>
     <string name="room_settings_de_prioritize">De-prioritize</string>
     <string name="room_settings_direct_chat">Direct Chat</string>
@@ -1441,6 +1446,10 @@
     <string name="room_settings_category_access_visibility_title">Access and visibility</string>
     <string name="room_settings_directory_visibility">List this room in room directory</string>
     <string name="room_settings_room_notifications_title">Notifications</string>
+    <string name="room_settings_room_notifications_notify_me">Notify me for</string>
+    <string name="room_settings_room_notifications_encryption_notice">Please note that mentions &amp; keyword notifications are not available in encrypted rooms on mobile.</string>
+    <string name="room_settings_room_notifications_manage_notifications">You can manage notifications in %1$s.</string>
+    <string name="room_settings_room_notifications_account_settings">Account settings</string>
     <string name="room_settings_room_access_rules_pref_title">Room Access</string>
     <string name="room_settings_room_read_history_rules_pref_title">Room History Readability</string>
     <string name="room_settings_room_read_history_rules_pref_dialog_title">Who can read history?</string>