Implement a in-memory cache for user avatar colors.

This commit is contained in:
Benoit Marty
2023-09-08 13:51:46 +02:00
committed by Benoit Marty
parent 06a607abf8
commit 5a85efc458
5 changed files with 42 additions and 23 deletions

View File

@@ -43,7 +43,7 @@ import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMo
import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule
import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
import io.element.android.libraries.designsystem.colors.AvatarColors
import io.element.android.libraries.designsystem.colors.avatarColors
import io.element.android.libraries.designsystem.colors.AvatarColorsProvider
import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
@@ -119,21 +119,21 @@ private fun NotificationsOptInContent(
) {
NotificationRow(
avatarLetter = "M",
avatarColors = avatarColors("5"),
avatarColors = AvatarColorsProvider.provide("5", ElementTheme.isLightTheme),
firstRowPercent = 1f,
secondRowPercent = 0.4f
)
NotificationRow(
avatarLetter = "A",
avatarColors = avatarColors("1"),
avatarColors = AvatarColorsProvider.provide("1", ElementTheme.isLightTheme),
firstRowPercent = 1f,
secondRowPercent = 1f
)
NotificationRow(
avatarLetter = "T",
avatarColors = avatarColors("4"),
avatarColors = AvatarColorsProvider.provide("4", ElementTheme.isLightTheme),
firstRowPercent = 0.65f,
secondRowPercent = 0f
)

View File

@@ -75,7 +75,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent
import io.element.android.libraries.designsystem.colors.avatarColors
import io.element.android.libraries.designsystem.colors.AvatarColorsProvider
import io.element.android.libraries.designsystem.components.EqualWidthColumn
import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.avatar.AvatarData
@@ -328,7 +328,7 @@ private fun MessageSenderInformation(
) {
val avatarStrokeColor = MaterialTheme.colorScheme.background
val avatarSize = senderAvatar.size.dp
val avatarColors = avatarColors(senderAvatar.id)
val avatarColors = AvatarColorsProvider.provide(senderAvatar.id, ElementTheme.isLightTheme)
Box(
modifier = modifier
) {

View File

@@ -16,9 +16,8 @@
package io.element.android.libraries.designsystem.colors
import androidx.compose.runtime.Composable
import androidx.collection.LruCache
import androidx.compose.ui.graphics.Color
import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.theme.colors.avatarColorsDark
import io.element.android.libraries.theme.colors.avatarColorsLight
@@ -27,18 +26,37 @@ data class AvatarColors(
val foreground: Color,
)
@Composable
fun avatarColors(userId: String): AvatarColors {
val hash = userId.toHash()
val colors = if (ElementTheme.isLightTheme) {
avatarColorsLight[hash]
} else {
avatarColorsDark[hash]
object AvatarColorsProvider {
private val cache = LruCache<String, AvatarColors>(200)
private var currentThemeIsLight = true
fun provide(id: String, isLightTheme: Boolean): AvatarColors {
if (currentThemeIsLight != isLightTheme) {
currentThemeIsLight = isLightTheme
cache.evictAll()
}
val valueFromCache = cache.get(id)
return if (valueFromCache != null) {
valueFromCache
} else {
val colors = avatarColors(id, isLightTheme)
cache.put(id, colors)
colors
}
}
private fun avatarColors(id: String, isLightTheme: Boolean): AvatarColors {
val hash = id.toHash()
val colors = if (isLightTheme) {
avatarColorsLight[hash]
} else {
avatarColorsDark[hash]
}
return AvatarColors(
background = colors.first,
foreground = colors.second,
)
}
return AvatarColors(
background = colors.first,
foreground = colors.second,
)
}
internal fun String.toHash(): Int {

View File

@@ -33,7 +33,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil.compose.AsyncImage
import io.element.android.libraries.designsystem.colors.AvatarColors
import io.element.android.libraries.designsystem.colors.avatarColors
import io.element.android.libraries.designsystem.colors.AvatarColorsProvider
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
import io.element.android.libraries.designsystem.preview.PreviewGroup
import io.element.android.libraries.designsystem.preview.debugPlaceholderAvatar
@@ -53,7 +53,7 @@ fun Avatar(
.size(avatarData.size.dp)
.clip(CircleShape)
if (avatarData.url.isNullOrBlank()) {
val avatarColors = initialAvatarColors ?: avatarColors(avatarData.id)
val avatarColors = initialAvatarColors ?: AvatarColorsProvider.provide(avatarData.id, ElementTheme.isLightTheme)
InitialsAvatar(
avatarData = avatarData,
avatarColors = avatarColors,

View File

@@ -24,10 +24,11 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.colors.avatarColors
import io.element.android.libraries.designsystem.colors.AvatarColorsProvider
import io.element.android.libraries.designsystem.preview.DayNightPreviews
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.theme.colors.avatarColorsLight
@DayNightPreviews
@@ -43,7 +44,7 @@ internal fun UserAvatarPreview() = ElementPreview {
verticalAlignment = Alignment.CenterVertically,
) {
// Note: it's OK, since the hash of "0" is 0, the hash of "1" is 1, etc.
Avatar(anAvatarData(), initialAvatarColors = avatarColors("$it"))
Avatar(anAvatarData(), initialAvatarColors = AvatarColorsProvider.provide("$it", ElementTheme.isLightTheme))
Text(text = "Color index $it")
}
}