diff --git a/app/src/main/java/im/vector/riotredesign/core/epoxy/KotlinModel.kt b/app/src/main/java/im/vector/riotredesign/core/epoxy/KotlinModel.kt
deleted file mode 100644
index dd651468cd..0000000000
--- a/app/src/main/java/im/vector/riotredesign/core/epoxy/KotlinModel.kt
+++ /dev/null
@@ -1,74 +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.riotredesign.core.epoxy
-
-import android.view.View
-import androidx.annotation.IdRes
-import androidx.annotation.LayoutRes
-import com.airbnb.epoxy.EpoxyModel
-import com.airbnb.epoxy.OnModelVisibilityStateChangedListener
-import kotlin.properties.ReadOnlyProperty
-import kotlin.reflect.KProperty
-
-abstract class KotlinModel(
-        @LayoutRes private val layoutRes: Int
-) : EpoxyModel<View>() {
-
-    private var view: View? = null
-    private var onBindCallback: (() -> Unit)? = null
-    private var onModelVisibilityStateChangedListener: OnModelVisibilityStateChangedListener<KotlinModel, View>? = null
-
-    abstract fun bind()
-
-    override fun bind(view: View) {
-        this.view = view
-        onBindCallback?.invoke()
-        bind()
-    }
-
-    override fun unbind(view: View) {
-        this.view = null
-    }
-
-    fun onBind(lambda: (() -> Unit)?): KotlinModel {
-        onBindCallback = lambda
-        return this
-    }
-
-    override fun onVisibilityStateChanged(visibilityState: Int, view: View) {
-        onModelVisibilityStateChangedListener?.onVisibilityStateChanged(this, view, visibilityState)
-        super.onVisibilityStateChanged(visibilityState, view)
-    }
-
-    fun setOnVisibilityStateChanged(listener: OnModelVisibilityStateChangedListener<KotlinModel, View>): KotlinModel {
-        this.onModelVisibilityStateChangedListener = listener
-        return this
-    }
-
-    override fun getDefaultLayout() = layoutRes
-
-    protected fun <V : View> bind(@IdRes id: Int) = object : ReadOnlyProperty<KotlinModel, V> {
-        override fun getValue(thisRef: KotlinModel, property: KProperty<*>): V {
-            // This is not efficient because it looks up the view by id every time (it loses
-            // the pattern of a "holder" to cache that look up). But it is simple to use and could
-            // be optimized with a map
-            @Suppress("UNCHECKED_CAST")
-            return view?.findViewById(id) as V?
-                   ?: throw IllegalStateException("View ID $id for '${property.name}' not found.")
-        }
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/im/vector/riotredesign/core/epoxy/KotlinEpoxyHolder.kt b/app/src/main/java/im/vector/riotredesign/core/epoxy/RiotEpoxyHolder.kt
similarity index 79%
rename from app/src/main/java/im/vector/riotredesign/core/epoxy/KotlinEpoxyHolder.kt
rename to app/src/main/java/im/vector/riotredesign/core/epoxy/RiotEpoxyHolder.kt
index 8b9cc92a04..f698394026 100644
--- a/app/src/main/java/im/vector/riotredesign/core/epoxy/KotlinEpoxyHolder.kt
+++ b/app/src/main/java/im/vector/riotredesign/core/epoxy/RiotEpoxyHolder.kt
@@ -26,15 +26,15 @@ import kotlin.reflect.KProperty
  *
  * See [SampleKotlinModelWithHolder] for a usage example.
  */
-abstract class KotlinEpoxyHolder : EpoxyHolder() {
+abstract class RiotEpoxyHolder : EpoxyHolder() {
     private lateinit var view: View
 
     override fun bindView(itemView: View) {
         view = itemView
     }
 
-    protected fun <V : View> bind(id: Int): ReadOnlyProperty<KotlinEpoxyHolder, V> =
-            Lazy { holder: KotlinEpoxyHolder, prop ->
+    protected fun <V : View> bind(id: Int): ReadOnlyProperty<RiotEpoxyHolder, V> =
+            Lazy { holder: RiotEpoxyHolder, prop ->
                 holder.view.findViewById(id) as V?
                 ?: throw IllegalStateException("View ID $id for '${prop.name}' not found.")
             }
@@ -44,13 +44,13 @@ abstract class KotlinEpoxyHolder : EpoxyHolder() {
      * https://github.com/JakeWharton/kotterknife
      */
     private class Lazy<V>(
-            private val initializer: (KotlinEpoxyHolder, KProperty<*>) -> V
-    ) : ReadOnlyProperty<KotlinEpoxyHolder, V> {
+            private val initializer: (RiotEpoxyHolder, KProperty<*>) -> V
+    ) : ReadOnlyProperty<RiotEpoxyHolder, V> {
         private object EMPTY
 
         private var value: Any? = EMPTY
 
-        override fun getValue(thisRef: KotlinEpoxyHolder, property: KProperty<*>): V {
+        override fun getValue(thisRef: RiotEpoxyHolder, property: KProperty<*>): V {
             if (value == EMPTY) {
                 value = initializer(thisRef, property)
             }
diff --git a/app/src/main/java/im/vector/riotredesign/core/epoxy/RiotEpoxyModel.kt b/app/src/main/java/im/vector/riotredesign/core/epoxy/RiotEpoxyModel.kt
new file mode 100644
index 0000000000..e93fc3cb22
--- /dev/null
+++ b/app/src/main/java/im/vector/riotredesign/core/epoxy/RiotEpoxyModel.kt
@@ -0,0 +1,41 @@
+/*
+ * 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.riotredesign.core.epoxy
+
+import com.airbnb.epoxy.EpoxyModelWithHolder
+import com.airbnb.epoxy.VisibilityState
+
+abstract class RiotEpoxyModel<H : RiotEpoxyHolder> : EpoxyModelWithHolder<H>() {
+
+    private var onModelVisibilityStateChangedListener: OnVisibilityStateChangedListener? = null
+
+    override fun onVisibilityStateChanged(visibilityState: Int, view: H) {
+        onModelVisibilityStateChangedListener?.onVisibilityStateChanged(visibilityState)
+        super.onVisibilityStateChanged(visibilityState, view)
+    }
+
+    fun setOnVisibilityStateChanged(listener: OnVisibilityStateChangedListener): RiotEpoxyModel<H> {
+        this.onModelVisibilityStateChangedListener = listener
+        return this
+    }
+
+    interface OnVisibilityStateChangedListener {
+        fun onVisibilityStateChanged(@VisibilityState.Visibility visibilityState: Int)
+    }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/im/vector/riotredesign/features/home/group/GroupSummaryItem.kt b/app/src/main/java/im/vector/riotredesign/features/home/group/GroupSummaryItem.kt
index 5b23f408de..ddf7cdeae3 100644
--- a/app/src/main/java/im/vector/riotredesign/features/home/group/GroupSummaryItem.kt
+++ b/app/src/main/java/im/vector/riotredesign/features/home/group/GroupSummaryItem.kt
@@ -21,7 +21,7 @@ import com.airbnb.epoxy.EpoxyAttribute
 import com.airbnb.epoxy.EpoxyModelClass
 import com.airbnb.epoxy.EpoxyModelWithHolder
 import im.vector.riotredesign.R
-import im.vector.riotredesign.core.epoxy.KotlinEpoxyHolder
+import im.vector.riotredesign.core.epoxy.RiotEpoxyHolder
 import im.vector.riotredesign.core.platform.CheckableFrameLayout
 import im.vector.riotredesign.features.home.AvatarRenderer
 
@@ -40,7 +40,7 @@ abstract class GroupSummaryItem : EpoxyModelWithHolder<GroupSummaryItem.Holder>(
         AvatarRenderer.render(avatarUrl, groupName.toString(), holder.avatarImageView)
     }
 
-    class Holder : KotlinEpoxyHolder() {
+    class Holder : RiotEpoxyHolder() {
         val avatarImageView by bind<ImageView>(R.id.groupAvatarImageView)
         val rootView by bind<CheckableFrameLayout>(R.id.itemGroupLayout)
     }
diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/AbsMessageItem.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/AbsMessageItem.kt
index 3127cb5b2a..8a598d0f35 100644
--- a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/AbsMessageItem.kt
+++ b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/AbsMessageItem.kt
@@ -19,11 +19,11 @@ package im.vector.riotredesign.features.home.room.detail.timeline
 import android.view.View
 import android.widget.ImageView
 import android.widget.TextView
-import com.airbnb.epoxy.EpoxyModelWithHolder
-import im.vector.riotredesign.core.epoxy.KotlinEpoxyHolder
+import im.vector.riotredesign.core.epoxy.RiotEpoxyHolder
+import im.vector.riotredesign.core.epoxy.RiotEpoxyModel
 import im.vector.riotredesign.features.home.AvatarRenderer
 
-abstract class AbsMessageItem<H : AbsMessageItem.Holder> : EpoxyModelWithHolder<H>() {
+abstract class AbsMessageItem<H : AbsMessageItem.Holder> : RiotEpoxyModel<H>() {
 
     abstract val informationData: MessageInformationData
 
@@ -42,7 +42,7 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : EpoxyModelWithHolder<
         }
     }
 
-    abstract class Holder : KotlinEpoxyHolder() {
+    abstract class Holder : RiotEpoxyHolder() {
         abstract val avatarImageView: ImageView
         abstract val memberNameView: TextView
         abstract val timeView: TextView
diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/BlankItem.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/BlankItem.kt
deleted file mode 100644
index 156a5281b4..0000000000
--- a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/BlankItem.kt
+++ /dev/null
@@ -1,29 +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.riotredesign.features.home.room.detail.timeline
-
-import im.vector.riotredesign.R
-import im.vector.riotredesign.core.epoxy.KotlinModel
-
-class BlankItem
-    : KotlinModel(R.layout.item_timeline_event_blank) {
-
-    override fun bind() {
-        //no-op
-    }
-
-}
\ No newline at end of file
diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/DaySeparatorItem.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/DaySeparatorItem.kt
index e80ec2bacd..6f1bcc7c36 100644
--- a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/DaySeparatorItem.kt
+++ b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/DaySeparatorItem.kt
@@ -17,16 +17,22 @@
 package im.vector.riotredesign.features.home.room.detail.timeline
 
 import android.widget.TextView
+import com.airbnb.epoxy.EpoxyAttribute
+import com.airbnb.epoxy.EpoxyModelClass
+import com.airbnb.epoxy.EpoxyModelWithHolder
 import im.vector.riotredesign.R
-import im.vector.riotredesign.core.epoxy.KotlinModel
+import im.vector.riotredesign.core.epoxy.RiotEpoxyHolder
 
-data class DaySeparatorItem(
-        val formattedDay: CharSequence
-) : KotlinModel(R.layout.item_timeline_event_day_separator) {
+@EpoxyModelClass(layout = R.layout.item_timeline_event_day_separator)
+abstract class DaySeparatorItem : EpoxyModelWithHolder<DaySeparatorItem.Holder>() {
 
-    private val dayTextView by bind<TextView>(R.id.itemDayTextView)
+    @EpoxyAttribute lateinit var formattedDay: CharSequence
 
-    override fun bind() {
-        dayTextView.text = formattedDay
+    override fun bind(holder: Holder) {
+        holder.dayTextView.text = formattedDay
+    }
+
+    class Holder : RiotEpoxyHolder() {
+        val dayTextView by bind<TextView>(R.id.itemDayTextView)
     }
 }
\ No newline at end of file
diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/DefaultItem.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/DefaultItem.kt
index b9db438484..3d399e2f45 100644
--- a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/DefaultItem.kt
+++ b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/DefaultItem.kt
@@ -17,16 +17,22 @@
 package im.vector.riotredesign.features.home.room.detail.timeline
 
 import android.widget.TextView
+import com.airbnb.epoxy.EpoxyAttribute
+import com.airbnb.epoxy.EpoxyModelClass
 import im.vector.riotredesign.R
-import im.vector.riotredesign.core.epoxy.KotlinModel
+import im.vector.riotredesign.core.epoxy.RiotEpoxyHolder
+import im.vector.riotredesign.core.epoxy.RiotEpoxyModel
 
-class DefaultItem(
-        val text: CharSequence? = null
-) : KotlinModel(R.layout.item_timeline_event_default) {
+@EpoxyModelClass(layout = R.layout.item_timeline_event_default)
+abstract class DefaultItem : RiotEpoxyModel<DefaultItem.Holder>() {
 
-    private val messageView by bind<TextView>(R.id.stateMessageView)
+    @EpoxyAttribute var text: CharSequence? = null
 
-    override fun bind() {
-        messageView.text = text
+    override fun bind(holder: Holder) {
+        holder.messageView.text = text
+    }
+
+    class Holder : RiotEpoxyHolder() {
+        val messageView by bind<TextView>(R.id.stateMessageView)
     }
 }
\ No newline at end of file
diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/DefaultItemFactory.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/DefaultItemFactory.kt
index 03a631eaf1..c168d89e17 100644
--- a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/DefaultItemFactory.kt
+++ b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/DefaultItemFactory.kt
@@ -26,7 +26,7 @@ class DefaultItemFactory {
         } else {
             "an exception occurred when rendering the event ${event.root.eventId}"
         }
-        return DefaultItem(text = text)
+        return DefaultItem_().text(text)
     }
 
 }
\ No newline at end of file
diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/MessageItemFactory.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/MessageItemFactory.kt
index ba57c08662..a52659de62 100644
--- a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/MessageItemFactory.kt
+++ b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/MessageItemFactory.kt
@@ -18,7 +18,6 @@ package im.vector.riotredesign.features.home.room.detail.timeline
 
 import android.text.SpannableStringBuilder
 import android.text.util.Linkify
-import com.airbnb.epoxy.EpoxyModel
 import im.vector.matrix.android.api.permalinks.MatrixLinkify
 import im.vector.matrix.android.api.permalinks.MatrixPermalinkSpan
 import im.vector.matrix.android.api.session.events.model.EventType
@@ -27,7 +26,7 @@ import im.vector.matrix.android.api.session.room.model.message.MessageContent
 import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
 import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
 import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
-import im.vector.riotredesign.core.epoxy.KotlinModel
+import im.vector.riotredesign.core.epoxy.RiotEpoxyModel
 import im.vector.riotredesign.core.extensions.localDateTime
 import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
 import im.vector.riotredesign.features.media.MediaContentRenderer
@@ -40,7 +39,7 @@ class MessageItemFactory(private val timelineMediaSizeProvider: TimelineMediaSiz
     fun create(event: TimelineEvent,
                nextEvent: TimelineEvent?,
                callback: TimelineEventController.Callback?
-    ): EpoxyModel<*>? {
+    ): RiotEpoxyModel<*>? {
 
         val roomMember = event.roomMember
         val nextRoomMember = nextEvent?.roomMember
@@ -49,12 +48,12 @@ class MessageItemFactory(private val timelineMediaSizeProvider: TimelineMediaSiz
         val nextDate = nextEvent?.root?.localDateTime()
         val addDaySeparator = date.toLocalDate() != nextDate?.toLocalDate()
         val isNextMessageReceivedMoreThanOneHourAgo = nextDate?.isBefore(date.minusMinutes(60))
-                                                      ?: false
+                ?: false
 
         if (addDaySeparator
-            || nextRoomMember != roomMember
-            || nextEvent?.root?.type != EventType.MESSAGE
-            || isNextMessageReceivedMoreThanOneHourAgo) {
+                || nextRoomMember != roomMember
+                || nextEvent?.root?.type != EventType.MESSAGE
+                || isNextMessageReceivedMoreThanOneHourAgo) {
             messagesDisplayedWithInformation.add(event.root.eventId)
         }
 
@@ -72,9 +71,9 @@ class MessageItemFactory(private val timelineMediaSizeProvider: TimelineMediaSiz
         }
     }
 
-    private fun buildNotHandledMessageItem(messageContent: MessageContent): KotlinModel? {
+    private fun buildNotHandledMessageItem(messageContent: MessageContent): DefaultItem? {
         val text = "${messageContent.type} message events are not yet handled"
-        return DefaultItem(text = text)
+        return DefaultItem_().text(text)
     }
 
     private fun buildImageMessageItem(messageContent: MessageImageContent,
diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/NoticeItem.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/NoticeItem.kt
index 14f9159c33..63c4ae1758 100644
--- a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/NoticeItem.kt
+++ b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/NoticeItem.kt
@@ -18,20 +18,27 @@ package im.vector.riotredesign.features.home.room.detail.timeline
 
 import android.widget.ImageView
 import android.widget.TextView
+import com.airbnb.epoxy.EpoxyAttribute
+import com.airbnb.epoxy.EpoxyModelClass
 import im.vector.riotredesign.R
-import im.vector.riotredesign.core.epoxy.KotlinModel
+import im.vector.riotredesign.core.epoxy.RiotEpoxyHolder
+import im.vector.riotredesign.core.epoxy.RiotEpoxyModel
 import im.vector.riotredesign.features.home.AvatarRenderer
 
-class NoticeItem(private val noticeText: CharSequence? = null,
-                 private val avatarUrl: String?,
-                 private val memberName: CharSequence? = null)
-    : KotlinModel(R.layout.item_timeline_event_notice) {
+@EpoxyModelClass(layout = R.layout.item_timeline_event_notice)
+abstract class NoticeItem : RiotEpoxyModel<NoticeItem.Holder>() {
 
-    private val avatarImageView by bind<ImageView>(R.id.itemNoticeAvatarView)
-    private val noticeTextView by bind<TextView>(R.id.itemNoticeTextView)
+    @EpoxyAttribute var noticeText: CharSequence? = null
+    @EpoxyAttribute var avatarUrl: String? = null
+    @EpoxyAttribute var memberName: CharSequence? = null
 
-    override fun bind() {
-        noticeTextView.text = noticeText
-        AvatarRenderer.render(avatarUrl, memberName?.toString(), avatarImageView)
+    override fun bind(holder: Holder) {
+        holder.noticeTextView.text = noticeText
+        AvatarRenderer.render(avatarUrl, memberName?.toString(), holder.avatarImageView)
+    }
+
+    class Holder : RiotEpoxyHolder() {
+        val avatarImageView by bind<ImageView>(R.id.itemNoticeAvatarView)
+        val noticeTextView by bind<TextView>(R.id.itemNoticeTextView)
     }
 }
\ No newline at end of file
diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/RoomMemberItemFactory.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/RoomMemberItemFactory.kt
index ab2347fd0b..e2cf8cbd4f 100644
--- a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/RoomMemberItemFactory.kt
+++ b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/RoomMemberItemFactory.kt
@@ -17,10 +17,10 @@
 package im.vector.riotredesign.features.home.room.detail.timeline
 
 import android.text.TextUtils
-import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
 import im.vector.matrix.android.api.session.events.model.toModel
 import im.vector.matrix.android.api.session.room.model.Membership
 import im.vector.matrix.android.api.session.room.model.RoomMember
+import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
 import im.vector.riotredesign.R
 import im.vector.riotredesign.core.resources.StringProvider
 
@@ -31,7 +31,10 @@ class RoomMemberItemFactory(private val stringProvider: StringProvider) {
     fun create(event: TimelineEvent): NoticeItem? {
         val roomMember = event.roomMember ?: return null
         val noticeText = buildRoomMemberNotice(event) ?: return null
-        return NoticeItem(noticeText, roomMember.avatarUrl, roomMember.displayName)
+        return NoticeItem_()
+                .noticeText(noticeText)
+                .avatarUrl(roomMember.avatarUrl)
+                .memberName(roomMember.displayName)
     }
 
     private fun buildRoomMemberNotice(event: TimelineEvent): String? {
diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/RoomNameItemFactory.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/RoomNameItemFactory.kt
index 8732a926ca..db59e58a72 100644
--- a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/RoomNameItemFactory.kt
+++ b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/RoomNameItemFactory.kt
@@ -17,9 +17,9 @@
 package im.vector.riotredesign.features.home.room.detail.timeline
 
 import android.text.TextUtils
-import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
 import im.vector.matrix.android.api.session.events.model.toModel
 import im.vector.matrix.android.api.session.room.model.RoomNameContent
+import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
 import im.vector.riotredesign.R
 import im.vector.riotredesign.core.resources.StringProvider
 
@@ -37,7 +37,10 @@ class RoomNameItemFactory(private val stringProvider: StringProvider) {
         } else {
             stringProvider.getString(R.string.notice_room_name_removed, roomMember.displayName)
         }
-        return NoticeItem(text, roomMember.avatarUrl, roomMember.displayName)
+        return NoticeItem_()
+                .noticeText(text)
+                .avatarUrl(roomMember.avatarUrl)
+                .memberName(roomMember.displayName)
     }
 
 
diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/RoomTopicItemFactory.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/RoomTopicItemFactory.kt
index 90c7c83f42..f4fe72c9ed 100644
--- a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/RoomTopicItemFactory.kt
+++ b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/RoomTopicItemFactory.kt
@@ -36,7 +36,10 @@ class RoomTopicItemFactory(private val stringProvider: StringProvider) {
         } else {
             stringProvider.getString(R.string.notice_room_topic_changed, roomMember.displayName, content.topic)
         }
-        return NoticeItem(text, roomMember.avatarUrl, roomMember.displayName)
+        return NoticeItem_()
+                .noticeText(text)
+                .avatarUrl(roomMember.avatarUrl)
+                .memberName(roomMember.displayName)
     }
 
 
diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventController.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventController.kt
index 8fc268c3be..75b3f26580 100644
--- a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventController.kt
+++ b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventController.kt
@@ -16,16 +16,14 @@
 
 package im.vector.riotredesign.features.home.room.detail.timeline
 
-import android.view.View
 import androidx.recyclerview.widget.RecyclerView
 import com.airbnb.epoxy.EpoxyAsyncUtil
 import com.airbnb.epoxy.EpoxyModel
-import com.airbnb.epoxy.OnModelVisibilityStateChangedListener
 import com.airbnb.epoxy.VisibilityState
 import im.vector.matrix.android.api.session.events.model.EventType
 import im.vector.matrix.android.api.session.room.timeline.TimelineData
 import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
-import im.vector.riotredesign.core.epoxy.KotlinModel
+import im.vector.riotredesign.core.epoxy.RiotEpoxyModel
 import im.vector.riotredesign.core.extensions.localDateTime
 import im.vector.riotredesign.features.home.LoadingItemModel_
 import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
@@ -78,16 +76,12 @@ class TimelineEventController(private val roomId: String,
 
         timelineItemFactory.create(event, nextEvent, callback)?.also {
             it.id(event.localId)
-            it.setOnVisibilityStateChanged(OnModelVisibilityStateChangedListener<KotlinModel, View> { model, view, visibilityState ->
-                if (visibilityState == VisibilityState.VISIBLE) {
-                    callback?.onEventVisible(event, currentPosition)
-                }
-            })
+            it.setOnVisibilityStateChanged(TimelineEventVisibilityStateChangedListener(callback, event, currentPosition))
             epoxyModels.add(it)
         }
         if (addDaySeparator) {
             val formattedDay = dateFormatter.formatMessageDay(date)
-            val daySeparatorItem = DaySeparatorItem(formattedDay).id(roomId + formattedDay)
+            val daySeparatorItem = DaySeparatorItem_().formattedDay(formattedDay).id(roomId + formattedDay)
             epoxyModels.add(daySeparatorItem)
         }
         return epoxyModels
@@ -111,4 +105,18 @@ class TimelineEventController(private val roomId: String,
         fun onUrlClicked(url: String)
     }
 
+}
+
+private class TimelineEventVisibilityStateChangedListener(private val callback: TimelineEventController.Callback?,
+                                                          private val event: TimelineEvent,
+                                                          private val currentPosition: Int)
+    : RiotEpoxyModel.OnVisibilityStateChangedListener {
+
+    override fun onVisibilityStateChanged(visibilityState: Int) {
+        if (visibilityState == VisibilityState.VISIBLE) {
+            callback?.onEventVisible(event, currentPosition)
+        }
+    }
+
+
 }
\ No newline at end of file
diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineItemFactory.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineItemFactory.kt
index 4becea3585..8fca5301b0 100644
--- a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineItemFactory.kt
+++ b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineItemFactory.kt
@@ -16,9 +16,9 @@
 
 package im.vector.riotredesign.features.home.room.detail.timeline
 
-import com.airbnb.epoxy.EpoxyModel
 import im.vector.matrix.android.api.session.events.model.EventType
 import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
+import im.vector.riotredesign.core.epoxy.RiotEpoxyModel
 
 class TimelineItemFactory(private val messageItemFactory: MessageItemFactory,
                           private val roomNameItemFactory: RoomNameItemFactory,
@@ -28,7 +28,7 @@ class TimelineItemFactory(private val messageItemFactory: MessageItemFactory,
 
     fun create(event: TimelineEvent,
                nextEvent: TimelineEvent?,
-               callback: TimelineEventController.Callback?): EpoxyModel<*>? {
+               callback: TimelineEventController.Callback?): RiotEpoxyModel<*>? {
 
         return try {
             when (event.root.type) {
diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomCategoryItem.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomCategoryItem.kt
index 895be8f6ec..ee990fffd3 100644
--- a/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomCategoryItem.kt
+++ b/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomCategoryItem.kt
@@ -24,7 +24,7 @@ import com.airbnb.epoxy.EpoxyAttribute
 import com.airbnb.epoxy.EpoxyModelClass
 import com.airbnb.epoxy.EpoxyModelWithHolder
 import im.vector.riotredesign.R
-import im.vector.riotredesign.core.epoxy.KotlinEpoxyHolder
+import im.vector.riotredesign.core.epoxy.RiotEpoxyHolder
 
 @EpoxyModelClass(layout = R.layout.item_room_category)
 abstract class RoomCategoryItem : EpoxyModelWithHolder<RoomCategoryItem.Holder>() {
@@ -48,7 +48,7 @@ abstract class RoomCategoryItem : EpoxyModelWithHolder<RoomCategoryItem.Holder>(
     }
 
 
-    class Holder : KotlinEpoxyHolder() {
+    class Holder : RiotEpoxyHolder() {
         val unreadCounterBadgeView by bind<UnreadCounterBadgeView>(R.id.roomCategoryUnreadCounterBadgeView)
         val titleView by bind<TextView>(R.id.roomCategoryTitleView)
         val rootView by bind<ViewGroup>(R.id.roomCategoryRootView)
diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryItem.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryItem.kt
index a45c7909ee..7f83c6aa3a 100644
--- a/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryItem.kt
+++ b/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryItem.kt
@@ -22,7 +22,7 @@ import com.airbnb.epoxy.EpoxyAttribute
 import com.airbnb.epoxy.EpoxyModelClass
 import com.airbnb.epoxy.EpoxyModelWithHolder
 import im.vector.riotredesign.R
-import im.vector.riotredesign.core.epoxy.KotlinEpoxyHolder
+import im.vector.riotredesign.core.epoxy.RiotEpoxyHolder
 import im.vector.riotredesign.core.platform.CheckableFrameLayout
 import im.vector.riotredesign.features.home.AvatarRenderer
 
@@ -47,7 +47,7 @@ abstract class RoomSummaryItem : EpoxyModelWithHolder<RoomSummaryItem.Holder>()
         AvatarRenderer.render(avatarUrl, roomName.toString(), holder.avatarImageView)
     }
 
-    class Holder : KotlinEpoxyHolder() {
+    class Holder : RiotEpoxyHolder() {
         val unreadCounterBadgeView by bind<UnreadCounterBadgeView>(R.id.roomUnreadCounterBadgeView)
         val titleView by bind<TextView>(R.id.roomNameView)
         val avatarImageView by bind<ImageView>(R.id.roomAvatarImageView)