feat(feed): 랭킹 강조 텍스트 계약을 추가한다
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.widget.feed
|
||||||
|
|
||||||
|
data class FeedRankHighlight(
|
||||||
|
val start: Int,
|
||||||
|
val endExclusive: Int
|
||||||
|
) {
|
||||||
|
fun coerceIn(text: CharSequence): FeedRankHighlight? {
|
||||||
|
if (text.isEmpty()) return null
|
||||||
|
val safeStart = start.coerceIn(0, text.length)
|
||||||
|
val safeEnd = endExclusive.coerceIn(0, text.length)
|
||||||
|
return if (safeStart < safeEnd) FeedRankHighlight(safeStart, safeEnd) else null
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.widget.feed
|
||||||
|
|
||||||
|
import android.text.SpannableString
|
||||||
|
import android.text.Spanned
|
||||||
|
import android.text.style.ForegroundColorSpan
|
||||||
|
|
||||||
|
object FeedRankTextStyler {
|
||||||
|
fun style(
|
||||||
|
text: String,
|
||||||
|
highlightRanges: List<FeedRankHighlight>,
|
||||||
|
highlightColor: Int
|
||||||
|
): SpannableString {
|
||||||
|
val spannable = SpannableString(text)
|
||||||
|
highlightRanges.mapNotNull { it.coerceIn(text) }.forEach { range ->
|
||||||
|
spannable.setSpan(
|
||||||
|
ForegroundColorSpan(highlightColor),
|
||||||
|
range.start,
|
||||||
|
range.endExclusive,
|
||||||
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return spannable
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.widget.feed
|
||||||
|
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Assert.assertNull
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class FeedRankHighlightTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `valid range remains unchanged`() {
|
||||||
|
val range = FeedRankHighlight(start = 3, endExclusive = 6).coerceIn("abc12위def")
|
||||||
|
|
||||||
|
assertEquals(3, range?.start)
|
||||||
|
assertEquals(6, range?.endExclusive)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `range larger than text is clamped`() {
|
||||||
|
val range = FeedRankHighlight(start = 2, endExclusive = 99).coerceIn("abc12위")
|
||||||
|
|
||||||
|
assertEquals(2, range?.start)
|
||||||
|
assertEquals(6, range?.endExclusive)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `empty range is ignored`() {
|
||||||
|
val range = FeedRankHighlight(start = 4, endExclusive = 4).coerceIn("abc12위")
|
||||||
|
|
||||||
|
assertNull(range)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `range starting after text is ignored`() {
|
||||||
|
val range = FeedRankHighlight(start = 99, endExclusive = 100).coerceIn("abc12위")
|
||||||
|
|
||||||
|
assertNull(range)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.widget.feed
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.text.Spanned
|
||||||
|
import android.text.style.ForegroundColorSpan
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.robolectric.RobolectricTestRunner
|
||||||
|
import org.robolectric.annotation.Config
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner::class)
|
||||||
|
@Config(sdk = [28], application = Application::class)
|
||||||
|
class FeedRankTextStylerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `applies highlight color only to rank range`() {
|
||||||
|
val text = "크리에이터님이 12위를 차지하였어요!"
|
||||||
|
val styled = FeedRankTextStyler.style(
|
||||||
|
text = text,
|
||||||
|
highlightRanges = listOf(FeedRankHighlight(start = 8, endExclusive = 11)),
|
||||||
|
highlightColor = Color.CYAN
|
||||||
|
)
|
||||||
|
|
||||||
|
val spans = styled.getSpans(0, styled.length, ForegroundColorSpan::class.java)
|
||||||
|
|
||||||
|
assertEquals(1, spans.size)
|
||||||
|
assertEquals(Color.CYAN, spans[0].foregroundColor)
|
||||||
|
assertEquals(8, styled.getSpanStart(spans[0]))
|
||||||
|
assertEquals(11, styled.getSpanEnd(spans[0]))
|
||||||
|
assertEquals(Spanned.SPAN_EXCLUSIVE_EXCLUSIVE, styled.getSpanFlags(spans[0]))
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user