RoomList: avoid recomposition on avatar and add placeholder
This commit is contained in:
@@ -28,6 +28,7 @@ import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.compose.collectAsState
|
||||
import com.airbnb.mvrx.compose.mavericksViewModel
|
||||
import io.element.android.x.core.data.LogCompositions
|
||||
import io.element.android.x.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.x.features.roomlist.model.MatrixUser
|
||||
import io.element.android.x.features.roomlist.model.RoomListRoomSummary
|
||||
import io.element.android.x.features.roomlist.model.RoomListViewState
|
||||
@@ -49,7 +50,7 @@ fun RoomListScreen(
|
||||
val matrixUser by viewModel.collectAsState(RoomListViewState::user)
|
||||
RoomListContent(
|
||||
roomSummaries = roomSummaries().orEmpty(),
|
||||
matrixUser = matrixUser,
|
||||
matrixUser = matrixUser(),
|
||||
onRoomClicked = onRoomClicked,
|
||||
onLogoutClicked = viewModel::logout
|
||||
)
|
||||
@@ -58,7 +59,7 @@ fun RoomListScreen(
|
||||
@Composable
|
||||
fun RoomListContent(
|
||||
roomSummaries: List<RoomListRoomSummary>,
|
||||
matrixUser: MatrixUser,
|
||||
matrixUser: MatrixUser?,
|
||||
onRoomClicked: (RoomId) -> Unit,
|
||||
onLogoutClicked: () -> Unit,
|
||||
) {
|
||||
@@ -84,15 +85,16 @@ fun RoomListContent(
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun RoomListTopBar(matrixUser: MatrixUser, onLogoutClicked: () -> Unit) {
|
||||
fun RoomListTopBar(matrixUser: MatrixUser?, onLogoutClicked: () -> Unit) {
|
||||
LogCompositions(tag = "RoomListScreen", msg = "TopBar")
|
||||
if (matrixUser == null) return
|
||||
TopAppBar(
|
||||
title = {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Avatar(data = matrixUser.avatarData, size = 32.dp)
|
||||
Avatar(matrixUser.avatarData)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text("${matrixUser.username}")
|
||||
}
|
||||
@@ -131,7 +133,7 @@ private fun RoomItem(
|
||||
.padding(horizontal = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Avatar(data = room.avatarData)
|
||||
Avatar(room.avatarData)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(12.dp)
|
||||
@@ -182,13 +184,13 @@ private fun PreviewableRoomListContent() {
|
||||
hasUnread = true,
|
||||
timestamp = "14:18",
|
||||
lastMessage = "A message",
|
||||
avatarData = null,
|
||||
avatarData = AvatarData("R"),
|
||||
id = "roomId"
|
||||
)
|
||||
)
|
||||
RoomListContent(
|
||||
roomSummaries = roomSummaries,
|
||||
matrixUser = MatrixUser("User#1"),
|
||||
matrixUser = MatrixUser("User#1", avatarData = AvatarData("U")),
|
||||
onRoomClicked = {},
|
||||
onLogoutClicked = {}
|
||||
)
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.MavericksViewModel
|
||||
import com.airbnb.mvrx.Success
|
||||
import io.element.android.x.core.data.parallelMap
|
||||
import io.element.android.x.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.x.features.roomlist.model.MatrixUser
|
||||
import io.element.android.x.features.roomlist.model.RoomListRoomSummary
|
||||
import io.element.android.x.features.roomlist.model.RoomListViewState
|
||||
@@ -41,17 +42,18 @@ class RoomListViewModel(initialState: RoomListViewState) :
|
||||
viewModelScope.launch {
|
||||
val client = getClient()
|
||||
client.startSync()
|
||||
val userAvatarUrl = client.loadUserAvatarURLString().getOrNull()
|
||||
val userDisplayName = client.loadUserDisplayName().getOrNull()
|
||||
val avatarData = loadAvatarData(client, userAvatarUrl)
|
||||
setState {
|
||||
copy(
|
||||
user = MatrixUser(
|
||||
username = userDisplayName,
|
||||
avatarUrl = userAvatarUrl,
|
||||
avatarData = avatarData,
|
||||
)
|
||||
suspend {
|
||||
val userAvatarUrl = client.loadUserAvatarURLString().getOrNull()
|
||||
val userDisplayName = client.loadUserDisplayName().getOrNull()
|
||||
val avatarData =
|
||||
loadAvatarData(client, userDisplayName ?: client.userId().value, userAvatarUrl)
|
||||
MatrixUser(
|
||||
username = userDisplayName ?: client.userId().value,
|
||||
avatarUrl = userAvatarUrl,
|
||||
avatarData = avatarData,
|
||||
)
|
||||
}.execute {
|
||||
copy(user = it)
|
||||
}
|
||||
client.roomSummaryDataSource().roomSummaries()
|
||||
.map { roomSummaries ->
|
||||
@@ -75,7 +77,11 @@ class RoomListViewModel(initialState: RoomListViewState) :
|
||||
isPlaceholder = true
|
||||
)
|
||||
is RoomSummary.Filled -> {
|
||||
val avatarData = loadAvatarData(client, roomSummary.details.avatarURLString)
|
||||
val avatarData = loadAvatarData(
|
||||
client,
|
||||
roomSummary.details.name,
|
||||
roomSummary.details.avatarURLString
|
||||
)
|
||||
RoomListRoomSummary(
|
||||
id = roomSummary.identifier(),
|
||||
name = roomSummary.details.name,
|
||||
@@ -89,7 +95,12 @@ class RoomListViewModel(initialState: RoomListViewState) :
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun loadAvatarData(client: MatrixClient, url: String?, size: Long = 48): ByteArray? {
|
||||
private suspend fun loadAvatarData(
|
||||
client: MatrixClient,
|
||||
name: String,
|
||||
url: String?,
|
||||
size: Long = 48
|
||||
): AvatarData {
|
||||
val mediaContent = url?.let {
|
||||
val mediaSource = mediaSourceFromUrl(it)
|
||||
client.loadMediaThumbnailForSource(mediaSource, size, size)
|
||||
@@ -97,7 +108,9 @@ class RoomListViewModel(initialState: RoomListViewState) :
|
||||
return mediaContent?.fold(
|
||||
{ it },
|
||||
{ null }
|
||||
)
|
||||
).let { model ->
|
||||
AvatarData(name.first().toString(), model, size.toInt())
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleLogout() {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package io.element.android.x.features.roomlist.model
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import io.element.android.x.designsystem.components.avatar.AvatarData
|
||||
|
||||
@Stable
|
||||
data class MatrixUser(
|
||||
val username: String? = null,
|
||||
val avatarUrl: String? = null,
|
||||
val avatarData: ByteArray? = null,
|
||||
val avatarData: AvatarData = AvatarData(),
|
||||
)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.element.android.x.features.roomlist.model
|
||||
|
||||
import io.element.android.x.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.x.matrix.core.RoomId
|
||||
|
||||
data class RoomListRoomSummary(
|
||||
@@ -9,6 +10,6 @@ data class RoomListRoomSummary(
|
||||
val hasUnread: Boolean = false,
|
||||
val timestamp: String? = null,
|
||||
val lastMessage: CharSequence? = null,
|
||||
val avatarData: ByteArray? = null,
|
||||
val avatarData: AvatarData = AvatarData(),
|
||||
val isPlaceholder: Boolean = false,
|
||||
)
|
||||
@@ -7,7 +7,7 @@ import io.element.android.x.features.roomlist.model.MatrixUser
|
||||
import io.element.android.x.matrix.room.RoomSummary
|
||||
|
||||
data class RoomListViewState(
|
||||
val user: MatrixUser = MatrixUser(),
|
||||
val user: Async<MatrixUser> = Uninitialized,
|
||||
val rooms: Async<List<RoomListRoomSummary>> = Uninitialized,
|
||||
val canLoadMore: Boolean = false,
|
||||
val logoutAction: Async<Unit> = Uninitialized,
|
||||
|
||||
Reference in New Issue
Block a user