Epoxy : finalize replacing KotlinModels

This commit is contained in:
ganfra 2019-02-19 15:47:50 +01:00
parent c977c651a2
commit 24ffd96b6e
18 changed files with 142 additions and 169 deletions

View File

@ -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.")
}
}
}

View File

@ -26,15 +26,15 @@ import kotlin.reflect.KProperty
* *
* See [SampleKotlinModelWithHolder] for a usage example. * See [SampleKotlinModelWithHolder] for a usage example.
*/ */
abstract class KotlinEpoxyHolder : EpoxyHolder() { abstract class RiotEpoxyHolder : EpoxyHolder() {
private lateinit var view: View private lateinit var view: View


override fun bindView(itemView: View) { override fun bindView(itemView: View) {
view = itemView view = itemView
} }


protected fun <V : View> bind(id: Int): ReadOnlyProperty<KotlinEpoxyHolder, V> = protected fun <V : View> bind(id: Int): ReadOnlyProperty<RiotEpoxyHolder, V> =
Lazy { holder: KotlinEpoxyHolder, prop -> Lazy { holder: RiotEpoxyHolder, prop ->
holder.view.findViewById(id) as V? holder.view.findViewById(id) as V?
?: throw IllegalStateException("View ID $id for '${prop.name}' not found.") ?: throw IllegalStateException("View ID $id for '${prop.name}' not found.")
} }
@ -44,13 +44,13 @@ abstract class KotlinEpoxyHolder : EpoxyHolder() {
* https://github.com/JakeWharton/kotterknife * https://github.com/JakeWharton/kotterknife
*/ */
private class Lazy<V>( private class Lazy<V>(
private val initializer: (KotlinEpoxyHolder, KProperty<*>) -> V private val initializer: (RiotEpoxyHolder, KProperty<*>) -> V
) : ReadOnlyProperty<KotlinEpoxyHolder, V> { ) : ReadOnlyProperty<RiotEpoxyHolder, V> {
private object EMPTY private object EMPTY


private var value: Any? = 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) { if (value == EMPTY) {
value = initializer(thisRef, property) value = initializer(thisRef, property)
} }

View File

@ -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)
}


}

View File

@ -21,7 +21,7 @@ import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass import com.airbnb.epoxy.EpoxyModelClass
import com.airbnb.epoxy.EpoxyModelWithHolder import com.airbnb.epoxy.EpoxyModelWithHolder
import im.vector.riotredesign.R 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.core.platform.CheckableFrameLayout
import im.vector.riotredesign.features.home.AvatarRenderer import im.vector.riotredesign.features.home.AvatarRenderer


@ -40,7 +40,7 @@ abstract class GroupSummaryItem : EpoxyModelWithHolder<GroupSummaryItem.Holder>(
AvatarRenderer.render(avatarUrl, groupName.toString(), holder.avatarImageView) AvatarRenderer.render(avatarUrl, groupName.toString(), holder.avatarImageView)
} }


class Holder : KotlinEpoxyHolder() { class Holder : RiotEpoxyHolder() {
val avatarImageView by bind<ImageView>(R.id.groupAvatarImageView) val avatarImageView by bind<ImageView>(R.id.groupAvatarImageView)
val rootView by bind<CheckableFrameLayout>(R.id.itemGroupLayout) val rootView by bind<CheckableFrameLayout>(R.id.itemGroupLayout)
} }

View File

@ -19,11 +19,11 @@ package im.vector.riotredesign.features.home.room.detail.timeline
import android.view.View import android.view.View
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import com.airbnb.epoxy.EpoxyModelWithHolder import im.vector.riotredesign.core.epoxy.RiotEpoxyHolder
import im.vector.riotredesign.core.epoxy.KotlinEpoxyHolder import im.vector.riotredesign.core.epoxy.RiotEpoxyModel
import im.vector.riotredesign.features.home.AvatarRenderer 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 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 avatarImageView: ImageView
abstract val memberNameView: TextView abstract val memberNameView: TextView
abstract val timeView: TextView abstract val timeView: TextView

View File

@ -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
}

}

View File

@ -17,16 +17,22 @@
package im.vector.riotredesign.features.home.room.detail.timeline package im.vector.riotredesign.features.home.room.detail.timeline


import android.widget.TextView 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.R
import im.vector.riotredesign.core.epoxy.KotlinModel import im.vector.riotredesign.core.epoxy.RiotEpoxyHolder


