Create a MatrixItemHelper to avoid duplicated code.
This commit is contained in:
parent
50216fb296
commit
2d9a5b5a2a
5 changed files with 103 additions and 61 deletions
|
|
@ -34,6 +34,7 @@ dependencies {
|
||||||
implementation(project(":libraries:di"))
|
implementation(project(":libraries:di"))
|
||||||
implementation(project(":libraries:core"))
|
implementation(project(":libraries:core"))
|
||||||
implementation(project(":libraries:matrix"))
|
implementation(project(":libraries:matrix"))
|
||||||
|
implementation(project(":libraries:matrixui"))
|
||||||
implementation(project(":libraries:designsystem"))
|
implementation(project(":libraries:designsystem"))
|
||||||
implementation(project(":libraries:textcomposer"))
|
implementation(project(":libraries:textcomposer"))
|
||||||
implementation(libs.mavericks.compose)
|
implementation(libs.mavericks.compose)
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
package io.element.android.x.features.messages
|
package io.element.android.x.features.messages
|
||||||
|
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import io.element.android.x.designsystem.components.avatar.AvatarData
|
|
||||||
import io.element.android.x.designsystem.components.avatar.AvatarSize
|
import io.element.android.x.designsystem.components.avatar.AvatarSize
|
||||||
import io.element.android.x.features.messages.diff.CacheInvalidator
|
import io.element.android.x.features.messages.diff.CacheInvalidator
|
||||||
import io.element.android.x.features.messages.diff.MatrixTimelineItemsDiffCallback
|
import io.element.android.x.features.messages.diff.MatrixTimelineItemsDiffCallback
|
||||||
|
|
@ -34,11 +33,10 @@ import io.element.android.x.features.messages.model.content.MessagesTimelineItem
|
||||||
import io.element.android.x.features.messages.model.content.MessagesTimelineItemTextContent
|
import io.element.android.x.features.messages.model.content.MessagesTimelineItemTextContent
|
||||||
import io.element.android.x.features.messages.model.content.MessagesTimelineItemUnknownContent
|
import io.element.android.x.features.messages.model.content.MessagesTimelineItemUnknownContent
|
||||||
import io.element.android.x.features.messages.util.invalidateLast
|
import io.element.android.x.features.messages.util.invalidateLast
|
||||||
import io.element.android.x.matrix.MatrixClient
|
|
||||||
import io.element.android.x.matrix.media.MediaResolver
|
import io.element.android.x.matrix.media.MediaResolver
|
||||||
import io.element.android.x.matrix.room.MatrixRoom
|
import io.element.android.x.matrix.room.MatrixRoom
|
||||||
import io.element.android.x.matrix.timeline.MatrixTimelineItem
|
import io.element.android.x.matrix.timeline.MatrixTimelineItem
|
||||||
import kotlin.system.measureTimeMillis
|
import io.element.android.x.matrix.ui.MatrixItemHelper
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
@ -52,9 +50,10 @@ import org.matrix.rustcomponents.sdk.FormattedBody
|
||||||
import org.matrix.rustcomponents.sdk.MessageFormat
|
import org.matrix.rustcomponents.sdk.MessageFormat
|
||||||
import org.matrix.rustcomponents.sdk.MessageType
|
import org.matrix.rustcomponents.sdk.MessageType
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
class MessageTimelineItemStateFactory(
|
class MessageTimelineItemStateFactory(
|
||||||
private val client: MatrixClient,
|
private val matrixItemHelper: MatrixItemHelper,
|
||||||
private val room: MatrixRoom,
|
private val room: MatrixRoom,
|
||||||
private val dispatcher: CoroutineDispatcher,
|
private val dispatcher: CoroutineDispatcher,
|
||||||
) {
|
) {
|
||||||
|
|
@ -153,7 +152,11 @@ class MessageTimelineItemStateFactory(
|
||||||
val senderDisplayName = room.userDisplayName(currentSender).getOrNull()
|
val senderDisplayName = room.userDisplayName(currentSender).getOrNull()
|
||||||
val senderAvatarUrl = room.userAvatarUrl(currentSender).getOrNull()
|
val senderAvatarUrl = room.userAvatarUrl(currentSender).getOrNull()
|
||||||
val senderAvatarData =
|
val senderAvatarData =
|
||||||
loadAvatarData(senderDisplayName ?: currentSender, senderAvatarUrl)
|
matrixItemHelper.loadAvatarData(
|
||||||
|
name = senderDisplayName ?: currentSender,
|
||||||
|
url = senderAvatarUrl,
|
||||||
|
size = AvatarSize.SMALL
|
||||||
|
)
|
||||||
return MessagesTimelineItemState.MessageEvent(
|
return MessagesTimelineItemState.MessageEvent(
|
||||||
id = currentTimelineItem.uniqueId,
|
id = currentTimelineItem.uniqueId,
|
||||||
senderId = currentSender,
|
senderId = currentSender,
|
||||||
|
|
@ -243,14 +246,4 @@ class MessageTimelineItemStateFactory(
|
||||||
else -> MessagesItemGroupPosition.None
|
else -> MessagesItemGroupPosition.None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun loadAvatarData(
|
|
||||||
name: String,
|
|
||||||
url: String?,
|
|
||||||
size: AvatarSize = AvatarSize.SMALL
|
|
||||||
): AvatarData {
|
|
||||||
val model = client.mediaResolver()
|
|
||||||
.resolve(url, kind = MediaResolver.Kind.Thumbnail(size.value))
|
|
||||||
return AvatarData(name, model, size)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import io.element.android.x.anvilannotations.ContributesViewModel
|
import io.element.android.x.anvilannotations.ContributesViewModel
|
||||||
import io.element.android.x.core.di.daggerMavericksViewModelFactory
|
import io.element.android.x.core.di.daggerMavericksViewModelFactory
|
||||||
import io.element.android.x.designsystem.components.avatar.AvatarData
|
|
||||||
import io.element.android.x.designsystem.components.avatar.AvatarSize
|
import io.element.android.x.designsystem.components.avatar.AvatarSize
|
||||||
import io.element.android.x.di.SessionScope
|
import io.element.android.x.di.SessionScope
|
||||||
import io.element.android.x.features.messages.model.MessagesItemAction
|
import io.element.android.x.features.messages.model.MessagesItemAction
|
||||||
|
|
@ -33,9 +32,9 @@ import io.element.android.x.features.messages.model.MessagesViewState
|
||||||
import io.element.android.x.features.messages.model.content.MessagesTimelineItemRedactedContent
|
import io.element.android.x.features.messages.model.content.MessagesTimelineItemRedactedContent
|
||||||
import io.element.android.x.features.messages.model.content.MessagesTimelineItemTextBasedContent
|
import io.element.android.x.features.messages.model.content.MessagesTimelineItemTextBasedContent
|
||||||
import io.element.android.x.matrix.MatrixClient
|
import io.element.android.x.matrix.MatrixClient
|
||||||
import io.element.android.x.matrix.media.MediaResolver
|
|
||||||
import io.element.android.x.matrix.timeline.MatrixTimeline
|
import io.element.android.x.matrix.timeline.MatrixTimeline
|
||||||
import io.element.android.x.matrix.timeline.MatrixTimelineItem
|
import io.element.android.x.matrix.timeline.MatrixTimelineItem
|
||||||
|
import io.element.android.x.matrix.ui.MatrixItemHelper
|
||||||
import io.element.android.x.textcomposer.MessageComposerMode
|
import io.element.android.x.textcomposer.MessageComposerMode
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
|
@ -53,9 +52,10 @@ class MessagesViewModel @AssistedInject constructor(
|
||||||
|
|
||||||
companion object : MavericksViewModelFactory<MessagesViewModel, MessagesViewState> by daggerMavericksViewModelFactory()
|
companion object : MavericksViewModelFactory<MessagesViewModel, MessagesViewState> by daggerMavericksViewModelFactory()
|
||||||
|
|
||||||
|
private val matrixItemHelper = MatrixItemHelper(client)
|
||||||
private val room = client.getRoom(initialState.roomId)!!
|
private val room = client.getRoom(initialState.roomId)!!
|
||||||
private val messageTimelineItemStateFactory =
|
private val messageTimelineItemStateFactory =
|
||||||
MessageTimelineItemStateFactory(client, room, Dispatchers.Default)
|
MessageTimelineItemStateFactory(matrixItemHelper, room, Dispatchers.Default)
|
||||||
private val timeline = room.timeline()
|
private val timeline = room.timeline()
|
||||||
|
|
||||||
private val timelineCallback = object : MatrixTimeline.Callback {
|
private val timelineCallback = object : MatrixTimeline.Callback {
|
||||||
|
|
@ -161,7 +161,10 @@ class MessagesViewModel @AssistedInject constructor(
|
||||||
room.syncUpdateFlow()
|
room.syncUpdateFlow()
|
||||||
.onEach {
|
.onEach {
|
||||||
val avatarData =
|
val avatarData =
|
||||||
loadAvatarData(room.name ?: room.roomId.value, room.avatarUrl, AvatarSize.SMALL)
|
matrixItemHelper.loadAvatarData(
|
||||||
|
room = room,
|
||||||
|
size = AvatarSize.SMALL
|
||||||
|
)
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
roomName = room.name, roomAvatar = avatarData,
|
roomName = room.name, roomAvatar = avatarData,
|
||||||
|
|
@ -217,16 +220,6 @@ class MessagesViewModel @AssistedInject constructor(
|
||||||
setSnackbarContent("Not implemented yet!")
|
setSnackbarContent("Not implemented yet!")
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun loadAvatarData(
|
|
||||||
name: String,
|
|
||||||
url: String?,
|
|
||||||
size: AvatarSize = AvatarSize.MEDIUM
|
|
||||||
): AvatarData {
|
|
||||||
val model = client.mediaResolver()
|
|
||||||
.resolve(url, kind = MediaResolver.Kind.Thumbnail(size.value))
|
|
||||||
return AvatarData(name, model, size)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCleared() {
|
override fun onCleared() {
|
||||||
super.onCleared()
|
super.onCleared()
|
||||||
timeline.callback = null
|
timeline.callback = null
|
||||||
|
|
|
||||||
|
|
@ -25,16 +25,14 @@ import dagger.assisted.AssistedInject
|
||||||
import io.element.android.x.anvilannotations.ContributesViewModel
|
import io.element.android.x.anvilannotations.ContributesViewModel
|
||||||
import io.element.android.x.core.coroutine.parallelMap
|
import io.element.android.x.core.coroutine.parallelMap
|
||||||
import io.element.android.x.core.di.daggerMavericksViewModelFactory
|
import io.element.android.x.core.di.daggerMavericksViewModelFactory
|
||||||
import io.element.android.x.designsystem.components.avatar.AvatarData
|
|
||||||
import io.element.android.x.designsystem.components.avatar.AvatarSize
|
import io.element.android.x.designsystem.components.avatar.AvatarSize
|
||||||
import io.element.android.x.di.SessionScope
|
import io.element.android.x.di.SessionScope
|
||||||
import io.element.android.x.features.roomlist.model.RoomListRoomSummary
|
import io.element.android.x.features.roomlist.model.RoomListRoomSummary
|
||||||
import io.element.android.x.features.roomlist.model.RoomListRoomSummaryPlaceholders
|
import io.element.android.x.features.roomlist.model.RoomListRoomSummaryPlaceholders
|
||||||
import io.element.android.x.features.roomlist.model.RoomListViewState
|
import io.element.android.x.features.roomlist.model.RoomListViewState
|
||||||
import io.element.android.x.matrix.MatrixClient
|
import io.element.android.x.matrix.MatrixClient
|
||||||
import io.element.android.x.matrix.media.MediaResolver
|
|
||||||
import io.element.android.x.matrix.room.RoomSummary
|
import io.element.android.x.matrix.room.RoomSummary
|
||||||
import io.element.android.x.matrix.ui.model.MatrixUser
|
import io.element.android.x.matrix.ui.MatrixItemHelper
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
|
|
@ -53,6 +51,7 @@ class RoomListViewModel @AssistedInject constructor(
|
||||||
companion object : MavericksViewModelFactory<RoomListViewModel, RoomListViewState> by daggerMavericksViewModelFactory()
|
companion object : MavericksViewModelFactory<RoomListViewModel, RoomListViewState> by daggerMavericksViewModelFactory()
|
||||||
|
|
||||||
private val lastMessageFormatter = LastMessageFormatter()
|
private val lastMessageFormatter = LastMessageFormatter()
|
||||||
|
private val matrixUserHelper = MatrixItemHelper(client)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
handleInit()
|
handleInit()
|
||||||
|
|
@ -79,22 +78,7 @@ class RoomListViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleInit() {
|
private fun handleInit() {
|
||||||
suspend {
|
matrixUserHelper.getCurrentUserData(avatarSize = AvatarSize.SMALL).execute {
|
||||||
val userAvatarUrl = client.loadUserAvatarURLString().getOrNull()
|
|
||||||
val userDisplayName = client.loadUserDisplayName().getOrNull()
|
|
||||||
val avatarData =
|
|
||||||
loadAvatarData(
|
|
||||||
userDisplayName ?: client.userId().value,
|
|
||||||
userAvatarUrl,
|
|
||||||
AvatarSize.SMALL
|
|
||||||
)
|
|
||||||
MatrixUser(
|
|
||||||
id = client.userId(),
|
|
||||||
username = userDisplayName,
|
|
||||||
avatarUrl = userAvatarUrl,
|
|
||||||
avatarData = avatarData,
|
|
||||||
)
|
|
||||||
}.execute {
|
|
||||||
copy(user = it)
|
copy(user = it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -137,9 +121,9 @@ class RoomListViewModel @AssistedInject constructor(
|
||||||
when (roomSummary) {
|
when (roomSummary) {
|
||||||
is RoomSummary.Empty -> RoomListRoomSummaryPlaceholders.create(roomSummary.identifier)
|
is RoomSummary.Empty -> RoomListRoomSummaryPlaceholders.create(roomSummary.identifier)
|
||||||
is RoomSummary.Filled -> {
|
is RoomSummary.Filled -> {
|
||||||
val avatarData = loadAvatarData(
|
val avatarData = matrixUserHelper.loadAvatarData(
|
||||||
roomSummary.details.name,
|
roomSummary = roomSummary,
|
||||||
roomSummary.details.avatarURLString
|
size = AvatarSize.MEDIUM
|
||||||
)
|
)
|
||||||
RoomListRoomSummary(
|
RoomListRoomSummary(
|
||||||
id = roomSummary.identifier(),
|
id = roomSummary.identifier(),
|
||||||
|
|
@ -153,14 +137,4 @@ class RoomListViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun loadAvatarData(
|
|
||||||
name: String,
|
|
||||||
url: String?,
|
|
||||||
size: AvatarSize = AvatarSize.MEDIUM
|
|
||||||
): AvatarData {
|
|
||||||
val model = client.mediaResolver()
|
|
||||||
.resolve(url, kind = MediaResolver.Kind.Thumbnail(size.value))
|
|
||||||
return AvatarData(name, model, size)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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 io.element.android.x.matrix.ui
|
||||||
|
|
||||||
|
import io.element.android.x.designsystem.components.avatar.AvatarData
|
||||||
|
import io.element.android.x.designsystem.components.avatar.AvatarSize
|
||||||
|
import io.element.android.x.matrix.MatrixClient
|
||||||
|
import io.element.android.x.matrix.media.MediaResolver
|
||||||
|
import io.element.android.x.matrix.room.MatrixRoom
|
||||||
|
import io.element.android.x.matrix.room.RoomSummary
|
||||||
|
import io.element.android.x.matrix.ui.model.MatrixUser
|
||||||
|
import kotlinx.coroutines.FlowPreview
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.asFlow
|
||||||
|
|
||||||
|
class MatrixItemHelper(
|
||||||
|
private val client: MatrixClient
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* TODO Make username and avatar live...
|
||||||
|
*/
|
||||||
|
@OptIn(FlowPreview::class)
|
||||||
|
fun getCurrentUserData(avatarSize: AvatarSize): Flow<MatrixUser> {
|
||||||
|
return suspend {
|
||||||
|
val userAvatarUrl = client.loadUserAvatarURLString().getOrNull()
|
||||||
|
val userDisplayName = client.loadUserDisplayName().getOrNull()
|
||||||
|
val avatarData =
|
||||||
|
loadAvatarData(
|
||||||
|
userDisplayName ?: client.userId().value,
|
||||||
|
userAvatarUrl,
|
||||||
|
avatarSize
|
||||||
|
)
|
||||||
|
MatrixUser(
|
||||||
|
id = client.userId(),
|
||||||
|
username = userDisplayName,
|
||||||
|
avatarUrl = userAvatarUrl,
|
||||||
|
avatarData = avatarData,
|
||||||
|
)
|
||||||
|
}.asFlow()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun loadAvatarData(room: MatrixRoom, size: AvatarSize): AvatarData {
|
||||||
|
return loadAvatarData(
|
||||||
|
name = room.name ?: room.roomId.value,
|
||||||
|
url = room.avatarUrl,
|
||||||
|
size = size
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun loadAvatarData(roomSummary: RoomSummary.Filled, size: AvatarSize): AvatarData {
|
||||||
|
return loadAvatarData(
|
||||||
|
name = roomSummary.details.name,
|
||||||
|
url = roomSummary.details.avatarURLString,
|
||||||
|
size = size
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun loadAvatarData(
|
||||||
|
name: String,
|
||||||
|
url: String?,
|
||||||
|
size: AvatarSize
|
||||||
|
): AvatarData {
|
||||||
|
val model = client.mediaResolver()
|
||||||
|
.resolve(url, kind = MediaResolver.Kind.Thumbnail(size.value))
|
||||||
|
return AvatarData(name, model, size)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue