Timeline: map on background thread
This commit is contained in:
parent
074da752ec
commit
754d266325
2 changed files with 79 additions and 52 deletions
|
|
@ -0,0 +1,67 @@
|
|||
package io.element.android.x.features.messages
|
||||
|
||||
import io.element.android.x.features.messages.model.MessagesItemGroupPosition
|
||||
import io.element.android.x.features.messages.model.MessagesTimelineItemState
|
||||
import io.element.android.x.matrix.core.UserId
|
||||
import io.element.android.x.matrix.room.MatrixRoom
|
||||
import io.element.android.x.matrix.timeline.MatrixTimelineItem
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.rustcomponents.sdk.MessageType
|
||||
|
||||
class MessageTimelineItemStateMapper(
|
||||
private val myUserId: UserId,
|
||||
private val room: MatrixRoom,
|
||||
private val dispatcher: CoroutineDispatcher,
|
||||
) {
|
||||
|
||||
suspend fun map(timelineItems: List<MatrixTimelineItem>): List<MessagesTimelineItemState> =
|
||||
withContext(dispatcher) {
|
||||
val messagesTimelineItemState = ArrayList<MessagesTimelineItemState>()
|
||||
for (index in timelineItems.indices.reversed()) {
|
||||
val currentTimelineItem = timelineItems[index]
|
||||
val timelineItemState = when (currentTimelineItem) {
|
||||
is MatrixTimelineItem.Event -> {
|
||||
val prevTimelineItem =
|
||||
timelineItems.getOrNull(index - 1) as? MatrixTimelineItem.Event
|
||||
val nextTimelineItem =
|
||||
timelineItems.getOrNull(index + 1) as? MatrixTimelineItem.Event
|
||||
val currentSender = currentTimelineItem.event.sender()
|
||||
val previousSender = prevTimelineItem?.event?.sender()
|
||||
val nextSender = nextTimelineItem?.event?.sender()
|
||||
|
||||
val groupPosition = when {
|
||||
previousSender != currentSender && nextSender == currentSender -> MessagesItemGroupPosition.First
|
||||
previousSender == currentSender && nextSender == currentSender -> MessagesItemGroupPosition.Middle
|
||||
previousSender == currentSender && nextSender != currentSender -> MessagesItemGroupPosition.Last
|
||||
else -> MessagesItemGroupPosition.None
|
||||
}
|
||||
val messageType =
|
||||
currentTimelineItem.event.content().asMessage()?.msgtype()
|
||||
val contentStr = when (messageType) {
|
||||
is MessageType.Emote -> messageType.content.body
|
||||
is MessageType.Image -> messageType.content.body
|
||||
is MessageType.Notice -> messageType.content.body
|
||||
is MessageType.Text -> messageType.content.body
|
||||
null -> null
|
||||
}
|
||||
MessagesTimelineItemState.MessageEvent(
|
||||
id = currentTimelineItem.event.eventId() ?: "",
|
||||
sender = currentTimelineItem.event.sender(),
|
||||
content = contentStr,
|
||||
isMine = currentTimelineItem.event.isOwn(),
|
||||
groupPosition = groupPosition
|
||||
)
|
||||
}
|
||||
is MatrixTimelineItem.Virtual -> MessagesTimelineItemState.Virtual(
|
||||
"virtual_item_$index"
|
||||
)
|
||||
MatrixTimelineItem.Other -> continue
|
||||
}
|
||||
messagesTimelineItemState.add(timelineItemState)
|
||||
}
|
||||
messagesTimelineItemState
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -5,19 +5,16 @@ import com.airbnb.mvrx.MavericksViewModelFactory
|
|||
import com.airbnb.mvrx.ViewModelContext
|
||||
import io.element.android.x.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.x.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.x.features.messages.model.MessagesItemGroupPosition
|
||||
import io.element.android.x.features.messages.model.MessagesTimelineItemState
|
||||
import io.element.android.x.features.messages.model.MessagesViewState
|
||||
import io.element.android.x.matrix.MatrixClient
|
||||
import io.element.android.x.matrix.MatrixInstance
|
||||
import io.element.android.x.matrix.room.MatrixRoom
|
||||
import io.element.android.x.matrix.timeline.MatrixTimeline
|
||||
import io.element.android.x.matrix.timeline.MatrixTimelineItem
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.rustcomponents.sdk.MessageType
|
||||
import org.matrix.rustcomponents.sdk.mediaSourceFromUrl
|
||||
|
||||
private const val PAGINATION_COUNT = 50
|
||||
|
|
@ -26,6 +23,7 @@ class MessagesViewModel(
|
|||
private val client: MatrixClient,
|
||||
private val room: MatrixRoom,
|
||||
private val timeline: MatrixTimeline,
|
||||
private val messageTimelineItemStateMapper: MessageTimelineItemStateMapper,
|
||||
private val initialState: MessagesViewState
|
||||
) :
|
||||
MavericksViewModel<MessagesViewState>(initialState) {
|
||||
|
|
@ -39,7 +37,15 @@ class MessagesViewModel(
|
|||
val matrix = MatrixInstance.getInstance()
|
||||
val client = matrix.activeClient()
|
||||
val room = client.getRoom(state.roomId) ?: return null
|
||||
return MessagesViewModel(client, room, room.timeline(), state)
|
||||
val messageTimelineItemStateMapper =
|
||||
MessageTimelineItemStateMapper(client.userId(), room, Dispatchers.Default)
|
||||
return MessagesViewModel(
|
||||
client,
|
||||
room,
|
||||
room.timeline(),
|
||||
messageTimelineItemStateMapper,
|
||||
state
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -67,53 +73,7 @@ class MessagesViewModel(
|
|||
}.launchIn(viewModelScope)
|
||||
|
||||
timeline.timelineItems()
|
||||
.map { timelineItems ->
|
||||
val messagesTimelineItemState = ArrayList<MessagesTimelineItemState>()
|
||||
for (index in timelineItems.indices.reversed()) {
|
||||
val currentTimelineItem = timelineItems[index]
|
||||
val timelineItemState = when (currentTimelineItem) {
|
||||
is MatrixTimelineItem.Event -> {
|
||||
val prevTimelineItem =
|
||||
timelineItems.getOrNull(index - 1) as? MatrixTimelineItem.Event
|
||||
val nextTimelineItem =
|
||||
timelineItems.getOrNull(index + 1) as? MatrixTimelineItem.Event
|
||||
val currentSender = currentTimelineItem.event.sender()
|
||||
val previousSender = prevTimelineItem?.event?.sender()
|
||||
val nextSender = nextTimelineItem?.event?.sender()
|
||||
|
||||
val groupPosition = when {
|
||||
previousSender != currentSender && nextSender == currentSender -> MessagesItemGroupPosition.First
|
||||
previousSender == currentSender && nextSender == currentSender -> MessagesItemGroupPosition.Middle
|
||||
previousSender == currentSender && nextSender != currentSender -> MessagesItemGroupPosition.Last
|
||||
else -> MessagesItemGroupPosition.None
|
||||
}
|
||||
val messageType =
|
||||
currentTimelineItem.event.content().asMessage()?.msgtype()
|
||||
val contentStr = when (messageType) {
|
||||
is MessageType.Emote -> messageType.content.body
|
||||
is MessageType.Image -> messageType.content.body
|
||||
is MessageType.Notice -> messageType.content.body
|
||||
is MessageType.Text -> messageType.content.body
|
||||
null -> null
|
||||
}
|
||||
|
||||
MessagesTimelineItemState.MessageEvent(
|
||||
id = currentTimelineItem.event.eventId() ?: "",
|
||||
sender = currentTimelineItem.event.sender(),
|
||||
content = contentStr,
|
||||
isMine = currentTimelineItem.event.sender() == client.userId().value,
|
||||
groupPosition = groupPosition
|
||||
)
|
||||
}
|
||||
is MatrixTimelineItem.Virtual -> MessagesTimelineItemState.Virtual(
|
||||
"virtual_item_$index"
|
||||
)
|
||||
MatrixTimelineItem.Other -> continue
|
||||
}
|
||||
messagesTimelineItemState.add(timelineItemState)
|
||||
}
|
||||
messagesTimelineItemState
|
||||
}
|
||||
.map(messageTimelineItemStateMapper::map)
|
||||
.execute {
|
||||
copy(timelineItems = it)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue