diff --git a/CHANGES.md b/CHANGES.md
index a01b74169b..e468229200 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -2,7 +2,7 @@ Changes in RiotX 0.2.1 (2019-XX-XX)
 ===================================================
 
 Features:
- -
+ - Message Editing: View edit history
 
 Improvements:
  - Handle click on redacted events: view source and create permalink
diff --git a/build.gradle b/build.gradle
index 91415088e5..4fa468ab26 100644
--- a/build.gradle
+++ b/build.gradle
@@ -45,6 +45,12 @@ allprojects {
         maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
         google()
         jcenter()
+        maven {
+            url 'https://repo.adobe.com/nexus/content/repositories/public/'
+            content {
+                includeGroupByRegex "diff_match_patch"
+            }
+        }
     }
 }
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/relation/RelationService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/relation/RelationService.kt
index 81d7ddd4c0..7ffbd5f1c9 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/relation/RelationService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/relation/RelationService.kt
@@ -16,6 +16,8 @@
 package im.vector.matrix.android.api.session.room.model.relation
 
 import androidx.lifecycle.LiveData
+import im.vector.matrix.android.api.MatrixCallback
+import im.vector.matrix.android.api.session.events.model.Event
 import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary
 import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
 import im.vector.matrix.android.api.util.Cancelable
@@ -78,6 +80,11 @@ interface RelationService {
                         newBodyAutoMarkdown: Boolean,
                         compatibilityBodyText: String = "* $newBodyText"): Cancelable
 
