From 75c2dfcd48e8fe4844ef358605b6c5340b45f30f Mon Sep 17 00:00:00 2001
From: ganfra
 <francoisg@matrix.orgfrancoisg@matrix.orgfrancoisg@matrix.orgfrancoisg@matrix.org>
Date: Wed, 8 Jul 2020 19:16:22 +0200
Subject: [PATCH] Fix user data being affected by local room member event
 changes

---
 .../android/api/session/events/model/UnsignedData.kt      | 7 ++++++-
 .../session/room/membership/RoomMemberEventHandler.kt     | 2 +-
 .../room/detail/timeline/format/NoticeEventFormatter.kt   | 8 ++++----
 3 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/UnsignedData.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/UnsignedData.kt
index b179cb7a31..16ff36ea07 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/UnsignedData.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/UnsignedData.kt
@@ -39,5 +39,10 @@ data class UnsignedData(
          * Optional. The previous content for this event. If there is no previous content, this key will be missing.
          */
         @Json(name = "prev_content") val prevContent: Map<String, Any>? = null,
-        @Json(name = "m.relations") val relations: AggregatedRelations? = null
+        @Json(name = "m.relations") val relations: AggregatedRelations? = null,
+        /**
+         * Optional. The eventId of the previous state event being replaced.
+         */
+        @Json(name = "replaces_state") val replacesState: String? = null
+
 )
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/RoomMemberEventHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/RoomMemberEventHandler.kt
index d7d578b635..b225895532 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/RoomMemberEventHandler.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/RoomMemberEventHandler.kt
@@ -34,7 +34,7 @@ internal class RoomMemberEventHandler @Inject constructor() {
         val userId = event.stateKey ?: return false
         val roomMemberEntity = RoomMemberEntityFactory.create(roomId, userId, roomMember)
         realm.insertOrUpdate(roomMemberEntity)
-        if (roomMember.membership.isActive()) {
+        if (roomMember.membership.isActive() && event.unsignedData?.replacesState.isNullOrEmpty()) {
             val userEntity = UserEntityFactory.create(userId, roomMember)
             realm.insertOrUpdate(userEntity)
         }
diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/format/NoticeEventFormatter.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/format/NoticeEventFormatter.kt
index c1f4187e0b..fff74e0328 100644
--- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/format/NoticeEventFormatter.kt
+++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/format/NoticeEventFormatter.kt
@@ -92,7 +92,7 @@ class NoticeEventFormatter @Inject constructor(private val sessionHolder: Active
 
     private fun formatRoomPowerLevels(event: Event, disambiguatedDisplayName: String): CharSequence? {
         val powerLevelsContent: PowerLevelsContent = event.getClearContent().toModel() ?: return null
-        val previousPowerLevelsContent: PowerLevelsContent = event.prevContent.toModel() ?: return null
+        val previousPowerLevelsContent: PowerLevelsContent = event.resolvedPrevContent().toModel() ?: return null
         val userIds = HashSet<String>()
         userIds.addAll(powerLevelsContent.users.keys)
         userIds.addAll(previousPowerLevelsContent.users.keys)
@@ -120,7 +120,7 @@ class NoticeEventFormatter @Inject constructor(private val sessionHolder: Active
 
     private fun formatWidgetEvent(event: Event, disambiguatedDisplayName: String): CharSequence? {
         val widgetContent: WidgetContent = event.getClearContent().toModel() ?: return null
-        val previousWidgetContent: WidgetContent? = event.prevContent.toModel()
+        val previousWidgetContent: WidgetContent? = event.resolvedPrevContent().toModel()
         return if (widgetContent.isActive()) {
             val widgetName = widgetContent.getHumanName()
             if (previousWidgetContent?.isActive().orFalse()) {
@@ -294,7 +294,7 @@ class NoticeEventFormatter @Inject constructor(private val sessionHolder: Active
 
     private fun formatRoomMemberEvent(event: Event, senderName: String?): String? {
         val eventContent: RoomMemberContent? = event.getClearContent().toModel()
-        val prevEventContent: RoomMemberContent? = event.prevContent.toModel()
+        val prevEventContent: RoomMemberContent? = event.resolvedPrevContent().toModel()
         val isMembershipEvent = prevEventContent?.membership != eventContent?.membership
         return if (isMembershipEvent) {
             buildMembershipNotice(event, senderName, eventContent, prevEventContent)
@@ -305,7 +305,7 @@ class NoticeEventFormatter @Inject constructor(private val sessionHolder: Active
 
     private fun formatRoomAliasesEvent(event: Event, senderName: String?): String? {
         val eventContent: RoomAliasesContent? = event.getClearContent().toModel()
-        val prevEventContent: RoomAliasesContent? = event.unsignedData?.prevContent?.toModel()
+        val prevEventContent: RoomAliasesContent? = event.resolvedPrevContent()?.toModel()
 
         val addedAliases = eventContent?.aliases.orEmpty() - prevEventContent?.aliases.orEmpty()
         val removedAliases = prevEventContent?.aliases.orEmpty() - eventContent?.aliases.orEmpty()