diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/util/UserStateJsonExtensions.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/util/UserStateJsonExtensions.kt index 29e6521b7e..5a921fa487 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/util/UserStateJsonExtensions.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/util/UserStateJsonExtensions.kt @@ -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, ) diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/base/util/StringExtensions.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/base/util/StringExtensions.kt index 532ea019e9..201dac9b7d 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/base/util/StringExtensions.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/base/util/StringExtensions.kt @@ -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" +} diff --git a/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/util/UserStateJsonExtensionsTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/util/UserStateJsonExtensionsTest.kt index 170cf3ec4f..23b39a5fa4 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/util/UserStateJsonExtensionsTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/util/UserStateJsonExtensionsTest.kt @@ -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(), diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/base/util/StringExtensionsTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/base/util/StringExtensionsTest.kt index 9777cffa4f..1dc2984371 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/base/util/StringExtensionsTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/base/util/StringExtensionsTest.kt @@ -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(), + ) + } + } }