feat: set comment name color above WCAG Guidelines

This commit is contained in:
rebelonion 2024-02-23 18:13:00 -06:00
parent 70c87b4067
commit 7ba117ec25
3 changed files with 108 additions and 18 deletions

View file

@ -27,12 +27,14 @@ import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
import java.util.TimeZone import java.util.TimeZone
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.pow
import kotlin.math.sqrt import kotlin.math.sqrt
class CommentItem(val comment: Comment, class CommentItem(val comment: Comment,
private val markwon: Markwon, private val markwon: Markwon,
private val section: Section, private val section: Section,
private val commentsActivity: CommentsActivity, private val commentsActivity: CommentsActivity,
private val backgroundColor: Int
) : BindableItem<ItemCommentsBinding>() { ) : BindableItem<ItemCommentsBinding>() {
var binding: ItemCommentsBinding? = null var binding: ItemCommentsBinding? = null
val adapter = GroupieAdapter() val adapter = GroupieAdapter()
@ -162,7 +164,7 @@ class CommentItem(val comment: Comment,
viewBinding.commentUserAvatar viewBinding.commentUserAvatar
comment.profilePictureUrl?.let { viewBinding.commentUserAvatar.loadImage(it) } comment.profilePictureUrl?.let { viewBinding.commentUserAvatar.loadImage(it) }
viewBinding.commentUserName.text = comment.username viewBinding.commentUserName.text = comment.username
viewBinding.commentUserName.setTextColor(getAvatarColor(comment.upvotes - comment.downvotes)) viewBinding.commentUserName.setTextColor(getAvatarColor(comment.upvotes - comment.downvotes, backgroundColor))
viewBinding.commentUserTime.text = "${formatTimestamp(comment.timestamp)}" viewBinding.commentUserTime.text = "${formatTimestamp(comment.timestamp)}"
} }
@ -236,16 +238,69 @@ class CommentItem(val comment: Comment,
} }
} }
private fun getAvatarColor(voteCount: Int): Int { private fun getLuminance(color: Int): Double {
//0.8x^{2} where x is the level val r = Color.red(color) / 255.0
val level = sqrt(abs(voteCount.toDouble()) / 0.8).toInt() val g = Color.green(color) / 255.0
return if (level > usernameColors.size - 1) { val b = Color.blue(color) / 255.0
Color.parseColor(usernameColors[usernameColors.size - 1])
} else { val rL = if (r <= 0.03928) r / 12.92 else ((r + 0.055) / 1.055).pow(2.4)
Color.parseColor(usernameColors[level]) val gL = if (g <= 0.03928) g / 12.92 else ((g + 0.055) / 1.055).pow(2.4)
} val bL = if (b <= 0.03928) b / 12.92 else ((b + 0.055) / 1.055).pow(2.4)
return 0.2126 * rL + 0.7152 * gL + 0.0722 * bL
} }
private fun getContrastRatio(color1: Int, color2: Int): Double {
val l1 = getLuminance(color1)
val l2 = getLuminance(color2)
return if (l1 > l2) (l1 + 0.05) / (l2 + 0.05) else (l2 + 0.05) / (l1 + 0.05)
}
private fun getAvatarColor(voteCount: Int, backgroundColor: Int): Int {
val level = sqrt(abs(voteCount.toDouble()) / 0.8).toInt()
val colorString = if (level > usernameColors.size - 1) usernameColors[usernameColors.size - 1] else usernameColors[level]
var color = Color.parseColor(colorString)
val ratio = getContrastRatio(color, backgroundColor)
if (ratio < 4.5) {
color = adjustColorForContrast(color, backgroundColor)
}
return color
}
private fun adjustColorForContrast(originalColor: Int, backgroundColor: Int): Int {
var adjustedColor = originalColor
var contrastRatio = getContrastRatio(adjustedColor, backgroundColor)
val isBackgroundDark = getLuminance(backgroundColor) < 0.5
while (contrastRatio < 4.5) {
// Adjust brightness by modifying the RGB values
val r = Color.red(adjustedColor)
val g = Color.green(adjustedColor)
val b = Color.blue(adjustedColor)
// Calculate the amount to adjust
val adjustment = if (isBackgroundDark) 10 else -10
// Adjust the color
val newR = (r + adjustment).coerceIn(0, 255)
val newG = (g + adjustment).coerceIn(0, 255)
val newB = (b + adjustment).coerceIn(0, 255)
adjustedColor = Color.rgb(newR, newG, newB)
contrastRatio = getContrastRatio(adjustedColor, backgroundColor)
// Break the loop if the color adjustment does not change (to avoid infinite loop)
if (newR == r && newG == g && newB == b) {
break
}
}
return adjustedColor
}
private val usernameColors: Array<String> = arrayOf( private val usernameColors: Array<String> = arrayOf(
"#9932cc", "#9932cc",
"#a020f0", "#a020f0",

View file

@ -1,5 +1,6 @@
package ani.dantotsu.media.comments package ani.dantotsu.media.comments
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.os.Bundle import android.os.Bundle
import android.text.TextWatcher import android.text.TextWatcher
@ -55,6 +56,7 @@ class CommentsActivity : AppCompatActivity() {
private val section = Section() private val section = Section()
private val adapter = GroupieAdapter() private val adapter = GroupieAdapter()
private var mediaId: Int = -1 private var mediaId: Int = -1
private var backgroundColor: Int = 0
var pagesLoaded = 1 var pagesLoaded = 1
var totalPages = 1 var totalPages = 1
@ -71,6 +73,7 @@ class CommentsActivity : AppCompatActivity() {
finish() finish()
} }
this.mediaId = mediaId this.mediaId = mediaId
backgroundColor = (binding.root.background as? ColorDrawable)?.color ?: 0
val markwon = buildMarkwon() val markwon = buildMarkwon()
@ -129,10 +132,15 @@ class CommentsActivity : AppCompatActivity() {
popup.show() popup.show()
} }
var isFetching = false var isFetching = false
//if we have scrolled to the bottom of the list, load more comments //if we have scrolled to the bottom of the list, load more comments
binding.commentsList.addOnScrollListener(object : androidx.recyclerview.widget.RecyclerView.OnScrollListener() { binding.commentsList.addOnScrollListener(object :
override fun onScrolled(recyclerView: androidx.recyclerview.widget.RecyclerView, dx: Int, dy: Int) { androidx.recyclerview.widget.RecyclerView.OnScrollListener() {
override fun onScrolled(
recyclerView: androidx.recyclerview.widget.RecyclerView,
dx: Int,
dy: Int
) {
super.onScrolled(recyclerView, dx, dy) super.onScrolled(recyclerView, dx, dy)
if (shouldLoadMoreComments(recyclerView)) { if (shouldLoadMoreComments(recyclerView)) {
loadMoreComments() loadMoreComments()
@ -164,7 +172,15 @@ class CommentsActivity : AppCompatActivity() {
private suspend fun updateUIWithComment(comment: Comment) { private suspend fun updateUIWithComment(comment: Comment) {
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
section.add(CommentItem(comment, buildMarkwon(), section, this@CommentsActivity)) section.add(
CommentItem(
comment,
buildMarkwon(),
section,
this@CommentsActivity,
backgroundColor
)
)
} }
} }
}) })
@ -215,7 +231,15 @@ class CommentsActivity : AppCompatActivity() {
val sortedComments = sortComments(comments?.comments) val sortedComments = sortComments(comments?.comments)
sortedComments.forEach { sortedComments.forEach {
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
section.add(CommentItem(it, buildMarkwon(), section, this@CommentsActivity)) section.add(
CommentItem(
it,
buildMarkwon(),
section,
this@CommentsActivity,
backgroundColor
)
)
} }
} }
@ -309,7 +333,9 @@ class CommentsActivity : AppCompatActivity() {
it, it,
buildMarkwon(), buildMarkwon(),
comment.repliesSection, comment.repliesSection,
this@CommentsActivity) this@CommentsActivity,
backgroundColor
)
) )
} }
} }
@ -366,7 +392,9 @@ class CommentsActivity : AppCompatActivity() {
private suspend fun handleEditComment(commentText: String) { private suspend fun handleEditComment(commentText: String) {
val success = withContext(Dispatchers.IO) { val success = withContext(Dispatchers.IO) {
CommentsAPI.editComment(commentWithInteraction?.comment?.commentId ?: return@withContext false, commentText) CommentsAPI.editComment(
commentWithInteraction?.comment?.commentId ?: return@withContext false, commentText
)
} }
if (success) { if (success) {
updateCommentInSection(commentText) updateCommentInSection(commentText)
@ -403,12 +431,18 @@ class CommentsActivity : AppCompatActivity() {
if (interactionState == InteractionState.REPLY) { if (interactionState == InteractionState.REPLY) {
commentWithInteraction?.repliesSection?.add( commentWithInteraction?.repliesSection?.add(
0, 0,
CommentItem(it, buildMarkwon(), commentWithInteraction!!.repliesSection, this@CommentsActivity) CommentItem(
it,
buildMarkwon(),
commentWithInteraction!!.repliesSection,
this@CommentsActivity,
backgroundColor
)
) )
} else { } else {
section.add( section.add(
0, 0,
CommentItem(it, buildMarkwon(), section, this@CommentsActivity) CommentItem(it, buildMarkwon(), section, this@CommentsActivity, backgroundColor)
) )
} }
} }

View file

@ -5,6 +5,7 @@
android:id="@+id/commentsLayout" android:id="@+id/commentsLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?android:colorBackground"
android:fitsSystemWindows="true"> android:fitsSystemWindows="true">
<LinearLayout <LinearLayout