feat(feed): 피드 크기 계산 계약을 추가한다

This commit is contained in:
2026-05-21 15:53:40 +09:00
parent 3444b1eeef
commit a5728bcc4d
5 changed files with 148 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
package kr.co.vividnext.sodalive.v2.widget.feed
data class FeedContentImageSize(
val widthDp: Int,
val heightDp: Int
) {
companion object {
fun from(widthDp: Int, category: FeedContentCategory): FeedContentImageSize {
require(widthDp > 0) { "widthDp must be greater than 0." }
val height = (widthDp * category.ratioHeight.toFloat() / category.ratioWidth).toInt()
return FeedContentImageSize(widthDp = widthDp, heightDp = height)
}
}
}

View File

@@ -0,0 +1,27 @@
package kr.co.vividnext.sodalive.v2.widget.feed
data class FeedSize(
val rootWidthDp: Int
) {
companion object {
private const val FIGMA_ROOT_WIDTH_DP = 374
fun from(
variant: FeedVariant,
widthMode: FeedWidthMode,
parentAvailableWidthDp: Int,
horizontalItemDecorationDp: Int = 0
): FeedSize {
val width = when (widthMode) {
FeedWidthMode.FigmaFixed -> FIGMA_ROOT_WIDTH_DP
FeedWidthMode.ParentAvailable -> {
require(parentAvailableWidthDp > 0) { "parentAvailableWidthDp must be greater than 0." }
require(horizontalItemDecorationDp >= 0) { "horizontalItemDecorationDp must be 0 or greater." }
parentAvailableWidthDp - horizontalItemDecorationDp
}
}
require(width > 0) { "rootWidthDp must be greater than 0." }
return FeedSize(rootWidthDp = width)
}
}
}

View File

@@ -0,0 +1,6 @@
package kr.co.vividnext.sodalive.v2.widget.feed
enum class FeedWidthMode {
FigmaFixed,
ParentAvailable
}

View File

@@ -0,0 +1,40 @@
package kr.co.vividnext.sodalive.v2.widget.feed
import org.junit.Assert.assertEquals
import kr.co.vividnext.sodalive.R
import org.junit.Test
class FeedContentImageSizeTest {
@Test
fun `content category keeps one to one ratio`() {
val size = FeedContentImageSize.from(widthDp = 163, category = FeedContentCategory.Content)
assertEquals(163, size.widthDp)
assertEquals(163, size.heightDp)
assertEquals(R.string.feed_content_category_content, FeedContentCategory.Content.labelResId)
}
@Test
fun `series category keeps configured width and uses 163 by 230 ratio`() {
val size = FeedContentImageSize.from(widthDp = 163, category = FeedContentCategory.Series)
assertEquals(163, size.widthDp)
assertEquals(230, size.heightDp)
assertEquals(R.string.feed_content_category_series, FeedContentCategory.Series.labelResId)
}
@Test
fun `magazine category keeps configured width and uses 163 by 218 ratio`() {
val size = FeedContentImageSize.from(widthDp = 163, category = FeedContentCategory.Magazine)
assertEquals(163, size.widthDp)
assertEquals(218, size.heightDp)
assertEquals(R.string.feed_content_category_magazine, FeedContentCategory.Magazine.labelResId)
}
@Test(expected = IllegalArgumentException::class)
fun `image width must be positive`() {
FeedContentImageSize.from(widthDp = 0, category = FeedContentCategory.Content)
}
}

View File

@@ -0,0 +1,61 @@
package kr.co.vividnext.sodalive.v2.widget.feed
import org.junit.Assert.assertEquals
import org.junit.Test
class FeedSizeTest {
@Test
fun `horizontal scroll uses figma width`() {
val size = FeedSize.from(
variant = FeedVariant.Rank,
widthMode = FeedWidthMode.FigmaFixed,
parentAvailableWidthDp = 320
)
assertEquals(374, size.rootWidthDp)
}
@Test
fun `multi item row uses figma width`() {
val size = FeedSize.from(
variant = FeedVariant.Content,
widthMode = FeedWidthMode.FigmaFixed,
parentAvailableWidthDp = 720
)
assertEquals(374, size.rootWidthDp)
}
@Test
fun `single item row uses parent available width`() {
val size = FeedSize.from(
variant = FeedVariant.Live,
widthMode = FeedWidthMode.ParentAvailable,
parentAvailableWidthDp = 328
)
assertEquals(328, size.rootWidthDp)
}
@Test
fun `single item row subtracts horizontal item decoration from parent available width`() {
val size = FeedSize.from(
variant = FeedVariant.Live,
widthMode = FeedWidthMode.ParentAvailable,
parentAvailableWidthDp = 328,
horizontalItemDecorationDp = 24
)
assertEquals(304, size.rootWidthDp)
}
@Test(expected = IllegalArgumentException::class)
fun `parent available width must be positive for parent available mode`() {
FeedSize.from(
variant = FeedVariant.Community,
widthMode = FeedWidthMode.ParentAvailable,
parentAvailableWidthDp = 0
)
}
}