BIT-1191: Calculate avatar color when absent (#280)

This commit is contained in:
Brian Yencho 2023-11-27 15:10:54 -06:00 committed by Álison Fernandes
parent 912d6b62fe
commit 5864f5376d
4 changed files with 50 additions and 4 deletions

View file

@ -4,6 +4,7 @@ import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
import com.x8bit.bitwarden.data.vault.repository.model.VaultState
import com.x8bit.bitwarden.ui.platform.base.util.toHexColorRepresentation
/**
* Updates the given [UserStateJson] with the data from the [syncResponse] to return a new
@ -51,8 +52,8 @@ fun UserStateJson.toUserState(
userId = accountJson.profile.userId,
name = accountJson.profile.name,
email = accountJson.profile.email,
// TODO Calculate default color (BIT-1191)
avatarColorHex = accountJson.profile.avatarColorHex ?: "#00aaaa",
avatarColorHex = accountJson.profile.avatarColorHex
?: accountJson.profile.userId.toHexColorRepresentation(),
isPremium = accountJson.profile.hasPremium == true,
isVaultUnlocked = userId in vaultState.unlockedVaultUserIds,
)

View file

@ -54,3 +54,28 @@ fun String.hexToColor(): Color = if (startsWith("#")) {
} else {
Color("#$this".toColorInt())
}
/**
* Creates a new [String] that represents a unique color in the hex representation (`"#AARRGGBB"`).
* This can be applied to any [String] in order to provide some deterministic color value based on
* arbitrary [String] properties.
*/
@OptIn(ExperimentalStdlibApi::class)
@Suppress("MagicNumber")
fun String.toHexColorRepresentation(): String {
// Produces a string with exactly two hexadecimal digits.
// Ex:
// 0 -> "00"
// 10 -> "0a"
// 1000 -> "e8"
fun Int.toTwoDigitHexString(): String =
this.toHexString().takeLast(2)
// Calculates separate red, blue, and green values from different positions in the hash and then
// combines then into a single color.
val hash = this.hashCode()
val red = (hash and 0x0000FF).toTwoDigitHexString()
val green = ((hash and 0x00FF00) shr 8).toTwoDigitHexString()
val blue = ((hash and 0xFF0000) shr 16).toTwoDigitHexString()
return "#ff$red$green$blue"
}

View file

@ -135,7 +135,8 @@ class UserStateJsonExtensionsTest {
userId = "activeUserId",
name = "activeName",
email = "activeEmail",
avatarColorHex = "activeAvatarColorHex",
// This value is calculated from the userId
avatarColorHex = "#ffecbc49",
isPremium = true,
isVaultUnlocked = false,
),
@ -149,7 +150,7 @@ class UserStateJsonExtensionsTest {
every { userId } returns "activeUserId"
every { name } returns "activeName"
every { email } returns "activeEmail"
every { avatarColorHex } returns "activeAvatarColorHex"
every { avatarColorHex } returns null
every { hasPremium } returns true
},
tokens = mockk(),

View file

@ -1,5 +1,6 @@
package com.x8bit.bitwarden.ui.platform.base.util
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
@ -67,4 +68,22 @@ class StringExtensionsTest {
assertFalse(badUri.isValidUri())
}
}
@Test
fun `toHexColorRepresentation should return valid hex color values`() {
mapOf(
"First" to "#ff90e20b",
"Second" to "#ff943060",
"Multiple words" to "#ffb9d46a",
"1234567890-=!@#$%^&*()_+[]\\;',./{}|:\"<>?" to "#ff171178",
"" to "#ff000000",
" " to "#ff200000",
)
.forEach { (input, colorHexOutput) ->
assertEquals(
colorHexOutput,
input.toHexColorRepresentation(),
)
}
}
}