fix(creator): 채널 홈 활동 표시를 보정한다
This commit is contained in:
@@ -11,139 +11,176 @@
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="@dimen/spacing_20"
|
||||
android:layout_marginTop="@dimen/spacing_14"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="@dimen/spacing_20">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/spacing_8"
|
||||
android:baselineAligned="false"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
style="@style/Typography.Body2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_8"
|
||||
android:layout_weight="1"
|
||||
android:letterSpacing="0"
|
||||
android:lineSpacingMultiplier="1.45"
|
||||
android:text="@string/creator_channel_activity_debut"
|
||||
android:textColor="@color/gray_500"
|
||||
android:textSize="16sp" />
|
||||
android:textColor="#939393" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_activity_debut_value"
|
||||
style="@style/Typography.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:letterSpacing="0"
|
||||
android:lineSpacingMultiplier="1.45"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp" />
|
||||
android:includeFontPadding="true" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/spacing_8"
|
||||
android:baselineAligned="false"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
style="@style/Typography.Body2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_8"
|
||||
android:layout_weight="1"
|
||||
android:letterSpacing="0"
|
||||
android:lineSpacingMultiplier="1.45"
|
||||
android:text="@string/creator_channel_activity_live_count"
|
||||
android:textColor="@color/gray_500"
|
||||
android:textSize="16sp" />
|
||||
android:textColor="#939393" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_activity_live_count_value"
|
||||
style="@style/Typography.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp" />
|
||||
android:letterSpacing="0"
|
||||
android:lineSpacingMultiplier="1.45"
|
||||
android:textColor="@color/white" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/spacing_8"
|
||||
android:baselineAligned="false"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
style="@style/Typography.Body2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_8"
|
||||
android:layout_weight="1"
|
||||
android:letterSpacing="0"
|
||||
android:lineSpacingMultiplier="1.45"
|
||||
android:text="@string/creator_channel_activity_live_duration"
|
||||
android:textColor="@color/gray_500"
|
||||
android:textSize="16sp" />
|
||||
android:textColor="#939393" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_activity_live_duration_value"
|
||||
style="@style/Typography.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp" />
|
||||
android:letterSpacing="0"
|
||||
android:lineSpacingMultiplier="1.45"
|
||||
android:textColor="@color/white" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/spacing_8"
|
||||
android:baselineAligned="false"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
style="@style/Typography.Body2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_8"
|
||||
android:layout_weight="1"
|
||||
android:letterSpacing="0"
|
||||
android:lineSpacingMultiplier="1.45"
|
||||
android:text="@string/creator_channel_activity_live_contributor"
|
||||
android:textColor="@color/gray_500"
|
||||
android:textSize="16sp" />
|
||||
android:textColor="#939393" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_activity_live_contributor_value"
|
||||
style="@style/Typography.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp" />
|
||||
android:letterSpacing="0"
|
||||
android:lineSpacingMultiplier="1.45"
|
||||
android:textColor="@color/white" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/spacing_8"
|
||||
android:baselineAligned="false"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
style="@style/Typography.Body2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_8"
|
||||
android:layout_weight="1"
|
||||
android:letterSpacing="0"
|
||||
android:lineSpacingMultiplier="1.45"
|
||||
android:text="@string/creator_channel_activity_audio_count"
|
||||
android:textColor="@color/gray_500"
|
||||
android:textSize="16sp" />
|
||||
android:textColor="#939393" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_activity_audio_count_value"
|
||||
style="@style/Typography.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp" />
|
||||
android:letterSpacing="0"
|
||||
android:lineSpacingMultiplier="1.45"
|
||||
android:textColor="@color/white" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:baselineAligned="false"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
style="@style/Typography.Body2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_8"
|
||||
android:layout_weight="1"
|
||||
android:letterSpacing="0"
|
||||
android:lineSpacingMultiplier="1.45"
|
||||
android:text="@string/creator_channel_activity_series_count"
|
||||
android:textColor="@color/gray_500"
|
||||
android:textSize="16sp" />
|
||||
android:textColor="#939393" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_activity_series_count_value"
|
||||
style="@style/Typography.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp" />
|
||||
android:letterSpacing="0"
|
||||
android:lineSpacingMultiplier="1.45"
|
||||
android:textColor="@color/white" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -10,6 +10,7 @@ import kr.co.vividnext.sodalive.v2.creator.channel.ui.calculateCreatorChannelFan
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.ui.calculateCreatorChannelSeriesCardHeightDp
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.ui.calculateCreatorChannelSeriesCardWidthDp
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.ui.calculateCreatorChannelScheduleTimelineLineCount
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.ui.formatCreatorChannelDebutActivityValue
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.ui.formatCreatorChannelScheduleDate
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.ui.formatCreatorChannelScheduleDayOfWeek
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.ui.formatCreatorChannelScheduleTime
|
||||
@@ -403,18 +404,20 @@ class CreatorChannelActivitySourceTest {
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt"
|
||||
).readText()
|
||||
|
||||
assertTrue(adapter.contains("creator_channel_activity_debut"))
|
||||
assertTrue(adapter.contains("creator_channel_activity_debut_format"))
|
||||
val activityLayout = projectFile("app/src/main/res/layout/item_creator_channel_home_activity.xml").readText()
|
||||
|
||||
assertTrue(activityLayout.contains("creator_channel_activity_debut"))
|
||||
assertTrue(adapter.contains("formatCreatorChannelDebutActivityValue"))
|
||||
assertTrue(adapter.contains("creator_channel_activity_live_count_format"))
|
||||
assertTrue(adapter.contains("creator_channel_activity_live_duration_format"))
|
||||
assertTrue(adapter.contains("creator_channel_activity_live_contributor_format"))
|
||||
assertTrue(adapter.contains("creator_channel_activity_audio_count_format"))
|
||||
assertTrue(adapter.contains("creator_channel_activity_series_count_format"))
|
||||
assertTrue(adapter.contains("creator_channel_activity_live_count"))
|
||||
assertTrue(adapter.contains("creator_channel_activity_live_duration"))
|
||||
assertTrue(adapter.contains("creator_channel_activity_live_contributor"))
|
||||
assertTrue(adapter.contains("creator_channel_activity_audio_count"))
|
||||
assertTrue(adapter.contains("creator_channel_activity_series_count"))
|
||||
assertTrue(activityLayout.contains("creator_channel_activity_live_count"))
|
||||
assertTrue(activityLayout.contains("creator_channel_activity_live_duration"))
|
||||
assertTrue(activityLayout.contains("creator_channel_activity_live_contributor"))
|
||||
assertTrue(activityLayout.contains("creator_channel_activity_audio_count"))
|
||||
assertTrue(activityLayout.contains("creator_channel_activity_series_count"))
|
||||
assertFalse(adapter.contains("addActivityRow(activity.dDay, activity.debutDateUtc.orEmpty())"))
|
||||
assertFalse(adapter.contains("\"Live "))
|
||||
assertFalse(adapter.contains("\"Audio "))
|
||||
@@ -496,7 +499,7 @@ class CreatorChannelActivitySourceTest {
|
||||
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("activityDebutValue?.text = formatCreatorChannelDebutActivityValue"))
|
||||
assertTrue(adapter.contains("activitySeriesCountValue?.text = itemView.context.getString"))
|
||||
assertFalse(adapter.contains("private fun addActivityRow"))
|
||||
assertFalse(adapter.contains("addActivityRow("))
|
||||
@@ -656,7 +659,12 @@ class CreatorChannelActivitySourceTest {
|
||||
assertTrue(adapter.contains("private val donationEmpty: View?"))
|
||||
assertTrue(adapter.contains("donationItemsScrollView?.isVisible = item.donations.isNotEmpty()"))
|
||||
assertTrue(adapter.contains("donationEmpty?.isVisible = item.donations.isEmpty()"))
|
||||
assertTrue(adapter.contains("private fun bindDonations(item: CreatorChannelHomeSection.Donations) {\n donationItems?.removeAllViews()"))
|
||||
assertTrue(
|
||||
adapter.contains(
|
||||
"private fun bindDonations(item: CreatorChannelHomeSection.Donations) {\n" +
|
||||
" donationItems?.removeAllViews()"
|
||||
)
|
||||
)
|
||||
assertTrue(adapter.contains("R.layout.item_creator_channel_home_donation_row"))
|
||||
assertTrue(adapter.contains("donationItems?.addView(row)"))
|
||||
assertTrue(adapter.contains("val visibleDonations = item.donations.take(MAX_DONATION_ITEM_COUNT)"))
|
||||
@@ -687,25 +695,25 @@ class CreatorChannelActivitySourceTest {
|
||||
assertTrue(adapter.contains("val isDonationEmptyButtonVisible = !item.isOwner"))
|
||||
assertTrue(adapter.contains("donationButton?.isVisible = isDonationButtonVisible"))
|
||||
assertTrue(adapter.contains("donationEmptyButton?.isVisible = isDonationEmptyButtonVisible"))
|
||||
assertTrue(
|
||||
adapter.contains(
|
||||
"donationButton?.setOnClickListener(if (isDonationButtonVisible) View.OnClickListener { onDonationClick() } else null)"
|
||||
)
|
||||
)
|
||||
assertTrue(
|
||||
adapter.contains(
|
||||
"donationEmptyButton?.setOnClickListener(if (isDonationEmptyButtonVisible) View.OnClickListener { onDonationClick() } else null)"
|
||||
)
|
||||
)
|
||||
assertTrue(adapter.contains("donationButton?.setOnClickListener("))
|
||||
assertTrue(adapter.contains("if (isDonationButtonVisible) View.OnClickListener { onDonationClick() } else null"))
|
||||
assertTrue(adapter.contains("donationEmptyButton?.setOnClickListener("))
|
||||
assertTrue(adapter.contains("if (isDonationEmptyButtonVisible) View.OnClickListener { onDonationClick() } else null"))
|
||||
assertTrue(fragment.contains("override fun postChannelDonation(can: Int, isSecret: Boolean, message: String)"))
|
||||
assertTrue(fragment.contains("viewModel.postChannelDonation(can = can, isSecret = isSecret, message = message)"))
|
||||
assertTrue(
|
||||
fragment.contains("viewModel.postChannelDonation(can = can, isSecret = isSecret, message = message)")
|
||||
)
|
||||
assertTrue(fragment.contains("host.onCreatorChannelDonationClicked()"))
|
||||
assertTrue(activity.contains("LiveRoomDonationDialog"))
|
||||
assertTrue(activity.contains("isLiveDonation = true"))
|
||||
assertTrue(activity.contains("messageMaxLength = 100"))
|
||||
assertTrue(activity.contains("secretToggleLabelResId = R.string.screen_user_profile_channel_donation_secret"))
|
||||
assertTrue(
|
||||
activity.contains("secretToggleLabelResId = R.string.screen_user_profile_channel_donation_secret")
|
||||
)
|
||||
assertTrue(activity.contains("applySecretMissionMessageHint = false"))
|
||||
assertTrue(activity.contains("homeActionDelegate?.postChannelDonation(can = can, isSecret = isSecret, message = message)"))
|
||||
assertTrue(
|
||||
activity.contains("homeActionDelegate?.postChannelDonation(can = can, isSecret = isSecret, message = message)")
|
||||
)
|
||||
assertTrue(activity.contains("dialog.show(screenWidth - 26.7f.dpToPx().toInt())"))
|
||||
}
|
||||
|
||||
@@ -992,6 +1000,30 @@ class CreatorChannelActivitySourceTest {
|
||||
assertTrue(source.contains("putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, audioContent.audioContentId)"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Phase 12 오디오 컨텐츠는 표시 개수만큼 높이를 차지하고 free tag는 wrap content를 사용한다`() {
|
||||
val adapter = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt"
|
||||
).readText()
|
||||
val audioItemLayout = projectFile(
|
||||
"app/src/main/res/layout/item_creator_channel_home_audio_content.xml"
|
||||
).readText()
|
||||
|
||||
assertTrue(audioItemLayout.contains("android:id=\"@+id/tv_audio_content_free_tag\""))
|
||||
assertTrue(audioItemLayout.contains("android:layout_width=\"wrap_content\""))
|
||||
assertFalse(
|
||||
audioItemLayout.contains(
|
||||
"android:id=\"@+id/tv_audio_content_free_tag\"\n" +
|
||||
" style=\"@style/Typography.Body6\"\n" +
|
||||
" android:layout_width=\"34dp\""
|
||||
)
|
||||
)
|
||||
assertTrue(adapter.contains("private fun updateAudioContentsGridSpan(itemCount: Int)"))
|
||||
assertTrue(adapter.contains("spanCount = itemCount.coerceIn("))
|
||||
assertTrue(adapter.contains("AUDIO_GRID_SPAN_COUNT"))
|
||||
assertTrue(adapter.contains("updateAudioContentsGridSpan(visibleAudioContents.size)"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `시리즈 섹션은 Figma Contents series size m 카드 row로 렌더링한다`() {
|
||||
val adapter = projectFile(
|
||||
@@ -1018,7 +1050,7 @@ class CreatorChannelActivitySourceTest {
|
||||
assertTrue(seriesItemLayout.contains("@+id/tv_series_original_text"))
|
||||
assertTrue(seriesItemLayout.contains("android:text=\"Only\""))
|
||||
assertTrue(seriesItemLayout.contains("@font/phosphate_solid"))
|
||||
assertTrue(seriesItemLayout.contains("android:layout_width=\"70dp\""))
|
||||
assertTrue(seriesItemLayout.contains("android:layout_width=\"wrap_content\""))
|
||||
assertTrue(seriesItemLayout.contains("@drawable/bg_series_original_tag"))
|
||||
assertTrue(seriesItemLayout.contains("@drawable/ic_series_original"))
|
||||
assertTrue(seriesItemLayout.contains("android:layout_width=\"163dp\""))
|
||||
@@ -1079,6 +1111,72 @@ class CreatorChannelActivitySourceTest {
|
||||
assertEquals(206, calculateCreatorChannelSeriesCardHeightDp(146))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Phase 12 시리즈 original tag는 wrap content sizing과 상세 이동 계약을 사용한다`() {
|
||||
val source = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt"
|
||||
).readText()
|
||||
val fragment = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeFragment.kt"
|
||||
).readText()
|
||||
val seriesItemLayout = projectFile(
|
||||
"app/src/main/res/layout/item_creator_channel_home_series_content.xml"
|
||||
).readText()
|
||||
|
||||
assertTrue(seriesItemLayout.contains("android:id=\"@+id/layout_series_original_tag\""))
|
||||
assertTrue(seriesItemLayout.contains("android:layout_width=\"wrap_content\""))
|
||||
assertTrue(seriesItemLayout.contains("android:layout_height=\"wrap_content\""))
|
||||
assertTrue(seriesItemLayout.contains("android:paddingStart=\"8dp\""))
|
||||
assertTrue(seriesItemLayout.contains("android:paddingEnd=\"8dp\""))
|
||||
assertTrue(seriesItemLayout.contains("android:minHeight=\"24dp\""))
|
||||
assertFalse(seriesItemLayout.contains("android:layout_width=\"70dp\""))
|
||||
assertTrue(fragment.contains("onSeriesClick = ::onSeriesClicked"))
|
||||
assertTrue(fragment.contains("private fun onSeriesClicked(series: CreatorChannelSeriesResponse)"))
|
||||
assertTrue(fragment.contains("host.onCreatorChannelSeriesClicked(series)"))
|
||||
assertTrue(source.contains("import kr.co.vividnext.sodalive.audio_content.series.detail.SeriesDetailActivity"))
|
||||
assertTrue(source.contains("private fun onSeriesClicked(series: CreatorChannelSeriesResponse)"))
|
||||
assertTrue(source.contains("SeriesDetailActivity::class.java"))
|
||||
assertTrue(source.contains("putExtra(Constants.EXTRA_SERIES_ID, series.seriesId)"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Phase 12 활동 영역은 Figma label value typography와 debut 날짜 포맷을 사용한다`() {
|
||||
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("style=\"@style/Typography.Body2\""))
|
||||
assertTrue(activityLayout.contains("android:lineSpacingMultiplier=\"1.45\""))
|
||||
assertTrue(activityLayout.contains("android:letterSpacing=\"0\""))
|
||||
assertTrue(activityLayout.contains("android:textColor=\"#939393\""))
|
||||
assertTrue(activityLayout.contains("android:textColor=\"@color/white\""))
|
||||
assertTrue(activityLayout.contains("android:layout_marginEnd=\"@dimen/spacing_8\""))
|
||||
assertTrue(activityLayout.contains("android:layout_marginBottom=\"@dimen/spacing_8\""))
|
||||
assertTrue(adapter.contains("formatCreatorChannelDebutActivityValue("))
|
||||
assertFalse(
|
||||
adapter.contains("itemView.context.getString(R.string.creator_channel_activity_debut_format, debutDate, dDay)")
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
"2026.06.11(D+1)",
|
||||
formatCreatorChannelDebutActivityValue(
|
||||
"2026-06-10T15:00:00Z",
|
||||
"D+1",
|
||||
TimeZone.getTimeZone("Asia/Seoul")
|
||||
)
|
||||
)
|
||||
assertEquals(
|
||||
"D+1",
|
||||
formatCreatorChannelDebutActivityValue(null, "D+1", TimeZone.getTimeZone("Asia/Seoul"))
|
||||
)
|
||||
assertEquals(
|
||||
"D+1",
|
||||
formatCreatorChannelDebutActivityValue("invalid", "D+1", TimeZone.getTimeZone("Asia/Seoul"))
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `커뮤니티 섹션은 Figma feed card 3개와 전체보기 capsule로 렌더링한다`() {
|
||||
val adapter = projectFile(
|
||||
|
||||
@@ -1257,7 +1257,7 @@
|
||||
- [x] `LiveRoomDonationDialog`가 validation/dismiss/charge navigation을 소유하고 `UserProfileActivity`도 callback-only 패턴을 쓰므로, Activity dismiss 흐름은 변경하지 않는다.
|
||||
- [x] 로컬 can 차감은 전체 balance resync가 아니라 최소 안전 장치로 `(SharedPreferenceManager.can - can).coerceAtLeast(0)`만 적용한다.
|
||||
|
||||
- [ ] **Task 12.2: 오디오/시리즈 아이템 세부 UI와 터치 액션 보강**
|
||||
- [x] **Task 12.2: 오디오/시리즈 아이템 세부 UI와 터치 액션 보강**
|
||||
- 수정:
|
||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt`
|
||||
- `app/src/main/res/layout/item_creator_channel_home_audio.xml`
|
||||
@@ -1279,8 +1279,12 @@
|
||||
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"`
|
||||
- `./gradlew :app:mergeDebugResources`
|
||||
- `./gradlew :app:compileDebugKotlin`
|
||||
- 검증 기록:
|
||||
- 2026-06-16: Figma `296:14895`와 시리즈 `Contents(type=series, size=m)` 구조를 확인해 오디오 free tag와 시리즈 original tag sizing 기준을 재확인했다. RED로 `CreatorChannelActivitySourceTest`에 오디오 `tv_audio_content_free_tag` `wrap_content`, audio grid span count 동적 보정, 시리즈 original tag `wrap_content`/padding, 시리즈 상세 이동 계약을 추가했고, 최초 실행은 `formatCreatorChannelDebutActivityValue` 미구현 컴파일 실패로 RED를 확인했다.
|
||||
- 2026-06-16: `item_creator_channel_home_audio_content.xml`의 free tag width를 `wrap_content`로 변경하되 `minWidth=34dp`와 padding을 유지했다. `CreatorChannelHomeSectionAdapter`는 표시되는 오디오 개수에 맞춰 `GridLayoutManager.spanCount = itemCount.coerceIn(1, AUDIO_GRID_SPAN_COUNT)`로 보정해 1개 항목에서 3개 row 높이를 예약하지 않게 했다. `item_creator_channel_home_series_content.xml`의 original tag는 width/height `wrap_content`, `minHeight=24dp`, horizontal padding으로 조정하고, `CreatorChannelHomeFragment`/`CreatorChannelActivity`에 `CreatorChannelSeriesResponse` click forwarding과 `SeriesDetailActivity` + `Constants.EXTRA_SERIES_ID` 이동을 연결했다.
|
||||
- 2026-06-16: 검증 중 기존 source assertion의 과거 `70dp` tag width 계약과 줄바꿈 전 문자열 계약이 Phase 12 구현과 충돌해 테스트를 새 계약 기준으로 갱신했다. 이후 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*"`, `./gradlew :app:mergeDebugResources`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:ktlintCheck`, `git diff --check`가 모두 PASS했다. `ktlintCheck`의 `.editorconfig disabled_rules` deprecation warning과 Gradle deprecation warning은 기존 경고로 이번 변경과 무관하다.
|
||||
|
||||
- [ ] **Task 12.3: 활동 영역 Figma 정합성과 데뷔 날짜/D+n 버그 수정**
|
||||
- [x] **Task 12.3: 활동 영역 Figma 정합성과 데뷔 날짜/D+n 버그 수정**
|
||||
- 수정:
|
||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt`
|
||||
- `app/src/main/res/layout/item_creator_channel_home_activity.xml`
|
||||
@@ -1302,6 +1306,10 @@
|
||||
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"`
|
||||
- `./gradlew :app:mergeDebugResources`
|
||||
- `./gradlew :app:compileDebugKotlin`
|
||||
- 검증 기록:
|
||||
- 2026-06-16: Figma `296:15001` 스크린샷/metadata를 확인해 활동 섹션이 `SectionTitle(활동)`, label/value 16sp medium row, label `#939393`, value white, label/value 8dp gap, row 간 8dp 구조임을 반영했다. `item_creator_channel_home_activity.xml`의 각 label/value에 `Typography.Body2`, `lineSpacingMultiplier=1.45`, `letterSpacing=0`, label `#939393`, value `@color/white`, label `marginEnd=8dp`를 적용했다.
|
||||
- 2026-06-16: `formatCreatorChannelDebutActivityValue(debutDateUtc, dDay, timeZone, locale)` helper를 추가해 UTC ISO 날짜를 `yyyy.MM.dd`로 변환하고 `yyyy.MM.dd(D+n)` 형식으로 표시하도록 수정했다. `debutDateUtc`가 null/blank이거나 파싱 실패해도 `dDay`가 누락되지 않도록 `dDay`를 fallback으로 반환한다.
|
||||
- 2026-06-16: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*"`, `./gradlew :app:mergeDebugResources`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:ktlintCheck`, `git diff --check`가 모두 PASS했다. 최초 `ktlintCheck`는 새/기존 source assertion과 adapter 긴 줄로 실패했으나 줄바꿈만 보정한 뒤 재실행해 PASS했다.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user