data class DaySeparatorItem( @EpoxyModelClass(layout = R.layout.item_timeline_event_day_separator)
val formattedDay: CharSequence abstract class DaySeparatorItem : EpoxyModelWithHolder<DaySeparatorItem.Holder>() {
) : KotlinModel(R.layout.item_timeline_event_day_separator) {


private val dayTextView by bind<TextView>(R.id.itemDayTextView) @EpoxyAttribute lateinit var formattedDay: CharSequence


override fun bind() { override fun bind(holder: Holder) {
dayTextView.text = formattedDay holder.dayTextView.text = formattedDay
}

class Holder : RiotEpoxyHolder() {
val dayTextView by bind<TextView>(R.id.itemDayTextView)
} }
} }

View File

@ -17,16 +17,22 @@
package im.vector.riotredesign.features.home.room.detail.timeline package im.vector.riotredesign.features.home.room.detail.timeline


import android.widget.TextView import android.widget.TextView
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.riotredesign.R 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( @EpoxyModelClass(layout = R.layout.item_timeline_event_default)
val text: CharSequence? = null abstract class DefaultItem : RiotEpoxyModel<DefaultItem.Holder>() {
) : KotlinModel(R.layout.item_timeline_event_default) {


private val messageView by bind<TextView>(R.id.stateMessageView) @EpoxyAttribute var text: CharSequence? = null


override fun bind() { override fun bind(holder: Holder) {
messageView.text = text holder.messageView.text = text
}

class Holder : RiotEpoxyHolder() {
val messageView by bind<TextView>(R.id.stateMessageView)
} }
} }

View File

@ -26,7 +26,7 @@ class DefaultItemFactory {
} else { } else {
"an exception occurred when rendering the event ${event.root.eventId}" "an exception occurred when rendering the event ${event.root.eventId}"
} }
return DefaultItem(text = text) return DefaultItem_().text(text)
} }


} }

View File

@ -18,7 +18,6 @@ package im.vector.riotredesign.features.home.room.detail.timeline


