feat: Implement dynamic icon and text colors based on background luminance for improved accessibility

This commit is contained in:
k1ngsterr1
2026-01-25 19:00:35 +05:00
parent ff900846d1
commit 89746c5bbd
4 changed files with 33 additions and 15 deletions

View File

@@ -898,7 +898,7 @@ fun ChatDetailScreen(
contentDescription =
"Call",
tint =
Color.White
if (isDarkTheme) Color.White else Color(0xFF007AFF)
)
}
}
@@ -931,7 +931,7 @@ fun ChatDetailScreen(
contentDescription =
"More",
tint =
Color.White,
if (isDarkTheme) Color.White else Color(0xFF007AFF),
modifier =
Modifier.size(
26.dp

View File

@@ -94,6 +94,15 @@ data class AvatarColors(val textColor: Color, val backgroundColor: Color)
private val avatarColorCache = mutableMapOf<String, AvatarColors>()
/**
* Определяет, является ли цвет светлым (true) или темным (false)
* Использует формулу relative luminance из WCAG
*/
fun isColorLight(color: Color): Boolean {
val luminance = 0.299f * color.red + 0.587f * color.green + 0.114f * color.blue
return luminance > 0.5f
}
fun getAvatarColor(name: String, isDarkTheme: Boolean): AvatarColors {
val cacheKey = "${name}_${if (isDarkTheme) "dark" else "light"}"
return avatarColorCache.getOrPut(cacheKey) {
@@ -453,7 +462,7 @@ fun ChatsListScreen(
text = accountName,
fontSize = 16.sp,
fontWeight = FontWeight.SemiBold,
color = Color.White
color = if (isColorLight(headerColor)) Color.Black else Color.White
)
}
@@ -465,11 +474,7 @@ fun ChatsListScreen(
"@$accountUsername",
fontSize = 13.sp,
color =
Color.White
.copy(
alpha =
0.7f
)
if (isColorLight(headerColor)) Color.Black.copy(alpha = 0.7f) else Color.White.copy(alpha = 0.7f)
)
}
}

View File

@@ -248,7 +248,7 @@ private fun CollapsingOtherProfileHeader(
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = "Back",
tint = Color.White,
tint = if (isColorLight(avatarColors.backgroundColor)) Color.Black else Color.White,
modifier = Modifier.size(24.dp)
)
}
@@ -272,7 +272,7 @@ private fun CollapsingOtherProfileHeader(
Icon(
imageVector = Icons.Default.MoreVert,
contentDescription = "Profile menu",
tint = Color.White,
tint = if (isColorLight(avatarColors.backgroundColor)) Color.Black else Color.White,
modifier = Modifier.size(24.dp)
)
}
@@ -347,7 +347,7 @@ private fun CollapsingOtherProfileHeader(
text = name,
fontSize = nameFontSize,
fontWeight = FontWeight.SemiBold,
color = Color.White,
color = if (isColorLight(avatarColors.backgroundColor)) Color.Black else Color.White,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
textAlign = TextAlign.Center
@@ -368,7 +368,11 @@ private fun CollapsingOtherProfileHeader(
Text(
text = if (isOnline) "online" else "offline",
fontSize = onlineFontSize,
color = if (isOnline) Color(0xFF4CAF50) else Color.White.copy(alpha = 0.6f)
color = if (isOnline) {
Color(0xFF4CAF50)
} else {
if (isColorLight(avatarColors.backgroundColor)) Color.Black.copy(alpha = 0.6f) else Color.White.copy(alpha = 0.6f)
}
)
}
}

View File

@@ -102,6 +102,15 @@ data class AvatarColors(val textColor: Color, val backgroundColor: Color)
private val avatarColorCache = mutableMapOf<String, AvatarColors>()
/**
* Определяет, является ли цвет светлым (true) или темным (false)
* Использует формулу relative luminance из WCAG
*/
fun isColorLight(color: Color): Boolean {
val luminance = 0.299f * color.red + 0.587f * color.green + 0.114f * color.blue
return luminance > 0.5f
}
fun getAvatarColor(name: String, isDarkTheme: Boolean): AvatarColors {
val cacheKey = "${name}_${if (isDarkTheme) "dark" else "light"}"
return avatarColorCache.getOrPut(cacheKey) {
@@ -697,7 +706,7 @@ private fun CollapsingProfileHeader(
Icon(
imageVector = TablerIcons.ArrowLeft,
contentDescription = "Back",
tint = Color.White,
tint = if (isColorLight(avatarColors.backgroundColor)) Color.Black else Color.White,
modifier = Modifier.size(24.dp)
)
}
@@ -721,7 +730,7 @@ private fun CollapsingProfileHeader(
Icon(
imageVector = TablerIcons.DotsVertical,
contentDescription = "Profile menu",
tint = Color.White,
tint = if (isColorLight(avatarColors.backgroundColor)) Color.Black else Color.White,
modifier = Modifier.size(24.dp)
)
}
@@ -805,7 +814,7 @@ private fun CollapsingProfileHeader(
text = name,
fontSize = nameFontSize,
fontWeight = FontWeight.SemiBold,
color = Color.White,
color = if (isColorLight(avatarColors.backgroundColor)) Color.Black else Color.White,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.widthIn(max = 220.dp),