RoomList: avoid recomposition on avatar and add placeholder

This commit is contained in:
ganfra 2022-11-03 10:58:53 +01:00
parent 30665b2594
commit eb2fd13518
9 changed files with 145 additions and 54 deletions

View file

@ -4,3 +4,6 @@ import androidx.compose.ui.graphics.Color
val LightGrey = Color(0x993C3C43)
val DarkGrey = Color(0x99EBEBF5)
val AvatarGradientStart = Color(0xFF4CA1AF)
val AvatarGradientEnd = Color(0xFFC4E0E5)

View file

@ -1,31 +0,0 @@
import android.util.Log
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
/**
* TODO fallback Avatar
*/
@Composable
fun Avatar(
data: ByteArray?,
size: Dp = 48.dp,
) {
AsyncImage(
model = data,
onError = {
Log.e("TAG", "Error $it\n${it.result}", it.result.throwable)
},
contentDescription = null,
modifier = Modifier
.size(size)
.clip(CircleShape)
)
}

View file

@ -0,0 +1,68 @@
import android.util.Log
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil.compose.AsyncImage
import io.element.android.x.designsystem.AvatarGradientEnd
import io.element.android.x.designsystem.AvatarGradientStart
import io.element.android.x.designsystem.components.avatar.AvatarData
@Composable
fun Avatar(avatarData: AvatarData) {
if (avatarData.model == null) {
InitialsAvatar(
modifier = Modifier
.size(avatarData.size.dp)
.clip(CircleShape),
initials = avatarData.initials
)
} else {
AsyncImage(
model = avatarData.model,
onError = {
Log.e("TAG", "Error $it\n${it.result}", it.result.throwable)
},
contentDescription = null,
modifier = Modifier
.size(avatarData.size.dp)
.clip(CircleShape)
)
}
}
@Composable
private fun InitialsAvatar(
initials: String,
modifier: Modifier = Modifier,
) {
val initialsGradient = Brush.linearGradient(
listOf(
AvatarGradientStart,
AvatarGradientEnd,
)
)
Box(
modifier
.background(brush = initialsGradient)
) {
Text(
modifier = Modifier
.align(Alignment.Center),
text = initials,
fontSize = 24.sp,
color = Color.White,
)
}
}

View file

@ -0,0 +1,34 @@
package io.element.android.x.designsystem.components.avatar
import androidx.compose.runtime.Stable
@Stable
data class AvatarData(
val initials: String = "",
val model: ByteArray? = null,
val size: Int = 0
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as AvatarData
if (initials != other.initials) return false
if (model != null) {
if (other.model == null) return false
if (!model.contentEquals(other.model)) return false
} else if (other.model != null) return false
if (size != other.size) return false
return true
}
override fun hashCode(): Int {
var result = initials.hashCode()
result = 31 * result + (model?.contentHashCode() ?: 0)
result = 31 * result + size
return result
}
}