import android.text.SpannableStringBuilder import android.text.SpannableStringBuilder
import android.text.util.Linkify 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.MatrixLinkify
import im.vector.matrix.android.api.permalinks.MatrixPermalinkSpan import im.vector.matrix.android.api.permalinks.MatrixPermalinkSpan
import im.vector.matrix.android.api.session.events.model.EventType 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.MessageImageContent
import im.vector.matrix.android.api.session.room.model.message.MessageTextContent import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent 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.core.extensions.localDateTime
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
import im.vector.riotredesign.features.media.MediaContentRenderer import im.vector.riotredesign.features.media.MediaContentRenderer
@ -40,7 +39,7 @@ class MessageItemFactory(private val timelineMediaSizeProvider: TimelineMediaSiz
fun create(event: TimelineEvent, fun create(event: TimelineEvent,
nextEvent: TimelineEvent?, nextEvent: TimelineEvent?,
callback: TimelineEventController.Callback? callback: TimelineEventController.Callback?
): EpoxyModel<*>? { ): RiotEpoxyModel<*>? {


val roomMember = event.roomMember val roomMember = event.roomMember
val nextRoomMember = nextEvent?.roomMember val nextRoomMember = nextEvent?.roomMember
@ -49,12 +48,12 @@ class MessageItemFactory(private val timelineMediaSizeProvider: TimelineMediaSiz
val nextDate = nextEvent?.root?.localDateTime() val nextDate = nextEvent?.root?.localDateTime()
val addDaySeparator = date.toLocalDate() != nextDate?.toLocalDate() val addDaySeparator = date.toLocalDate() != nextDate?.toLocalDate()
val isNextMessageReceivedMoreThanOneHourAgo = nextDate?.isBefore(date.minusMinutes(60)) val isNextMessageReceivedMoreThanOneHourAgo = nextDate?.isBefore(date.minusMinutes(60))
?: false ?: false


if (addDaySeparator if (addDaySeparator
|| nextRoomMember != roomMember || nextRoomMember != roomMember
|| nextEvent?.root?.type != EventType.MESSAGE || nextEvent?.root?.type != EventType.MESSAGE
|| isNextMessageReceivedMoreThanOneHourAgo) { || isNextMessageReceivedMoreThanOneHourAgo) {
messagesDisplayedWithInformation.add(event.root.eventId) 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" val text = "${messageContent.type} message events are not yet handled"
return DefaultItem(text = text) return DefaultItem_().text(text)
} }


private fun buildImageMessageItem(messageContent: MessageImageContent, private fun buildImageMessageItem(messageContent: MessageImageContent,

View File

@ -18,20 +18,27 @@ package im.vector.riotredesign.features.home.room.detail.timeline


import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.riotredesign.R 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 import im.vector.riotredesign.features.home.AvatarRenderer


class NoticeItem(private val noticeText: CharSequence? = null, @EpoxyModelClass(layout = R.layout.item_timeline_event_notice)
private val avatarUrl: String?, abstract class NoticeItem : RiotEpoxyModel<NoticeItem.Holder>() {
private val memberName: CharSequence? = null)
: KotlinModel(R.layout.item_timeline_event_notice) {


private val avatarImageView by bind<ImageView>(R.id.itemNoticeAvatarView) @EpoxyAttribute var noticeText: CharSequence? = null
private val noticeTextView by bind<TextView>(R.id.itemNoticeTextView) @EpoxyAttribute var avatarUrl: String? = null
@EpoxyAttribute var memberName: CharSequence? = null


override fun bind() { override fun bind(holder: Holder) {
noticeTextView.text = noticeText holder.noticeTextView.text = noticeText
AvatarRenderer.render(avatarUrl, memberName?.toString(), avatarImageView) 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)
} }
} }

View File

@ -17,10 +17,10 @@
package im.vector.riotredesign.features.home.room.detail.timeline package im.vector.riotredesign.features.home.room.detail.timeline


import android.text.TextUtils 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.events.model.toModel
import im.vector.matrix.android.api.session.room.model.Membership 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.model.RoomMember
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.riotredesign.R import im.vector.riotredesign.R
import im.vector.riotredesign.core.resources.StringProvider import im.vector.riotredesign.core.resources.StringProvider


@ -31,7 +31,10 @@ class RoomMemberItemFactory(private val stringProvider: StringProvider) {
fun create(event: TimelineEvent): NoticeItem? { fun create(event: TimelineEvent): NoticeItem? {
val roomMember = event.roomMember ?: return null val roomMember = event.roomMember ?: return null
val noticeText = buildRoomMemberNotice(event) ?: 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? { private fun buildRoomMemberNotice(event: TimelineEvent): String? {

View File

@ -17,9 +17,9 @@
package im.vector.riotredesign.features.home.room.detail.timeline package im.vector.riotredesign.features.home.room.detail.timeline


import android.text.TextUtils 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.events.model.toModel
import im.vector.matrix.android.api.session.room.model.RoomNameContent 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.R
import im.vector.riotredesign.core.resources.StringProvider import im.vector.riotredesign.core.resources.StringProvider


@ -37,7 +37,10 @@ class RoomNameItemFactory(private val stringProvider: StringProvider) {
} else { } else {
stringProvider.getString(R.string.notice_room_name_removed, roomMember.displayName) 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)
} }





View File

@ -36,7 +36,10 @@ class RoomTopicItemFactory(private val stringProvider: StringProvider) {
} else { } else {
stringProvider.getString(R.string.notice_room_topic_changed, roomMember.displayName, content.topic) 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)
} }





View File

@ -16,16 +16,14 @@


package im.vector.riotredesign.features.home.room.detail.timeline package im.vector.riotredesign.features.home.room.detail.timeline


import android.view.View
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.airbnb.epoxy.EpoxyAsyncUtil import com.airbnb.epoxy.EpoxyAsyncUtil
import com.airbnb.epoxy.EpoxyModel import com.airbnb.epoxy.EpoxyModel
import com.airbnb.epoxy.OnModelVisibilityStateChangedListener
import com.airbnb.epoxy.VisibilityState import com.airbnb.epoxy.VisibilityState
import im.vector.matrix.android.api.session.events.model.EventType 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.TimelineData
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent 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.core.extensions.localDateTime
import im.vector.riotredesign.features.home.LoadingItemModel_ import im.vector.riotredesign.features.home.LoadingItemModel_
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider 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 { timelineItemFactory.create(event, nextEvent, callback)?.also {
it.id(event.localId) it.id(event.localId)
it.setOnVisibilityStateChanged(OnModelVisibilityStateChangedListener<KotlinModel, View> { model, view, visibilityState -> it.setOnVisibilityStateChanged(TimelineEventVisibilityStateChangedListener(callback, event, currentPosition))
if (visibilityState == VisibilityState.VISIBLE) {
callback?.onEventVisible(event, currentPosition)
}
})
epoxyModels.add(it) epoxyModels.add(it)
} }
if (addDaySeparator) { if (addDaySeparator) {
val formattedDay = dateFormatter.formatMessageDay(date) val formattedDay = dateFormatter.formatMessageDay(date)
val daySeparatorItem = DaySeparatorItem(formattedDay).id(roomId + formattedDay) val daySeparatorItem = DaySeparatorItem_().formattedDay(formattedDay).id(roomId + formattedDay)
epoxyModels.add(daySeparatorItem) epoxyModels.add(daySeparatorItem)
} }
return epoxyModels return epoxyModels
@ -111,4 +105,18 @@ class TimelineEventController(private val roomId: String,
fun onUrlClicked(url: 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)
}
}


} }

View File

@ -16,9 +16,9 @@


package im.vector.riotredesign.features.home.room.detail.timeline 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.events.model.EventType
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.riotredesign.core.epoxy.RiotEpoxyModel


class TimelineItemFactory(private val messageItemFactory: MessageItemFactory, class TimelineItemFactory(private val messageItemFactory: MessageItemFactory,
private val roomNameItemFactory: RoomNameItemFactory, private val roomNameItemFactory: RoomNameItemFactory,
@ -28,7 +28,7 @@ class TimelineItemFactory(private val messageItemFactory: MessageItemFactory,


fun create(event: TimelineEvent, fun create(event: TimelineEvent,
nextEvent: TimelineEvent?, nextEvent: TimelineEvent?,
callback: TimelineEventController.Callback?): EpoxyModel<*>? { callback: TimelineEventController.Callback?): RiotEpoxyModel<*>? {


return try { return try {
when (event.root.type) { when (event.root.type) {

View File

@ -24,7 +24,7 @@ import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass import com.airbnb.epoxy.EpoxyModelClass
import com.airbnb.epoxy.EpoxyModelWithHolder import com.airbnb.epoxy.EpoxyModelWithHolder
import im.vector.riotredesign.R 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) @EpoxyModelClass(layout = R.layout.item_room_category)
abstract class RoomCategoryItem : EpoxyModelWithHolder<RoomCategoryItem.Holder>() { 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 unreadCounterBadgeView by bind<UnreadCounterBadgeView>(R.id.roomCategoryUnreadCounterBadgeView)
val titleView by bind<TextView>(R.id.roomCategoryTitleView) val titleView by bind<TextView>(R.id.roomCategoryTitleView)
val rootView by bind<ViewGroup>(R.id.roomCategoryRootView) val rootView by bind<ViewGroup>(R.id.roomCategoryRootView)

View File

@ -22,7 +22,7 @@ import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass import com.airbnb.epoxy.EpoxyModelClass
import com.airbnb.epoxy.EpoxyModelWithHolder import com.airbnb.epoxy.EpoxyModelWithHolder
import im.vector.riotredesign.R 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.core.platform.CheckableFrameLayout
import im.vector.riotredesign.features.home.AvatarRenderer import im.vector.riotredesign.features.home.AvatarRenderer


@ -47,7 +47,7 @@ abstract class RoomSummaryItem : EpoxyModelWithHolder<RoomSummaryItem.Holder>()
AvatarRenderer.render(avatarUrl, roomName.toString(), holder.avatarImageView) AvatarRenderer.render(avatarUrl, roomName.toString(), holder.avatarImageView)
} }


class Holder : KotlinEpoxyHolder() { class Holder : RiotEpoxyHolder() {
val unreadCounterBadgeView by bind<UnreadCounterBadgeView>(R.id.roomUnreadCounterBadgeView) val unreadCounterBadgeView by bind<UnreadCounterBadgeView>(R.id.roomUnreadCounterBadgeView)
val titleView by bind<TextView>(R.id.roomNameView) val titleView by bind<TextView>(R.id.roomNameView)
val avatarImageView by bind<ImageView>(R.id.roomAvatarImageView) val avatarImageView by bind<ImageView>(R.id.roomAvatarImageView)