+    /**
+     * Get's the edit history of the given event
+     */
+    fun fetchEditHistory(eventId: String, callback: MatrixCallback<List<Event>>)
+
 
     /**
      * Reply to an event in the timeline (must be in same room)
@@ -91,4 +98,6 @@ interface RelationService {
                        autoMarkdown: Boolean = false): Cancelable?
 
     fun getEventSummaryLive(eventId: String): LiveData<EventAnnotationsSummary>
+
+
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/NetworkConstants.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/NetworkConstants.kt
index d6d2d9cc6c..cbd4d0c674 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/NetworkConstants.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/NetworkConstants.kt
@@ -18,7 +18,8 @@ package im.vector.matrix.android.internal.network
 
 internal object NetworkConstants {
 
-    const val URI_API_PREFIX_PATH = "_matrix/client/"
-    const val URI_API_PREFIX_PATH_R0 = "_matrix/client/r0/"
+    private const val URI_API_PREFIX_PATH = "_matrix/client"
+    const val URI_API_PREFIX_PATH_R0 = "$URI_API_PREFIX_PATH/r0/"
+    const val URI_API_PREFIX_PATH_UNSTABLE = "$URI_API_PREFIX_PATH/unstable/"
 
-}
\ No newline at end of file
+}
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAPI.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAPI.kt
index af26397046..361a935d2f 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAPI.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAPI.kt
@@ -22,10 +22,11 @@ import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
 import im.vector.matrix.android.api.session.room.model.create.CreateRoomResponse
 import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoomsParams
 import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoomsResponse
+import im.vector.matrix.android.api.session.room.model.thirdparty.ThirdPartyProtocol
 import im.vector.matrix.android.internal.network.NetworkConstants
 import im.vector.matrix.android.internal.session.room.membership.RoomMembersResponse
 import im.vector.matrix.android.internal.session.room.membership.joining.InviteBody
-import im.vector.matrix.android.api.session.room.model.thirdparty.ThirdPartyProtocol
+import im.vector.matrix.android.internal.session.room.relation.RelationsResponse
 import im.vector.matrix.android.internal.session.room.send.SendResponse
 import im.vector.matrix.android.internal.session.room.timeline.EventContextResponse
 import im.vector.matrix.android.internal.session.room.timeline.PaginationResponse
@@ -195,6 +196,20 @@ internal interface RoomAPI {
                      @Body content: Content?
     ): Call<SendResponse>
 
+
+    /**
+     * Paginate relations for event based in normal topological order
+     *
+     * @param relationType filter for this relation type
+     * @param eventType filter for this event type
+     */
+    @GET(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "rooms/{roomId}/relations/{eventId}/{relationType}/{eventType}")
+    fun getRelations(@Path("roomId") roomId: String,
+                     @Path("eventId") eventId: String,
+                     @Path("relationType") relationType: String,
+                     @Path("eventType") eventType: String
+    ): Call<RelationsResponse>
+
     /**
      * Join the given room.
      *
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt
index 143ef60b46..98cf872b10 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt
@@ -30,8 +30,8 @@ import im.vector.matrix.android.internal.session.room.membership.leaving.LeaveRo
 import im.vector.matrix.android.internal.session.room.read.DefaultReadService
 import im.vector.matrix.android.internal.session.room.read.SetReadMarkersTask
 import im.vector.matrix.android.internal.session.room.relation.DefaultRelationService
+import im.vector.matrix.android.internal.session.room.relation.FetchEditHistoryTask
 import im.vector.matrix.android.internal.session.room.relation.FindReactionEventForUndoTask
-import im.vector.matrix.android.internal.session.room.relation.UpdateQuickReactionTask
 import im.vector.matrix.android.internal.session.room.send.DefaultSendService
 import im.vector.matrix.android.internal.session.room.send.LocalEchoEventFactory
 import im.vector.matrix.android.internal.session.room.state.DefaultStateService
@@ -56,7 +56,7 @@ internal class RoomFactory @Inject constructor(private val context: Context,
                                                private val setReadMarkersTask: SetReadMarkersTask,
                                                private val cryptoService: CryptoService,
                                                private val findReactionEventForUndoTask: FindReactionEventForUndoTask,
-                                               private val updateQuickReactionTask: UpdateQuickReactionTask,
+                                               private val fetchEditHistoryTask: FetchEditHistoryTask,
                                                private val joinRoomTask: JoinRoomTask,
                                                private val leaveRoomTask: LeaveRoomTask) {
 
@@ -67,7 +67,7 @@ internal class RoomFactory @Inject constructor(private val context: Context,
         val roomMembersService = DefaultMembershipService(roomId, monarchy, taskExecutor, loadRoomMembersTask, inviteTask, joinRoomTask, leaveRoomTask)
         val readService = DefaultReadService(roomId, monarchy, taskExecutor, setReadMarkersTask, credentials)
         val relationService = DefaultRelationService(context,
-                credentials, roomId, eventFactory, cryptoService, findReactionEventForUndoTask, monarchy, taskExecutor)
+                credentials, roomId, eventFactory, cryptoService, findReactionEventForUndoTask, fetchEditHistoryTask, monarchy, taskExecutor)
 
         return DefaultRoom(
                 roomId,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt
index 09322e6a1a..942239ea12 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt
@@ -142,4 +142,7 @@ internal abstract class RoomModule {
 
     @Binds
     abstract fun bindFileService(fileService: DefaultFileService): FileService
+
+    @Binds
+    abstract fun bindFetchEditHistoryTask(editHistoryTask: DefaultFetchEditHistoryTask): FetchEditHistoryTask
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt
index 3eb1c066a8..1b487d960d 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt
@@ -53,6 +53,7 @@ internal class DefaultRelationService @Inject constructor(private val context: C
                                                           private val eventFactory: LocalEchoEventFactory,
                                                           private val cryptoService: CryptoService,
                                                           private val findReactionEventForUndoTask: FindReactionEventForUndoTask,
+                                                          private val fetchEditHistoryTask: FetchEditHistoryTask,
                                                           private val monarchy: Monarchy,
                                                           private val taskExecutor: TaskExecutor)
     : RelationService {
@@ -131,6 +132,13 @@ internal class DefaultRelationService @Inject constructor(private val context: C
 
     }
 
+    override fun fetchEditHistory(eventId: String, callback: MatrixCallback<List<Event>>) {
+        val params = FetchEditHistoryTask.Params(roomId, eventId)
+        fetchEditHistoryTask.configureWith(params)
+                .dispatchTo(callback)
+                .executeBy(taskExecutor)
+    }
+
     override fun replyToMessage(eventReplied: TimelineEvent, replyText: String, autoMarkdown: Boolean): Cancelable? {
         val event = eventFactory.createReplyTextEvent(roomId, eventReplied, replyText, autoMarkdown)?.also {
             saveLocalEcho(it)
@@ -169,7 +177,8 @@ internal class DefaultRelationService @Inject constructor(private val context: C
             EventAnnotationsSummaryEntity.where(realm, eventId)
         }
         return Transformations.map(liveEntity) { realmResults ->
-            realmResults.firstOrNull()?.asDomain() ?: EventAnnotationsSummary(eventId, emptyList(), null)
+            realmResults.firstOrNull()?.asDomain()
+                    ?: EventAnnotationsSummary(eventId, emptyList(), null)
         }
     }
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/FetchEditHistoryTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/FetchEditHistoryTask.kt
new file mode 100644
index 0000000000..e891ece8da
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/FetchEditHistoryTask.kt
@@ -0,0 +1,48 @@
+/*
+ * 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.matrix.android.internal.session.room.relation
+
+import arrow.core.Try
+import im.vector.matrix.android.api.session.events.model.Event
+import im.vector.matrix.android.api.session.events.model.EventType
+import im.vector.matrix.android.api.session.events.model.RelationType
+import im.vector.matrix.android.internal.network.executeRequest
+import im.vector.matrix.android.internal.session.room.RoomAPI
+import im.vector.matrix.android.internal.task.Task
+import javax.inject.Inject
+
+
+internal interface FetchEditHistoryTask : Task<FetchEditHistoryTask.Params, List<Event>> {
+
+    data class Params(
+            val roomId: String,
+            val eventId: String
+    )
+}
+
+
+internal class DefaultFetchEditHistoryTask @Inject constructor(
+        private val roomAPI: RoomAPI
+) : FetchEditHistoryTask {
+
+    override suspend fun execute(params: FetchEditHistoryTask.Params): Try<List<Event>> {
+        return executeRequest<RelationsResponse> {
+            apiCall = roomAPI.getRelations(params.roomId, params.eventId, RelationType.REPLACE, EventType.MESSAGE)
+        }.map { resp ->
+            resp.chunks
+        }
+    }
+}
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/RelationsResponse.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/RelationsResponse.kt
new file mode 100644
index 0000000000..5d39e81c48
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/RelationsResponse.kt
@@ -0,0 +1,27 @@
+/*
+ * 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.matrix.android.internal.session.room.relation
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import im.vector.matrix.android.api.session.events.model.Event
+
+@JsonClass(generateAdapter = true)
+internal data class RelationsResponse(
+        @Json(name = "chunk") val chunks: List<Event>,
+        @Json(name = "next_batch") val nextBatch: String?,
+        @Json(name = "prev_batch") val prevBatch: String?
+)
\ No newline at end of file
diff --git a/vector/build.gradle b/vector/build.gradle
index ace3135ae5..d7332c476c 100644
--- a/vector/build.gradle
+++ b/vector/build.gradle
@@ -254,6 +254,8 @@ dependencies {
         exclude group: 'com.google.firebase', module: 'firebase-measurement-connector'
     }
 
+    implementation 'diff_match_patch:diff_match_patch:current'
+
     // TESTS
     testImplementation 'junit:junit:4.12'
     androidTestImplementation 'androidx.test:runner:1.2.0'
diff --git a/vector/src/main/assets/open_source_licenses.html b/vector/src/main/assets/open_source_licenses.html
index cec7c7183d..9e87d466af 100755
--- a/vector/src/main/assets/open_source_licenses.html
+++ b/vector/src/main/assets/open_source_licenses.html
@@ -344,6 +344,13 @@ SOFTWARE.
         <br/>
         Copyright (c) 2018, Jaisel Rahman
     </li>
+    <li>
+        <b>diff-match-patch</b>
+        <br/>
+        Copyright 2018 The diff-match-patch Authors. https://github.com/google/diff-match-patch
+    </li>
+
+
 </ul>
 <pre>
 Apache License
diff --git a/vector/src/main/java/im/vector/riotx/core/di/ScreenComponent.kt b/vector/src/main/java/im/vector/riotx/core/di/ScreenComponent.kt
index 06f6512939..611ee171bd 100644
--- a/vector/src/main/java/im/vector/riotx/core/di/ScreenComponent.kt
+++ b/vector/src/main/java/im/vector/riotx/core/di/ScreenComponent.kt
@@ -35,10 +35,7 @@ import im.vector.riotx.features.crypto.verification.SASVerificationIncomingFragm
 import im.vector.riotx.features.home.*
 import im.vector.riotx.features.home.group.GroupListFragment
 import im.vector.riotx.features.home.room.detail.RoomDetailFragment
-import im.vector.riotx.features.home.room.detail.timeline.action.MessageActionsBottomSheet
-import im.vector.riotx.features.home.room.detail.timeline.action.MessageMenuFragment
-import im.vector.riotx.features.home.room.detail.timeline.action.QuickReactionFragment
-import im.vector.riotx.features.home.room.detail.timeline.action.ViewReactionBottomSheet
+import im.vector.riotx.features.home.room.detail.timeline.action.*
 import im.vector.riotx.features.home.room.list.RoomListFragment
 import im.vector.riotx.features.invite.VectorInviteView
 import im.vector.riotx.features.login.LoginActivity
@@ -93,6 +90,8 @@ interface ScreenComponent {
 
     fun inject(viewReactionBottomSheet: ViewReactionBottomSheet)
 
+    fun inject(viewEditHistoryBottomSheet: ViewEditHistoryBottomSheet)
+
     fun inject(messageMenuFragment: MessageMenuFragment)
 
     fun inject(vectorSettingsActivity: VectorSettingsActivity)
diff --git a/vector/src/main/java/im/vector/riotx/core/di/ViewModelModule.kt b/vector/src/main/java/im/vector/riotx/core/di/ViewModelModule.kt
index 234d4a0caf..37abde20b8 100644
--- a/vector/src/main/java/im/vector/riotx/core/di/ViewModelModule.kt
+++ b/vector/src/main/java/im/vector/riotx/core/di/ViewModelModule.kt
@@ -29,11 +29,7 @@ import im.vector.riotx.features.crypto.keysbackup.settings.KeysBackupSettingsVie
 import im.vector.riotx.features.crypto.keysbackup.settings.KeysBackupSettingsViewModel_AssistedFactory
 import im.vector.riotx.features.crypto.keysbackup.setup.KeysBackupSetupSharedViewModel
 import im.vector.riotx.features.crypto.verification.SasVerificationViewModel
-import im.vector.riotx.features.home.HomeActivityViewModel
-import im.vector.riotx.features.home.HomeActivityViewModel_AssistedFactory
-import im.vector.riotx.features.home.HomeDetailViewModel
-import im.vector.riotx.features.home.HomeDetailViewModel_AssistedFactory
-import im.vector.riotx.features.home.HomeNavigationViewModel
+import im.vector.riotx.features.home.*
 import im.vector.riotx.features.home.group.GroupListViewModel
 import im.vector.riotx.features.home.group.GroupListViewModel_AssistedFactory
 import im.vector.riotx.features.home.room.detail.RoomDetailViewModel
@@ -59,7 +55,7 @@ import im.vector.riotx.features.workers.signout.SignOutViewModel
 
 @Module
 interface ViewModelModule {
-    
+
 
     @Binds
     fun bindViewModelFactory(factory: VectorViewModelFactory): ViewModelProvider.Factory
@@ -156,6 +152,9 @@ interface ViewModelModule {
     @Binds
     fun bindViewReactionViewModelFactory(factory: ViewReactionViewModel_AssistedFactory): ViewReactionViewModel.Factory
 
+    @Binds
+    fun bindViewEditHistoryViewModelFactory(factory: ViewEditHistoryViewModel_AssistedFactory): ViewEditHistoryViewModel.Factory
+
     @Binds
     fun bindCreateRoomViewModelFactory(factory: CreateRoomViewModel_AssistedFactory): CreateRoomViewModel.Factory
 
diff --git a/vector/src/main/java/im/vector/riotx/core/ui/list/GenericItem.kt b/vector/src/main/java/im/vector/riotx/core/ui/list/GenericItem.kt
index ebaeb2d39e..f0a62ccd5a 100644
--- a/vector/src/main/java/im/vector/riotx/core/ui/list/GenericItem.kt
+++ b/vector/src/main/java/im/vector/riotx/core/ui/list/GenericItem.kt
@@ -51,7 +51,7 @@ abstract class GenericItem : VectorEpoxyModel<GenericItem.Holder>() {
     var title: String? = null
 
     @EpoxyAttribute
-    var description: String? = null
+    var description: CharSequence? = null
 
     @EpoxyAttribute
     var style: STYLE = STYLE.NORMAL_TEXT
diff --git a/vector/src/main/java/im/vector/riotx/core/ui/list/GenericItemHeader.kt b/vector/src/main/java/im/vector/riotx/core/ui/list/GenericItemHeader.kt
new file mode 100644
index 0000000000..3c9ce20de3
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotx/core/ui/list/GenericItemHeader.kt
@@ -0,0 +1,42 @@
+/*
+ * 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.riotx.core.ui.list
+
+import android.widget.TextView
+import com.airbnb.epoxy.EpoxyAttribute
+import com.airbnb.epoxy.EpoxyModelClass
+import im.vector.riotx.R
+import im.vector.riotx.core.epoxy.VectorEpoxyHolder
+import im.vector.riotx.core.epoxy.VectorEpoxyModel
+import im.vector.riotx.core.extensions.setTextOrHide
+
+/**
+ * A generic list item header left aligned with notice color.
+ */
+@EpoxyModelClass(layout = R.layout.item_generic_header)
+abstract class GenericItemHeader : VectorEpoxyModel<GenericItemHeader.Holder>() {
+
+    @EpoxyAttribute
+    var text: String? = null
+
+    override fun bind(holder: Holder) {
+        holder.text.setTextOrHide(text)
+    }
+
+    class Holder : VectorEpoxyHolder() {
+        val text by bind<TextView>(R.id.itemGenericHeaderText)
+    }
+}
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotx/core/ui/list/GenericLoaderItem.kt b/vector/src/main/java/im/vector/riotx/core/ui/list/GenericLoaderItem.kt
new file mode 100644
index 0000000000..56daca223e
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotx/core/ui/list/GenericLoaderItem.kt
@@ -0,0 +1,20 @@
+package im.vector.riotx.core.ui.list
+
+import com.airbnb.epoxy.EpoxyModelClass
+import im.vector.riotx.R
+import im.vector.riotx.core.epoxy.VectorEpoxyHolder
+import im.vector.riotx.core.epoxy.VectorEpoxyModel
+
+
+/**
+ * A generic list item header left aligned with notice color.
+ */
+@EpoxyModelClass(layout = R.layout.item_generic_loader)
+abstract class GenericLoaderItem : VectorEpoxyModel<GenericLoaderItem.Holder>() {
+
+    //Maybe/Later add some style configuration, SMALL/BIG ?
+
+    override fun bind(holder: Holder) {}
+
+    class Holder : VectorEpoxyHolder()
+}
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailActions.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailActions.kt
index d52b16ca04..ace0802e09 100644
--- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailActions.kt
+++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailActions.kt
@@ -32,7 +32,6 @@ sealed class RoomDetailActions {
     data class RedactAction(val targetEventId: String, val reason: String? = "") : RoomDetailActions()
     data class UndoReaction(val targetEventId: String, val key: String, val reason: String? = "") : RoomDetailActions()
     data class UpdateQuickReactAction(val targetEventId: String, val selectedReaction: String, val add: Boolean) : RoomDetailActions()
-    data class ShowEditHistoryAction(val event: String, val editAggregatedSummary: EditAggregatedSummary) : RoomDetailActions()
     data class NavigateToEvent(val eventId: String, val position: Int?) : RoomDetailActions()
     data class DownloadFile(val eventId: String, val messageFileContent: MessageFileContent) : RoomDetailActions()
     object AcceptInvite : RoomDetailActions()
diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt
index f611fe9973..943b6165e0 100644
--- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt
@@ -85,10 +85,7 @@ import im.vector.riotx.features.home.room.detail.composer.TextComposerView
 import im.vector.riotx.features.home.room.detail.composer.TextComposerViewModel
 import im.vector.riotx.features.home.room.detail.composer.TextComposerViewState
 import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
-import im.vector.riotx.features.home.room.detail.timeline.action.ActionsHandler
-import im.vector.riotx.features.home.room.detail.timeline.action.MessageActionsBottomSheet
-import im.vector.riotx.features.home.room.detail.timeline.action.MessageMenuViewModel
-import im.vector.riotx.features.home.room.detail.timeline.action.ViewReactionBottomSheet
+import im.vector.riotx.features.home.room.detail.timeline.action.*
 import im.vector.riotx.features.home.room.detail.timeline.helper.EndlessRecyclerViewScrollListener
 import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData
 import im.vector.riotx.features.html.EventHtmlRenderer
@@ -666,10 +663,8 @@ class RoomDetailFragment :
     }
 
     override fun onEditedDecorationClicked(informationData: MessageInformationData, editAggregatedSummary: EditAggregatedSummary?) {
-        editAggregatedSummary?.also {
-            roomDetailViewModel.process(RoomDetailActions.ShowEditHistoryAction(informationData.eventId, it))
-        }
-
+        ViewEditHistoryBottomSheet.newInstance(roomDetailArgs.roomId, informationData)
+                .show(requireActivity().supportFragmentManager, "DISPLAY_EDITS")
     }
 // AutocompleteUserPresenter.Callback
 
diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt
index 2a19914a8c..36b989fe31 100644
--- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt
+++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt
@@ -114,7 +114,6 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
             is RoomDetailActions.RedactAction           -> handleRedactEvent(action)
             is RoomDetailActions.UndoReaction           -> handleUndoReact(action)
             is RoomDetailActions.UpdateQuickReactAction -> handleUpdateQuickReaction(action)
-            is RoomDetailActions.ShowEditHistoryAction  -> handleShowEditHistoryReaction(action)
             is RoomDetailActions.EnterEditMode          -> handleEditAction(action)
             is RoomDetailActions.EnterQuoteMode         -> handleQuoteAction(action)
             is RoomDetailActions.EnterReplyMode         -> handleReplyAction(action)
@@ -309,22 +308,6 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
         return finalText
     }
 
-    private fun handleShowEditHistoryReaction(action: RoomDetailActions.ShowEditHistoryAction) {
-        //TODO temporary implementation
-        val lastReplace = action.editAggregatedSummary.sourceEvents.lastOrNull()?.let {
-            room.getTimeLineEvent(it)
-        } ?: return
-
-        val dateFormat = SimpleDateFormat("EEE, d MMM yyyy HH:mm", Locale.getDefault())
-        _nonBlockingPopAlert.postValue(LiveEvent(
-                Pair(R.string.last_edited_info_message, listOf(
-                        lastReplace.getDisambiguatedDisplayName(),
-                        dateFormat.format(Date(lastReplace.root.originServerTs ?: 0)))
-                ))
-        )
-    }
-
-
     private fun handleChangeTopicSlashCommand(changeTopic: ParsedCommand.ChangeTopic) {
         _sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandHandled))
 
diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ViewEditHistoryBottomSheet.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ViewEditHistoryBottomSheet.kt
new file mode 100644
index 0000000000..aefbde431a
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ViewEditHistoryBottomSheet.kt
@@ -0,0 +1,93 @@
+/*
+ * 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.riotx.features.home.room.detail.timeline.action
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.LinearLayout
+import androidx.recyclerview.widget.DividerItemDecoration
+import butterknife.BindView
+import butterknife.ButterKnife
+import com.airbnb.epoxy.EpoxyRecyclerView
+import com.airbnb.mvrx.MvRx
+import com.airbnb.mvrx.fragmentViewModel
+import com.airbnb.mvrx.withState
+import im.vector.riotx.R
+import im.vector.riotx.core.di.ScreenComponent
+import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData
+import im.vector.riotx.features.html.EventHtmlRenderer
+import kotlinx.android.synthetic.main.bottom_sheet_epoxylist_with_title.*
+import javax.inject.Inject
+
+
+/**
+ * Bottom sheet displaying list of edits for a given event ordered by timestamp
+ */
+class ViewEditHistoryBottomSheet : VectorBaseBottomSheetDialogFragment() {
+
+    private val viewModel: ViewEditHistoryViewModel by fragmentViewModel(ViewEditHistoryViewModel::class)
+
+    @Inject lateinit var viewEditHistoryViewModelFactory: ViewEditHistoryViewModel.Factory
+    @Inject lateinit var eventHtmlRenderer: EventHtmlRenderer
+
+    @BindView(R.id.bottom_sheet_display_reactions_list)
+    lateinit var epoxyRecyclerView: EpoxyRecyclerView
+
+    private val epoxyController by lazy {
+        ViewEditHistoryEpoxyController(requireContext(), viewModel.timelineDateFormatter, eventHtmlRenderer)
+    }
+
+    override fun injectWith(screenComponent: ScreenComponent) {
+        screenComponent.inject(this)
+    }
+
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+        val view = inflater.inflate(R.layout.bottom_sheet_epoxylist_with_title, container, false)
+        ButterKnife.bind(this, view)
+        return view
+    }
+
+    override fun onActivityCreated(savedInstanceState: Bundle?) {
+        super.onActivityCreated(savedInstanceState)
+        epoxyRecyclerView.setController(epoxyController)
+        val dividerItemDecoration = DividerItemDecoration(epoxyRecyclerView.context,
+                LinearLayout.VERTICAL)
+        epoxyRecyclerView.addItemDecoration(dividerItemDecoration)
+        bottomSheetTitle.text = context?.getString(R.string.message_edits)
+    }
+
+
+    override fun invalidate() = withState(viewModel) {
+        epoxyController.setData(it)
+    }
+
+    companion object {
+        fun newInstance(roomId: String, informationData: MessageInformationData): ViewEditHistoryBottomSheet {
+            val args = Bundle()
+            val parcelableArgs = TimelineEventFragmentArgs(
+                    informationData.eventId,
+                    roomId,
+                    informationData
+            )
+            args.putParcelable(MvRx.KEY_ARG, parcelableArgs)
+            return ViewEditHistoryBottomSheet().apply { arguments = args }
+
+        }
+    }
+}
+
diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ViewEditHistoryEpoxyController.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ViewEditHistoryEpoxyController.kt
new file mode 100644
index 0000000000..4ae62fbd93
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ViewEditHistoryEpoxyController.kt
@@ -0,0 +1,155 @@
+/*
+ * 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.riotx.features.home.room.detail.timeline.action
+
+import android.content.Context
+import android.text.Spannable
+import android.text.format.DateUtils
+import androidx.core.content.ContextCompat
+import com.airbnb.epoxy.TypedEpoxyController
+import com.airbnb.mvrx.Fail
+import com.airbnb.mvrx.Incomplete
+import com.airbnb.mvrx.Success
+import im.vector.matrix.android.api.session.events.model.Event
+import im.vector.matrix.android.api.session.events.model.toModel
+import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
+import im.vector.riotx.R
+import im.vector.riotx.core.extensions.localDateTime
+import im.vector.riotx.core.ui.list.genericFooterItem
+import im.vector.riotx.core.ui.list.genericItem
+import im.vector.riotx.core.ui.list.genericItemHeader
+import im.vector.riotx.core.ui.list.genericLoaderItem
+import im.vector.riotx.features.home.room.detail.timeline.helper.TimelineDateFormatter
+import im.vector.riotx.features.html.EventHtmlRenderer
+import me.gujun.android.span.span
+import name.fraser.neil.plaintext.diff_match_patch
+import timber.log.Timber
+import java.util.*
+
+/**
+ * Epoxy controller for reaction event list
+ */
+class ViewEditHistoryEpoxyController(private val context: Context,
+                                     val timelineDateFormatter: TimelineDateFormatter,
+                                     val eventHtmlRenderer: EventHtmlRenderer) : TypedEpoxyController<ViewEditHistoryViewState>() {
+
+    override fun buildModels(state: ViewEditHistoryViewState) {
+        when (state.editList) {
+            is Incomplete -> {
+                genericLoaderItem {
+                    id("Spinner")
+                }
+            }
+            is Fail       -> {
+                genericFooterItem {
+                    id("failure")
+                    text(context.getString(R.string.unknown_error))
+                }
+            }
+            is Success    -> {
+                state.editList()?.let { renderEvents(it) }
+            }
+
+        }
+    }
+
+    private fun renderEvents(sourceEvents: List<Event>) {
+        if (sourceEvents.isEmpty()) {
+            genericItem {
+                id("footer")
+                title(context.getString(R.string.no_message_edits_found))
+            }
+        } else {
+            var lastDate: Calendar? = null
+            sourceEvents.sortedByDescending {
+                it.originServerTs ?: 0
+            }.forEachIndexed { index, timelineEvent ->
+
+                val evDate = Calendar.getInstance().apply {
+                    timeInMillis = timelineEvent.originServerTs
+                            ?: System.currentTimeMillis()
+                }
+                if (lastDate?.get(Calendar.DAY_OF_YEAR) != evDate.get(Calendar.DAY_OF_YEAR)) {
+                    //need to display header with day
+                    val dateString = if (DateUtils.isToday(evDate.timeInMillis)) context.getString(R.string.today)
+                    else timelineDateFormatter.formatMessageDay(timelineEvent.localDateTime())
+                    genericItemHeader {
+                        id(evDate.hashCode())
+                        text(dateString)
+                    }
+                }
+                lastDate = evDate
+                val cContent = getCorrectContent(timelineEvent)
+                val body = cContent.second?.let { eventHtmlRenderer.render(it) }
+                        ?: cContent.first
+
+                val nextEvent = if (index + 1 <= sourceEvents.lastIndex) sourceEvents[index + 1] else null
+
+                var spannedDiff: Spannable? = null
+                if (nextEvent != null && cContent.second == null /*No diff for html*/) {
+                    //compares the body
+                    val nContent = getCorrectContent(nextEvent)
+                    val nextBody = nContent.second?.let { eventHtmlRenderer.render(it) }
+                            ?: nContent.first
+                    val dmp = diff_match_patch()
+                    val diff = dmp.diff_main(nextBody.toString(), body.toString())
+                    Timber.e("#### Diff: $diff")
+                    dmp.diff_cleanupSemantic(diff)
+                    Timber.e("#### Diff: $diff")
+                    spannedDiff = span {
+                        diff.map {
+                            when (it.operation) {
+                                diff_match_patch.Operation.DELETE -> {
+                                    span {
+                                        text = it.text
+                                        textColor = ContextCompat.getColor(context, R.color.vector_error_color)
+                                        textDecorationLine = "line-through"
+                                    }
+                                }
+                                diff_match_patch.Operation.INSERT -> {
+                                    span {
+                                        text = it.text
+                                        textColor = ContextCompat.getColor(context, R.color.vector_success_color)
+                                    }
+                                }
+                                else                              -> {
+                                    span {
+                                        text = it.text
+                                    }
+                                }
+                            }
+                        }
+
+                    }
+                }
+                genericItem {
+                    id(timelineEvent.eventId)
+                    title(timelineDateFormatter.formatMessageHour(timelineEvent.localDateTime()))
+                    description(spannedDiff ?: body)
+                }
+            }
+        }
+    }
+
+    private fun getCorrectContent(event: Event): Pair<String, String?> {
+        val clearContent = event.getClearContent().toModel<MessageTextContent>()
+        val newContent = clearContent
+                ?.newContent
+                ?.toModel<MessageTextContent>()
+        return (newContent?.body ?: clearContent?.body ?: "") to (newContent?.formattedBody
+                ?: clearContent?.formattedBody)
+    }
+}
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ViewEditHistoryViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ViewEditHistoryViewModel.kt
new file mode 100644
index 0000000000..64005c3fa3
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ViewEditHistoryViewModel.kt
@@ -0,0 +1,90 @@
+/*
+ * 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.riotx.features.home.room.detail.timeline.action
+
+import com.airbnb.mvrx.*
+import com.squareup.inject.assisted.Assisted
+import com.squareup.inject.assisted.AssistedInject
+import im.vector.matrix.android.api.MatrixCallback
+import im.vector.matrix.android.api.session.Session
+import im.vector.matrix.android.api.session.events.model.Event
+import im.vector.riotx.core.platform.VectorViewModel
+import im.vector.riotx.features.home.room.detail.timeline.helper.TimelineDateFormatter
+
+
+data class ViewEditHistoryViewState(
+        val eventId: String,
+        val roomId: String,
+        val editList: Async<List<Event>> = Uninitialized)
+    : MvRxState {
+
+    constructor(args: TimelineEventFragmentArgs) : this(roomId = args.roomId, eventId = args.eventId)
+
+}
+
+class ViewEditHistoryViewModel @AssistedInject constructor(@Assisted
+                                                           initialState: ViewEditHistoryViewState,
+                                                           val session: Session,
+                                                           val timelineDateFormatter: TimelineDateFormatter
+) : VectorViewModel<ViewEditHistoryViewState>(initialState) {
+
+    private val roomId = initialState.roomId
+    private val eventId = initialState.eventId
+    private val room = session.getRoom(roomId)
+            ?: throw IllegalStateException("Shouldn't use this ViewModel without a room")
+
+    @AssistedInject.Factory
+    interface Factory {
+        fun create(initialState: ViewEditHistoryViewState): ViewEditHistoryViewModel
+    }
+
+
+    companion object : MvRxViewModelFactory<ViewEditHistoryViewModel, ViewEditHistoryViewState> {
+
+        override fun create(viewModelContext: ViewModelContext, state: ViewEditHistoryViewState): ViewEditHistoryViewModel? {
+            val fragment: ViewEditHistoryBottomSheet = (viewModelContext as FragmentViewModelContext).fragment()
+            return fragment.viewEditHistoryViewModelFactory.create(state)
+        }
+
+    }
+
+    init {
+        loadHistory()
+    }
+
+    private fun loadHistory() {
+        setState { copy(editList = Loading()) }
+        room.fetchEditHistory(eventId, object : MatrixCallback<List<Event>> {
+            override fun onFailure(failure: Throwable) {
+                setState {
+                    copy(editList = Fail(failure))
+                }
+            }
+
+            override fun onSuccess(data: List<Event>) {
+                //TODO until supported by API Add original event manually
+                val withOriginal = data.toMutableList()
+                room.getTimeLineEvent(eventId)?.let {
+                    withOriginal.add(it.root)
+                }
+                setState {
+                    copy(editList = Success(withOriginal))
+                }
+            }
+        })
+    }
+
+}
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ViewReactionBottomSheet.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ViewReactionBottomSheet.kt
index 760b74daf6..d7e41784ea 100644
--- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ViewReactionBottomSheet.kt
+++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ViewReactionBottomSheet.kt
@@ -21,7 +21,6 @@ import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
 import android.widget.LinearLayout
-import androidx.core.view.isVisible
 import androidx.recyclerview.widget.DividerItemDecoration
 import butterknife.BindView
 import butterknife.ButterKnife
@@ -33,7 +32,7 @@ import im.vector.riotx.EmojiCompatFontProvider
 import im.vector.riotx.R
 import im.vector.riotx.core.di.ScreenComponent
 import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData
-import kotlinx.android.synthetic.main.bottom_sheet_display_reactions.*
+import kotlinx.android.synthetic.main.bottom_sheet_epoxylist_with_title.*
 import javax.inject.Inject
 
 /**
@@ -49,14 +48,16 @@ class ViewReactionBottomSheet : VectorBaseBottomSheetDialogFragment() {
     @BindView(R.id.bottom_sheet_display_reactions_list)
     lateinit var epoxyRecyclerView: EpoxyRecyclerView
 
-    private val epoxyController by lazy { ViewReactionsEpoxyController(emojiCompatFontProvider.typeface) }
+    private val epoxyController by lazy {
+        ViewReactionsEpoxyController(requireContext(), emojiCompatFontProvider.typeface)
+    }
 
     override fun injectWith(screenComponent: ScreenComponent) {
         screenComponent.inject(this)
     }
 
     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
-        val view = inflater.inflate(R.layout.bottom_sheet_display_reactions, container, false)
+        val view = inflater.inflate(R.layout.bottom_sheet_epoxylist_with_title, container, false)
         ButterKnife.bind(this, view)
         return view
     }
@@ -67,16 +68,11 @@ class ViewReactionBottomSheet : VectorBaseBottomSheetDialogFragment() {
         val dividerItemDecoration = DividerItemDecoration(epoxyRecyclerView.context,
                 LinearLayout.VERTICAL)
         epoxyRecyclerView.addItemDecoration(dividerItemDecoration)
+        bottomSheetTitle.text = context?.getString(R.string.reactions)
     }
 
 
     override fun invalidate() = withState(viewModel) {
-        if (it.mapReactionKeyToMemberList() == null) {
-            bottomSheetViewReactionSpinner.isVisible = true
-            bottomSheetViewReactionSpinner.animate()
-        } else {
-            bottomSheetViewReactionSpinner.isVisible = false
-        }
         epoxyController.setData(it)
     }
 
diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ViewReactionsEpoxyController.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ViewReactionsEpoxyController.kt
index 57c3d26528..74b3f4925f 100644
--- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ViewReactionsEpoxyController.kt
+++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ViewReactionsEpoxyController.kt
@@ -16,24 +16,47 @@
 
 package im.vector.riotx.features.home.room.detail.timeline.action
 
+import android.content.Context
 import android.graphics.Typeface
 import com.airbnb.epoxy.TypedEpoxyController
+import com.airbnb.mvrx.Fail
+import com.airbnb.mvrx.Incomplete
+import com.airbnb.mvrx.Success
+import im.vector.riotx.R
+import im.vector.riotx.core.ui.list.genericFooterItem
+import im.vector.riotx.core.ui.list.genericLoaderItem
 
 /**
  * Epoxy controller for reaction event list
  */
-class ViewReactionsEpoxyController(private val emojiCompatTypeface: Typeface?) : TypedEpoxyController<DisplayReactionsViewState>() {
+class ViewReactionsEpoxyController(private val context: Context, private val emojiCompatTypeface: Typeface?)
+    : TypedEpoxyController<DisplayReactionsViewState>() {
 
     override fun buildModels(state: DisplayReactionsViewState) {
-        val map = state.mapReactionKeyToMemberList() ?: return
-        map.forEach {
-            reactionInfoSimpleItem {
-                id(it.eventId)
-                emojiTypeFace(emojiCompatTypeface)
-                timeStamp(it.timestamp)
-                reactionKey(it.reactionKey)
-                authorDisplayName(it.authorName ?: it.authorId)
+        when (state.mapReactionKeyToMemberList) {
+            is Incomplete -> {
+                genericLoaderItem {
+                    id("Spinner")
+                }
+            }
+            is Fail       -> {
+                genericFooterItem {
+                    id("failure")
+                    text(context.getString(R.string.unknown_error))
+                }
+            }
+            is Success    -> {
+                state.mapReactionKeyToMemberList()?.forEach {
+                    reactionInfoSimpleItem {
+                        id(it.eventId)
+                        emojiTypeFace(emojiCompatTypeface)
+                        timeStamp(it.timestamp)
+                        reactionKey(it.reactionKey)
+                        authorDisplayName(it.authorName ?: it.authorId)
+                    }
+                }
             }
         }
+
     }
 }
\ No newline at end of file
diff --git a/vector/src/main/res/layout/bottom_sheet_display_reactions.xml b/vector/src/main/res/layout/bottom_sheet_epoxylist_with_title.xml
similarity index 71%
rename from vector/src/main/res/layout/bottom_sheet_display_reactions.xml
rename to vector/src/main/res/layout/bottom_sheet_epoxylist_with_title.xml
index 0f5b63654d..9b3ffb26a3 100644
--- a/vector/src/main/res/layout/bottom_sheet_display_reactions.xml
+++ b/vector/src/main/res/layout/bottom_sheet_epoxylist_with_title.xml
@@ -7,23 +7,14 @@
     android:orientation="vertical">
 
     <TextView
+        android:id="@+id/bottomSheetTitle"
         android:layout_width="match_parent"
         android:layout_height="44dp"
         android:gravity="center_vertical"
         android:padding="8dp"
-        android:text="@string/reactions"
         android:textColor="?android:textColorSecondary"
-        android:textSize="16sp" />
-
-    <ProgressBar
-        android:id="@+id/bottomSheetViewReactionSpinner"
-        style="?android:attr/progressBarStyleSmall"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_margin="8dp"
-        android:visibility="gone"
-        tools:visibility="visible" />
-
+        android:textSize="16sp"
+        tools:text="@string/reactions" />
 
     <com.airbnb.epoxy.EpoxyRecyclerView
         android:id="@+id/bottom_sheet_display_reactions_list"
diff --git a/vector/src/main/res/layout/item_generic_header.xml b/vector/src/main/res/layout/item_generic_header.xml
new file mode 100644
index 0000000000..0d2cf8ebc5
--- /dev/null
+++ b/vector/src/main/res/layout/item_generic_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/itemGenericHeaderText"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingLeft="16dp"
+    android:paddingTop="4dp"
+    android:paddingRight="16dp"
+    android:paddingBottom="4dp"
+    android:textColor="?vctr_notice_text_color"
+    android:textSize="15sp"
+    android:textStyle="bold"
+    tools:text="Today" />
\ No newline at end of file
diff --git a/vector/src/main/res/layout/item_generic_loader.xml b/vector/src/main/res/layout/item_generic_loader.xml
new file mode 100644
index 0000000000..53460c4e7a
--- /dev/null
+++ b/vector/src/main/res/layout/item_generic_loader.xml
@@ -0,0 +1,6 @@
+<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/genericProgressSpinner"
+    style="?android:attr/progressBarStyleSmall"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_margin="8dp" />
\ No newline at end of file
diff --git a/vector/src/main/res/values/strings_riotX.xml b/vector/src/main/res/values/strings_riotX.xml
index 7c1d39c4df..9a20356ed1 100644
--- a/vector/src/main/res/values/strings_riotX.xml
+++ b/vector/src/main/res/values/strings_riotX.xml
@@ -21,4 +21,8 @@
     <string name="riotx_no_registration_notice_colored_part">Use the old app</string>
 
 
+
+    <string name="message_edits">Message Edits</string>
+    <string name="no_message_edits_found">No edits found</string>
+
 </resources>
\ No newline at end of file