Refactoring (duplication in Message Item Factory) + cleaning

This commit is contained in:
Valere 2019-06-05 23:45:46 +02:00
parent 297f202005
commit e22b555b58
5 changed files with 69 additions and 112 deletions

View File

@ -46,7 +46,7 @@ class TimelineEventController(private val dateFormatter: TimelineDateFormatter,
private val backgroundHandler: Handler = TimelineAsyncHelper.getBackgroundHandler()
) : EpoxyController(backgroundHandler, backgroundHandler), Timeline.Listener {

interface Callback : ReactionPillCallback {
interface Callback : ReactionPillCallback, AvatarCallback {
fun onEventVisible(event: TimelineEvent)
fun onUrlClicked(url: String)
fun onImageMessageClicked(messageImageContent: MessageImageContent, mediaData: ImageContentRenderer.Data, view: View)
@ -55,8 +55,6 @@ class TimelineEventController(private val dateFormatter: TimelineDateFormatter,
fun onAudioMessageClicked(messageAudioContent: MessageAudioContent)
fun onEventCellClicked(informationData: MessageInformationData, messageContent: MessageContent, view: View)
fun onEventLongClicked(informationData: MessageInformationData, messageContent: MessageContent, view: View): Boolean
fun onAvatarClicked(informationData: MessageInformationData)
fun onMemberNameClicked(informationData: MessageInformationData)
fun onEditedDecorationClicked(informationData: MessageInformationData, editAggregatedSummary: EditAggregatedSummary?)
}

@ -65,6 +63,11 @@ class TimelineEventController(private val dateFormatter: TimelineDateFormatter,
fun onLongClickOnReactionPill(informationData: MessageInformationData, reaction: String)
}

interface AvatarCallback {
fun onAvatarClicked(informationData: MessageInformationData)
fun onMemberNameClicked(informationData: MessageInformationData)
}

private val collapsedEventIds = linkedSetOf<String>()
private val mergeItemCollapseStates = HashMap<String, Boolean>()
private val modelCache = arrayListOf<CacheItemData?>()

View File

@ -1,16 +1,12 @@
package im.vector.riotredesign.features.home.room.detail.timeline.action

import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import com.airbnb.mvrx.*
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary
import im.vector.riotredesign.core.extensions.localDateTime
import im.vector.riotredesign.core.platform.VectorViewModel
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDateFormatter
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.koin.android.ext.android.get


@ -33,53 +29,41 @@ data class ReactionInfo(
*/
class ViewReactionViewModel(private val session: Session,
private val timelineDateFormatter: TimelineDateFormatter,
lifecycleOwner: LifecycleOwner?,
liveSummary: LiveData<List<EventAnnotationsSummary>>?,
initialState: DisplayReactionsViewState) : VectorViewModel<DisplayReactionsViewState>(initialState) {

init {
loadReaction()
if (lifecycleOwner != null) {
liveSummary?.observe(lifecycleOwner, Observer {
it?.firstOrNull()?.let {
loadReaction()
}
})
}

}

private fun loadReaction() = withState { state ->
fun loadReaction() = withState { state ->

GlobalScope.launch {
try {
val room = session.getRoom(state.roomId)
val event = room?.getTimeLineEvent(state.eventId)
if (event == null) {
setState { copy(mapReactionKeyToMemberList = Fail(Throwable())) }
return@launch
}
var results = ArrayList<ReactionInfo>()
event.annotations?.reactionsSummary?.forEach { sum ->
try {
val room = session.getRoom(state.roomId)
val event = room?.getTimeLineEvent(state.eventId)
if (event == null) {
setState { copy(mapReactionKeyToMemberList = Fail(Throwable())) }
return@withState
}
var results = ArrayList<ReactionInfo>()
event.annotations?.reactionsSummary?.forEach { sum ->

sum.sourceEvents.mapNotNull { room.getTimeLineEvent(it) }.forEach {
val localDate = it.root.localDateTime()
results.add(ReactionInfo(it.root.eventId!!, sum.key, it.root.sender
?: "", it.senderName, timelineDateFormatter.formatMessageHour(localDate)))
}
}
setState {
copy(
mapReactionKeyToMemberList = Success(results.sortedBy { it.timestamp })
)
}
} catch (t: Throwable) {
setState {
copy(
mapReactionKeyToMemberList = Fail(t)
)
sum.sourceEvents.mapNotNull { room.getTimeLineEvent(it) }.forEach {
val localDate = it.root.localDateTime()
results.add(ReactionInfo(it.root.eventId!!, sum.key, it.root.sender
?: "", it.senderName, timelineDateFormatter.formatMessageHour(localDate)))
}
}
setState {
copy(
mapReactionKeyToMemberList = Success(results.sortedBy { it.timestamp })
)
}
} catch (t: Throwable) {
setState {
copy(
mapReactionKeyToMemberList = Fail(t)
)
}
}
}

@ -98,7 +82,18 @@ class ViewReactionViewModel(private val session: Session,
override fun create(viewModelContext: ViewModelContext, state: DisplayReactionsViewState): ViewReactionViewModel? {
val session = viewModelContext.activity.get<Session>()
val eventId = (viewModelContext.args as TimelineEventFragmentArgs).eventId
return ViewReactionViewModel(session, viewModelContext.activity.get(), viewModelContext.activity, session.getRoom(state.roomId)?.getEventSummaryLive(eventId), state)
val lifecycleOwner = (viewModelContext as FragmentViewModelContext).fragment<Fragment>()
val liveSummary = session.getRoom(state.roomId)?.getEventSummaryLive(eventId)
val viewReactionViewModel = ViewReactionViewModel(session, viewModelContext.activity.get(), state)
// This states observes the live summary
// When fragment context will be destroyed the observer will automatically removed
liveSummary?.observe(lifecycleOwner, Observer {
it?.firstOrNull()?.let {
viewReactionViewModel.loadReaction()
}
})

return viewReactionViewModel
}



View File

@ -143,18 +143,11 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
callback: TimelineEventController.Callback?): MessageFileItem? {
return MessageFileItem_()
.informationData(informationData)
.avatarCallback(callback)
.filename(messageContent.body)
.iconRes(R.drawable.filetype_audio)
.reactionPillCallback(callback)
.emojiTypeFace(emojiCompatFontProvider.typeface)
.avatarClickListener(
DebouncedClickListener(View.OnClickListener {
callback?.onAvatarClicked(informationData)
}))
.memberClickListener(
DebouncedClickListener(View.OnClickListener {
callback?.onMemberNameClicked(informationData)
}))
.cellClickListener(
DebouncedClickListener(View.OnClickListener { view: View ->
callback?.onEventCellClicked(informationData, messageContent, view)
@ -174,18 +167,11 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
callback: TimelineEventController.Callback?): MessageFileItem? {
return MessageFileItem_()
.informationData(informationData)
.avatarCallback(callback)
.filename(messageContent.body)
.reactionPillCallback(callback)
.emojiTypeFace(emojiCompatFontProvider.typeface)
.iconRes(R.drawable.filetype_attachment)
.avatarClickListener(
DebouncedClickListener(View.OnClickListener { view ->
callback?.onAvatarClicked(informationData)
}))
.memberClickListener(
DebouncedClickListener(View.OnClickListener { view ->
callback?.onMemberNameClicked(informationData)
}))
.cellClickListener(
DebouncedClickListener(View.OnClickListener { view ->
callback?.onEventCellClicked(informationData, messageContent, view)
@ -223,17 +209,10 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
return MessageImageVideoItem_()
.playable(messageContent.info?.mimeType == "image/gif")
.informationData(informationData)
.avatarCallback(callback)
.mediaData(data)
.reactionPillCallback(callback)
.emojiTypeFace(emojiCompatFontProvider.typeface)
.avatarClickListener(
DebouncedClickListener(View.OnClickListener { view ->
callback?.onAvatarClicked(informationData)
}))
.memberClickListener(
DebouncedClickListener(View.OnClickListener { view ->
callback?.onMemberNameClicked(informationData)
}))
.clickListener(
DebouncedClickListener(View.OnClickListener { view ->
callback?.onImageMessageClicked(messageContent, data, view)
@ -271,17 +250,10 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
return MessageImageVideoItem_()
.playable(true)
.informationData(informationData)
.avatarCallback(callback)
.mediaData(thumbnailData)
.reactionPillCallback(callback)
.emojiTypeFace(emojiCompatFontProvider.typeface)
.avatarClickListener(
DebouncedClickListener(View.OnClickListener { view ->
callback?.onAvatarClicked(informationData)
}))
.memberClickListener(
DebouncedClickListener(View.OnClickListener { view ->
callback?.onMemberNameClicked(informationData)
}))
.cellClickListener(
DebouncedClickListener(View.OnClickListener { view ->
callback?.onEventCellClicked(informationData, messageContent, view)
@ -316,16 +288,9 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
}
}
.informationData(informationData)
.avatarCallback(callback)
.reactionPillCallback(callback)
.emojiTypeFace(emojiCompatFontProvider.typeface)
.avatarClickListener(
DebouncedClickListener(View.OnClickListener { view ->
callback?.onAvatarClicked(informationData)
}))
.memberClickListener(
DebouncedClickListener(View.OnClickListener { view ->
callback?.onMemberNameClicked(informationData)
}))
//click on the text
.clickListener(
DebouncedClickListener(View.OnClickListener { view ->
@ -390,12 +355,9 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
return MessageTextItem_()
.message(message)
.informationData(informationData)
.avatarCallback(callback)
.reactionPillCallback(callback)
.emojiTypeFace(emojiCompatFontProvider.typeface)
.avatarClickListener(
DebouncedClickListener(View.OnClickListener { view ->
callback?.onAvatarClicked(informationData)
}))
.memberClickListener(
DebouncedClickListener(View.OnClickListener { view ->
callback?.onMemberNameClicked(informationData)
@ -430,16 +392,9 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
}
}
.informationData(informationData)
.avatarCallback(callback)
.reactionPillCallback(callback)
.emojiTypeFace(emojiCompatFontProvider.typeface)
.avatarClickListener(
DebouncedClickListener(View.OnClickListener { view ->
callback?.onAvatarClicked(informationData)
}))
.memberClickListener(
DebouncedClickListener(View.OnClickListener { view ->
callback?.onMemberNameClicked(informationData)
}))
.cellClickListener(
DebouncedClickListener(View.OnClickListener { view ->
callback?.onEventCellClicked(informationData, messageContent, view)
@ -454,14 +409,7 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
callback: TimelineEventController.Callback?): RedactedMessageItem? {
return RedactedMessageItem_()
.informationData(informationData)
.avatarClickListener(
DebouncedClickListener(View.OnClickListener { view ->
callback?.onAvatarClicked(informationData)
}))
.memberClickListener(
DebouncedClickListener(View.OnClickListener { view ->
callback?.onMemberNameClicked(informationData)
}))
.avatarCallback(callback)
}

private fun linkifyBody(body: CharSequence, callback: TimelineEventController.Callback?): CharSequence {

View File

@ -29,6 +29,7 @@ import androidx.core.view.isGone
import androidx.core.view.isVisible
import com.airbnb.epoxy.EpoxyAttribute
import im.vector.riotredesign.R
import im.vector.riotredesign.core.utils.DebouncedClickListener
import im.vector.riotredesign.core.utils.DimensionUtils.dpToPx
import im.vector.riotredesign.features.home.AvatarRenderer
import im.vector.riotredesign.features.home.room.detail.timeline.TimelineEventController
@ -45,9 +46,6 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : BaseEventItem<H>() {
@EpoxyAttribute
var cellClickListener: View.OnClickListener? = null

@EpoxyAttribute
var avatarClickListener: View.OnClickListener? = null

@EpoxyAttribute
var memberClickListener: View.OnClickListener? = null

@ -57,6 +55,17 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : BaseEventItem<H>() {
@EpoxyAttribute
var reactionPillCallback: TimelineEventController.ReactionPillCallback? = null

@EpoxyAttribute
var avatarCallback: TimelineEventController.AvatarCallback?= null

private val _avatarClickListener = DebouncedClickListener(View.OnClickListener {
avatarCallback?.onAvatarClicked(informationData)
})
private val _memberNameClickListener = DebouncedClickListener(View.OnClickListener {
avatarCallback?.onMemberNameClicked(informationData)
})


var reactionClickListener: ReactionButton.ReactedListener = object : ReactionButton.ReactedListener {
override fun onReacted(reactionButton: ReactionButton) {
reactionPillCallback?.onClickOnReactionPill(informationData, reactionButton.reactionString, true)
@ -81,9 +90,9 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : BaseEventItem<H>() {
width = size
}
holder.avatarImageView.visibility = View.VISIBLE
holder.avatarImageView.setOnClickListener(avatarClickListener)
holder.avatarImageView.setOnClickListener(_avatarClickListener)
holder.memberNameView.visibility = View.VISIBLE
holder.memberNameView.setOnClickListener(memberClickListener)
holder.memberNameView.setOnClickListener(_memberNameClickListener)
holder.timeView.visibility = View.VISIBLE
holder.timeView.text = informationData.time
holder.memberNameView.text = informationData.memberName

View File

@ -11,8 +11,10 @@

<TextView
android:id="@+id/itemSimpleReactionInfoKey"
android:layout_width="44dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:gravity="center"
android:lines="1"
android:textColor="?android:textColorPrimary"