feat: set comment name color above WCAG Guidelines
This commit is contained in:
parent
70c87b4067
commit
7ba117ec25
3 changed files with 108 additions and 18 deletions
|
@ -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,15 +238,68 @@ 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 g = Color.green(color) / 255.0
|
||||||
|
val b = Color.blue(color) / 255.0
|
||||||
|
|
||||||
|
val rL = if (r <= 0.03928) r / 12.92 else ((r + 0.055) / 1.055).pow(2.4)
|
||||||
|
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 level = sqrt(abs(voteCount.toDouble()) / 0.8).toInt()
|
||||||
return if (level > usernameColors.size - 1) {
|
val colorString = if (level > usernameColors.size - 1) usernameColors[usernameColors.size - 1] else usernameColors[level]
|
||||||
Color.parseColor(usernameColors[usernameColors.size - 1])
|
var color = Color.parseColor(colorString)
|
||||||
} else {
|
val ratio = getContrastRatio(color, backgroundColor)
|
||||||
Color.parseColor(usernameColors[level])
|
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",
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
@ -131,8 +134,13 @@ class CommentsActivity : AppCompatActivity() {
|
||||||
|
|
||||||
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)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue