Skip to content
Merged
Prev Previous commit
Next Next commit
Merge branch 'main' into rz/feat/session-replay-custom-redaction
  • Loading branch information
romtsn committed Sep 12, 2024
commit 5727f286a5cb63e44945d8a068b5d694e554eaf3
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,15 @@ internal val TextView.totalPaddingTopSafe: Int
extendedPaddingTop
}

internal val TextView.dominantTextColor: Int get() {
if (text !is Spanned) return currentTextColor
/**
* Returns the dominant text color of the layout by looking at the [ForegroundColorSpan] spans if
* this text is a [Spanned] text. If the text is not a [Spanned] text or there are no spans, it
* returns null.
*/
internal val Layout?.dominantTextColor: Int? get() {
this ?: return null

if (text !is Spanned) return null

val spans = (text as Spanned).getSpans(0, text.length, ForegroundColorSpan::class.java)

Expand All @@ -125,5 +132,5 @@ internal val TextView.dominantTextColor: Int get() {
dominantColor = span.foregroundColor
}
}
return dominantColor ?: currentTextColor
return dominantColor
}
Original file line number Diff line number Diff line change
@@ -1,52 +1,104 @@
package io.sentry.android.replay.util

import android.app.Activity
import android.graphics.Color
import android.os.Bundle
import android.os.Looper
import android.text.SpannableString
import android.text.Spanned
import android.text.style.ForegroundColorSpan
import android.widget.LinearLayout
import android.widget.LinearLayout.LayoutParams
import android.widget.TextView
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.sentry.SentryOptions
import io.sentry.android.replay.viewhierarchy.ViewHierarchyNode
import io.sentry.android.replay.viewhierarchy.ViewHierarchyNode.TextViewHierarchyNode
import org.junit.runner.RunWith
import org.robolectric.Robolectric.buildActivity
import org.robolectric.Shadows.shadowOf
import org.robolectric.annotation.Config
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNull
import kotlin.test.assertTrue

@RunWith(AndroidJUnit4::class)
@Config(sdk = [30])
class TextViewDominantColorTest {

@Test
fun `when no spans, returns currentTextColor`() {
val textView = TextView(ApplicationProvider.getApplicationContext())
textView.text = "Hello, World!"
textView.setTextColor(Color.WHITE)
val controller = buildActivity(TextViewActivity::class.java, null).setup()
controller.create().start().resume()

assertEquals(Color.WHITE, textView.dominantTextColor)
TextViewActivity.textView?.setTextColor(Color.WHITE)

val node = ViewHierarchyNode.fromView(TextViewActivity.textView!!, null, 0, SentryOptions())
assertTrue(node is TextViewHierarchyNode)
assertNull(node.layout.dominantTextColor)
}

@Test
fun `when has a foreground color span, returns its color`() {
val textView = TextView(ApplicationProvider.getApplicationContext())
val controller = buildActivity(TextViewActivity::class.java, null).setup()
controller.create().start().resume()

val text = "Hello, World!"
textView.text = SpannableString(text).apply {
TextViewActivity.textView?.text = SpannableString(text).apply {
setSpan(ForegroundColorSpan(Color.RED), 0, text.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
}
textView.setTextColor(Color.WHITE)
TextViewActivity.textView?.setTextColor(Color.WHITE)
TextViewActivity.textView?.requestLayout()

assertEquals(Color.RED, textView.dominantTextColor)
shadowOf(Looper.getMainLooper()).idle()

val node = ViewHierarchyNode.fromView(TextViewActivity.textView!!, null, 0, SentryOptions())
assertTrue(node is TextViewHierarchyNode)
assertEquals(Color.RED, node.layout.dominantTextColor)
}

@Test
fun `when has multiple foreground color spans, returns color of the longest span`() {
val textView = TextView(ApplicationProvider.getApplicationContext())
val controller = buildActivity(TextViewActivity::class.java, null).setup()
controller.create().start().resume()

val text = "Hello, World!"
textView.text = SpannableString(text).apply {
TextViewActivity.textView?.text = SpannableString(text).apply {
setSpan(ForegroundColorSpan(Color.RED), 0, 5, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
setSpan(ForegroundColorSpan(Color.BLACK), 6, text.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
}
textView.setTextColor(Color.WHITE)
TextViewActivity.textView?.setTextColor(Color.WHITE)
TextViewActivity.textView?.requestLayout()

shadowOf(Looper.getMainLooper()).idle()

val node = ViewHierarchyNode.fromView(TextViewActivity.textView!!, null, 0, SentryOptions())
assertTrue(node is TextViewHierarchyNode)
assertEquals(Color.BLACK, node.layout.dominantTextColor)
}
}

private class TextViewActivity : Activity() {

companion object {
var textView: TextView? = null
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val linearLayout = LinearLayout(this).apply {
setBackgroundColor(android.R.color.white)
orientation = LinearLayout.VERTICAL
layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
}

textView = TextView(this).apply {
text = "Hello, World!"
layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
}
linearLayout.addView(textView)

assertEquals(Color.BLACK, textView.dominantTextColor)
setContentView(linearLayout)
}
}
You are viewing a condensed version of this merge commit. You can view the full changes here.