RoomList: avoid recomposition on avatar and add placeholder
This commit is contained in:
parent
30665b2594
commit
eb2fd13518
9 changed files with 145 additions and 54 deletions
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue