Implement a in-memory cache for user avatar colors.
This commit is contained in:
parent
06a607abf8
commit
5a85efc458
5 changed files with 42 additions and 23 deletions
|
|
@ -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.molecules.IconTitleSubtitleMolecule
|
||||||
import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
|
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.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.Avatar
|
||||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||||
|
|
@ -119,21 +119,21 @@ private fun NotificationsOptInContent(
|
||||||
) {
|
) {
|
||||||
NotificationRow(
|
NotificationRow(
|
||||||
avatarLetter = "M",
|
avatarLetter = "M",
|
||||||
avatarColors = avatarColors("5"),
|
avatarColors = AvatarColorsProvider.provide("5", ElementTheme.isLightTheme),
|
||||||
firstRowPercent = 1f,
|
firstRowPercent = 1f,
|
||||||
secondRowPercent = 0.4f
|
secondRowPercent = 0.4f
|
||||||
)
|
)
|
||||||
|
|
||||||
NotificationRow(
|
NotificationRow(
|
||||||
avatarLetter = "A",
|
avatarLetter = "A",
|
||||||
avatarColors = avatarColors("1"),
|
avatarColors = AvatarColorsProvider.provide("1", ElementTheme.isLightTheme),
|
||||||
firstRowPercent = 1f,
|
firstRowPercent = 1f,
|
||||||
secondRowPercent = 1f
|
secondRowPercent = 1f
|
||||||
)
|
)
|
||||||
|
|
||||||
NotificationRow(
|
NotificationRow(
|
||||||
avatarLetter = "T",
|
avatarLetter = "T",
|
||||||
avatarColors = avatarColors("4"),
|
avatarColors = AvatarColorsProvider.provide("4", ElementTheme.isLightTheme),
|
||||||
firstRowPercent = 0.65f,
|
firstRowPercent = 0.65f,
|
||||||
secondRowPercent = 0f
|
secondRowPercent = 0f
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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.aTimelineItemImageContent
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent
|
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.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.EqualWidthColumn
|
||||||
import io.element.android.libraries.designsystem.components.avatar.Avatar
|
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.AvatarData
|
||||||
|
|
@ -328,7 +328,7 @@ private fun MessageSenderInformation(
|
||||||
) {
|
) {
|
||||||
val avatarStrokeColor = MaterialTheme.colorScheme.background
|
val avatarStrokeColor = MaterialTheme.colorScheme.background
|
||||||
val avatarSize = senderAvatar.size.dp
|
val avatarSize = senderAvatar.size.dp
|
||||||
val avatarColors = avatarColors(senderAvatar.id)
|
val avatarColors = AvatarColorsProvider.provide(senderAvatar.id, ElementTheme.isLightTheme)
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
) {
|
) {
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,8 @@
|
||||||
|
|
||||||
package io.element.android.libraries.designsystem.colors
|
package io.element.android.libraries.designsystem.colors
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.collection.LruCache
|
||||||
import androidx.compose.ui.graphics.Color
|
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.avatarColorsDark
|
||||||
import io.element.android.libraries.theme.colors.avatarColorsLight
|
import io.element.android.libraries.theme.colors.avatarColorsLight
|
||||||
|
|
||||||
|
|
@ -27,18 +26,37 @@ data class AvatarColors(
|
||||||
val foreground: Color,
|
val foreground: Color,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Composable
|
object AvatarColorsProvider {
|
||||||
fun avatarColors(userId: String): AvatarColors {
|
private val cache = LruCache<String, AvatarColors>(200)
|
||||||
val hash = userId.toHash()
|
private var currentThemeIsLight = true
|
||||||
val colors = if (ElementTheme.isLightTheme) {
|
|
||||||
avatarColorsLight[hash]
|
fun provide(id: String, isLightTheme: Boolean): AvatarColors {
|
||||||
} else {
|
if (currentThemeIsLight != isLightTheme) {
|
||||||
avatarColorsDark[hash]
|
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 {
|
internal fun String.toHash(): Int {
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import coil.compose.AsyncImage
|
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.avatarColors
|
import io.element.android.libraries.designsystem.colors.AvatarColorsProvider
|
||||||
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
|
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
|
||||||
import io.element.android.libraries.designsystem.preview.PreviewGroup
|
import io.element.android.libraries.designsystem.preview.PreviewGroup
|
||||||
import io.element.android.libraries.designsystem.preview.debugPlaceholderAvatar
|
import io.element.android.libraries.designsystem.preview.debugPlaceholderAvatar
|
||||||
|
|
@ -53,7 +53,7 @@ fun Avatar(
|
||||||
.size(avatarData.size.dp)
|
.size(avatarData.size.dp)
|
||||||
.clip(CircleShape)
|
.clip(CircleShape)
|
||||||
if (avatarData.url.isNullOrBlank()) {
|
if (avatarData.url.isNullOrBlank()) {
|
||||||
val avatarColors = initialAvatarColors ?: avatarColors(avatarData.id)
|
val avatarColors = initialAvatarColors ?: AvatarColorsProvider.provide(avatarData.id, ElementTheme.isLightTheme)
|
||||||
InitialsAvatar(
|
InitialsAvatar(
|
||||||
avatarData = avatarData,
|
avatarData = avatarData,
|
||||||
avatarColors = avatarColors,
|
avatarColors = avatarColors,
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,11 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
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.DayNightPreviews
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||||
import io.element.android.libraries.designsystem.theme.components.Text
|
import io.element.android.libraries.designsystem.theme.components.Text
|
||||||
|
import io.element.android.libraries.theme.ElementTheme
|
||||||
import io.element.android.libraries.theme.colors.avatarColorsLight
|
import io.element.android.libraries.theme.colors.avatarColorsLight
|
||||||
|
|
||||||
@DayNightPreviews
|
@DayNightPreviews
|
||||||
|
|
@ -43,7 +44,7 @@ internal fun UserAvatarPreview() = ElementPreview {
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
// Note: it's OK, since the hash of "0" is 0, the hash of "1" is 1, etc.
|
// 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")
|
Text(text = "Color index $it")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue