feat(creator): 채널 홈 소개 활동 SNS 섹션을 재구성한다

This commit is contained in:
2026-06-15 18:43:47 +09:00
parent 1f3abfde4f
commit 2d2844338a
5 changed files with 302 additions and 187 deletions

View File

@@ -157,15 +157,11 @@ class CreatorChannelHomeActivitySourceTest {
assertTrue(adapter.contains("bindFanTalk"))
assertTrue(adapter.contains("bindSns"))
assertTrue(adapter.contains("bindActivity"))
assertTrue(adapter.contains("ll_section_items"))
assertTrue(adapter.contains("sectionItems?.addView"))
assertTrue(adapter.contains("addActivityRow"))
assertFalse(adapter.contains("createContentTile"))
assertFalse(adapter.contains("addFeedCard"))
assertFalse(adapter.contains("addScheduleRow"))
assertFalse(adapter.contains("addDonationCard"))
assertFalse(adapter.contains("addCommentCard"))
assertTrue(adapter.contains("createSnsButton"))
assertTrue(adapter.contains("activity.debutDateUtc"))
assertTrue(adapter.contains("activity.liveDurationHours"))
assertTrue(adapter.contains("activity.liveContributorCount"))
@@ -179,6 +175,80 @@ class CreatorChannelHomeActivitySourceTest {
assertFalse(adapter.contains("fun CreatorChannelHomeSection.imageUrl"))
}
@Test
fun `소개 섹션은 카드 배경 없는 Figma 본문 텍스트로 렌더링한다`() {
val adapter = projectFile(
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt"
).readText()
val introduceLayout = projectFile("app/src/main/res/layout/item_creator_channel_home_introduce.xml").readText()
assertTrue(introduceLayout.contains("@layout/view_section_title"))
assertTrue(introduceLayout.contains("@+id/tv_introduce_body"))
assertTrue(introduceLayout.contains("android:layout_width=\"match_parent\""))
assertTrue(introduceLayout.contains("android:paddingHorizontal=\"@dimen/spacing_20\""))
assertFalse(introduceLayout.contains("android:layout_width=\"362dp\""))
assertTrue(introduceLayout.contains("android:textSize=\"16sp\""))
assertTrue(introduceLayout.contains("android:textColor=\"@color/white\""))
assertFalse(introduceLayout.contains("@+id/ll_section_items"))
assertFalse(introduceLayout.contains("bg_round_corner_16_7_222222"))
assertTrue(adapter.contains("private val introduceBody: TextView?"))
assertTrue(adapter.contains("introduceBody?.text = item.introduce"))
assertFalse(adapter.contains("private fun addTextCard"))
assertFalse(adapter.contains("addTextCard("))
}
@Test
fun `활동 섹션은 배경 카드 없는 label value row로 렌더링한다`() {
val adapter = projectFile(
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt"
).readText()
val activityLayout = projectFile("app/src/main/res/layout/item_creator_channel_home_activity.xml").readText()
assertTrue(activityLayout.contains("@layout/view_section_title"))
assertTrue(activityLayout.contains("android:layout_width=\"match_parent\""))
assertTrue(activityLayout.contains("android:paddingHorizontal=\"@dimen/spacing_20\""))
assertFalse(activityLayout.contains("android:layout_width=\"362dp\""))
assertTrue(activityLayout.contains("@+id/tv_activity_debut_value"))
assertTrue(activityLayout.contains("@+id/tv_activity_live_count_value"))
assertTrue(activityLayout.contains("@+id/tv_activity_live_duration_value"))
assertTrue(activityLayout.contains("@+id/tv_activity_live_contributor_value"))
assertTrue(activityLayout.contains("@+id/tv_activity_audio_count_value"))
assertTrue(activityLayout.contains("@+id/tv_activity_series_count_value"))
assertTrue(activityLayout.contains("@string/creator_channel_activity_debut"))
assertTrue(activityLayout.contains("@string/creator_channel_activity_live_count"))
assertFalse(activityLayout.contains("@+id/ll_section_items"))
assertFalse(activityLayout.contains("creator_channel_activity_photo"))
assertFalse(activityLayout.contains("bg_round_corner_16_7_222222"))
assertTrue(adapter.contains("private val activityDebutValue: TextView?"))
assertTrue(adapter.contains("activityDebutValue?.text = formatDebutActivityValue"))
assertTrue(adapter.contains("activitySeriesCountValue?.text = itemView.context.getString"))
assertFalse(adapter.contains("private fun addActivityRow"))
assertFalse(adapter.contains("addActivityRow("))
}
@Test
fun `SNS 섹션은 전용 layout 아이콘 row와 안전한 링크 실행을 유지한다`() {
val adapter = projectFile(
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt"
).readText()
val snsLayout = projectFile("app/src/main/res/layout/item_creator_channel_home_sns.xml").readText()
assertTrue(snsLayout.contains("@+id/tv_sns_title"))
assertTrue(snsLayout.contains("@string/creator_channel_section_sns"))
assertTrue(snsLayout.contains("android:textSize=\"18sp\""))
assertTrue(snsLayout.contains("@+id/ll_sns_items"))
assertTrue(snsLayout.contains("android:layout_width=\"match_parent\""))
assertTrue(snsLayout.contains("android:paddingHorizontal=\"@dimen/spacing_20\""))
assertFalse(snsLayout.contains("android:layout_width=\"362dp\""))
assertFalse(snsLayout.contains("@+id/ll_section_items"))
assertTrue(adapter.contains("private val snsItems: LinearLayout?"))
assertTrue(adapter.contains("snsItems?.removeAllViews()"))
assertTrue(adapter.contains("snsItems?.addView"))
assertTrue(adapter.contains("calculateCreatorChannelSnsButtonSizeDp"))
assertTrue(adapter.contains("button.contentDescription = sns.label"))
assertTrue(adapter.contains("resolveActivity(itemView.context.packageManager)"))
}
@Test
fun `현재 라이브 섹션은 전용 layout과 bind로 렌더링한다`() {
val adapter = projectFile(
@@ -391,8 +461,8 @@ class CreatorChannelHomeActivitySourceTest {
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt"
).readText()
assertTrue(adapter.contains("iconResId = sns.iconResId"))
assertTrue(adapter.contains("url = sns.url"))
assertTrue(adapter.contains("button.setImageResource(sns.iconResId)"))
assertTrue(adapter.contains("Intent(Intent.ACTION_VIEW, sns.url.toUri())"))
assertTrue(adapter.contains("schedule.type.labelResId"))
assertFalse(adapter.contains("schedule.type.code"))
}
@@ -772,8 +842,12 @@ class CreatorChannelHomeActivitySourceTest {
assertTrue(mapper.contains("R.drawable.ic_sns_x"))
assertTrue(mapper.contains("R.drawable.ic_sns_kakao"))
assertTrue(mapper.contains("R.drawable.ic_sns_fancimm"))
assertTrue(adapter.contains("private fun createSnsButton(iconResId: Int, url: String, isLast: Boolean): ImageView"))
assertTrue(adapter.contains("setImageResource(iconResId)"))
assertTrue(adapter.contains("R.layout.item_creator_channel_home_sns_icon"))
assertTrue(adapter.contains("button.setImageResource(sns.iconResId)"))
assertTrue(adapter.contains("button.contentDescription = sns.label"))
val snsIconLayout = projectFile("app/src/main/res/layout/item_creator_channel_home_sns_icon.xml").readText()
assertFalse(snsIconLayout.contains("android:layout_width=\"52dp\""))
assertFalse(snsIconLayout.contains("android:layout_height=\"52dp\""))
assertFalse(adapter.contains("createText(label, R.style.Typography_Caption2, R.color.white"))
}
@@ -800,8 +874,16 @@ class CreatorChannelHomeActivitySourceTest {
assertEquals(52, calculateCreatorChannelSnsButtonSizeDp(402))
assertEquals(52, calculateCreatorChannelSnsButtonSizeDp(430))
assertEquals(47, calculateCreatorChannelSnsButtonSizeDp(360))
assertEquals(51, calculateCreatorChannelSnsButtonSizeDp(360))
assertEquals(43, calculateCreatorChannelSnsButtonSizeDp(322))
assertEquals(43, calculateCreatorChannelSnsButtonSizeDp(320))
assertTrue(adapter.contains("calculateCreatorChannelSnsButtonSizeDp"))
assertTrue(adapter.contains("minOf("))
assertTrue(adapter.contains("SNS_MAX_ICON_SIZE_DP"))
assertTrue(adapter.contains("SNS_HORIZONTAL_PADDING_DP"))
assertTrue(adapter.contains("SNS_TOTAL_GAP_DP"))
assertTrue(adapter.contains("SNS_ICON_COUNT"))
assertFalse(adapter.contains("SNS_ICON_COUNT.toFloat()).roundToInt()"))
assertFalse(adapter.contains("LinearLayout.LayoutParams(52.dp(), 52.dp())"))
}
@@ -812,13 +894,12 @@ class CreatorChannelHomeActivitySourceTest {
).readText()
assertTrue(adapter.contains("item.items.forEachIndexed { index, sns ->"))
assertTrue(adapter.contains("isLast = index == item.items.lastIndex"))
assertTrue(adapter.contains("private fun createSnsButton(iconResId: Int, url: String, isLast: Boolean): ImageView"))
assertTrue(adapter.contains("marginEnd = if (isLast) 0 else 16.dp()"))
assertTrue(adapter.contains("buttonSize = calculateCreatorChannelSnsButtonSizeDp"))
assertTrue(adapter.contains("marginEnd = if (index == item.items.lastIndex) 0 else 16.dp()"))
}
@Test
fun `남은 section item layouts는 legacy generic card id를 제거하고 동적 컨테이너만 둔다`() {
fun `남은 section item layouts는 legacy generic card id를 제거다`() {
val layoutNames = listOf(
"introduce",
"activity",
@@ -827,7 +908,7 @@ class CreatorChannelHomeActivitySourceTest {
layoutNames.forEach { name ->
val layout = projectFile("app/src/main/res/layout/item_creator_channel_home_$name.xml").readText()
assertTrue(layout.contains("@+id/ll_section_items"))
assertFalse(layout.contains("@+id/ll_section_items"))
assertFalse(layout.contains("@+id/iv_thumbnail"))
assertFalse(layout.contains("@+id/tv_primary"))
assertFalse(layout.contains("@+id/tv_secondary"))