From 0a4b88fabeaaab50c3e9efde45ffebab53a790c4 Mon Sep 17 00:00:00 2001 From: klaus Date: Sat, 27 Jun 2026 08:29:19 +0900 Subject: [PATCH] =?UTF-8?q?feat(content):=20=EC=A0=84=EC=B2=B4=EB=B3=B4?= =?UTF-8?q?=EA=B8=B0=20UI=20=EB=AA=A8=EB=8D=B8=20=EB=A7=A4=ED=95=91?= =?UTF-8?q?=EC=9D=84=20=EC=B6=94=EA=B0=80=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../overview/model/ContentOverviewMappers.kt | 32 +++++ .../overview/model/ContentOverviewUiModels.kt | 21 ++++ .../overview/model/ContentOverviewUiState.kt | 19 +++ .../ic_feed_community_heart_fill.png | Bin 0 -> 401 bytes .../overview/ContentOverviewMapperTest.kt | 112 ++++++++++++++++++ 5 files changed, 184 insertions(+) create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/model/ContentOverviewMappers.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/model/ContentOverviewUiModels.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/model/ContentOverviewUiState.kt create mode 100644 app/src/main/res/drawable-mdpi/ic_feed_community_heart_fill.png create mode 100644 app/src/test/java/kr/co/vividnext/sodalive/v2/main/content/overview/ContentOverviewMapperTest.kt diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/model/ContentOverviewMappers.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/model/ContentOverviewMappers.kt new file mode 100644 index 00000000..819ce1c0 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/model/ContentOverviewMappers.kt @@ -0,0 +1,32 @@ +package kr.co.vividnext.sodalive.v2.main.content.overview.model + +import kr.co.vividnext.sodalive.v2.main.content.overview.data.ContentOverviewItemResponse +import kr.co.vividnext.sodalive.v2.main.content.overview.data.ContentOverviewPageResponse +import kr.co.vividnext.sodalive.v2.widget.AudioContentTag + +fun ContentOverviewPageResponse.toContent(): ContentOverviewUiState.Content { + return ContentOverviewUiState.Content( + type = type, + totalCount = items.size, + items = items.map { it.toUiModel() }, + page = page, + size = size, + hasNext = hasNext + ) +} + +fun ContentOverviewItemResponse.toUiModel(): ContentOverviewUiModel = ContentOverviewUiModel( + contentId = contentId, + title = title, + coverImage = coverImage, + creatorNickname = creatorNickname, + tags = toAudioContentTags(), + showAdultBadge = isAdult +) + +private fun ContentOverviewItemResponse.toAudioContentTags(): Set = buildSet { + if (isOriginalSeries) add(AudioContentTag.Original) + if (isFirstContent) add(AudioContentTag.First) + if (isPointAvailable) add(AudioContentTag.Point) + if (price == 0) add(AudioContentTag.Free) +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/model/ContentOverviewUiModels.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/model/ContentOverviewUiModels.kt new file mode 100644 index 00000000..c374b22c --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/model/ContentOverviewUiModels.kt @@ -0,0 +1,21 @@ +package kr.co.vividnext.sodalive.v2.main.content.overview.model + +import androidx.annotation.StringRes +import kr.co.vividnext.sodalive.R +import kr.co.vividnext.sodalive.v2.main.content.overview.data.ContentOverviewType +import kr.co.vividnext.sodalive.v2.widget.AudioContentTag + +data class ContentOverviewUiModel( + val contentId: Long, + val title: String, + val coverImage: String?, + val creatorNickname: String, + val tags: Set, + val showAdultBadge: Boolean +) + +@StringRes +fun ContentOverviewType.toTitleResId(): Int = when (this) { + ContentOverviewType.NEW_AND_HOT_AUDIO -> R.string.content_recommendation_section_new_and_hot + ContentOverviewType.FIRST_AUDIO_CONTENT -> R.string.home_recommendation_section_first_audio_contents +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/model/ContentOverviewUiState.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/model/ContentOverviewUiState.kt new file mode 100644 index 00000000..2ec60c2b --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/model/ContentOverviewUiState.kt @@ -0,0 +1,19 @@ +package kr.co.vividnext.sodalive.v2.main.content.overview.model + +import kr.co.vividnext.sodalive.v2.main.content.overview.data.ContentOverviewType + +sealed interface ContentOverviewUiState { + data class Loading(val type: ContentOverviewType) : ContentOverviewUiState + data class Empty(val type: ContentOverviewType, val totalCount: Int) : ContentOverviewUiState + data class Error(val type: ContentOverviewType, val message: String?) : ContentOverviewUiState + data class Content( + val type: ContentOverviewType, + val totalCount: Int, + val items: List, + val page: Int, + val size: Int, + val hasNext: Boolean, + val isLoadingMore: Boolean = false, + val paginationErrorMessage: String? = null + ) : ContentOverviewUiState +} diff --git a/app/src/main/res/drawable-mdpi/ic_feed_community_heart_fill.png b/app/src/main/res/drawable-mdpi/ic_feed_community_heart_fill.png new file mode 100644 index 0000000000000000000000000000000000000000..cd9968e5ff041a14082ac8c489a5f48cd1a364f6 GIT binary patch literal 401 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1|-AI^@Rf|&H|6fVg?3oVGw3ym^DWND9BhG zX2qt`s`;c1prjYnwwd zjjg8}w@set;q-$u=Yj5}x%159%O`ObWG%{S%(pfalld8Hy7c1l)$8NkBNV==8GW(y z%XXBBZ!M@&$XtD=Yi-V!Nv>1p-T!gXJmrke?m*Ydb@JC0_EkqPJHFdn(0s{7W_xr& zR+saVyQ)j$ulYY|5@^p_w@61rMmy}A{1Rs6>yop&ZeA)#;u2W;>DkQR8EX_G(~d5_ z_~NstlW;_R<*`qHuZCJybhfa+Y2r~onbr6zCOYxV_xj7p>Kfn6Z`=M8AHh|1)>}_|uoipPCt7q$c7}1`II = listOf(item()), + page: Int = 0, + size: Int = 20, + hasNext: Boolean = false + ) = ContentOverviewPageResponse( + type = type, + items = items, + page = page, + size = size, + hasNext = hasNext + ) + + private fun item( + contentId: Long = 1L, + title: String = "content", + coverImage: String? = "https://example.com/image.png", + price: Int = 100, + isAdult: Boolean = false, + isPointAvailable: Boolean = false, + isFirstContent: Boolean = false, + isOriginalSeries: Boolean = false, + creatorNickname: String = "creator" + ) = ContentOverviewItemResponse( + contentId = contentId, + title = title, + coverImage = coverImage, + price = price, + isAdult = isAdult, + isPointAvailable = isPointAvailable, + isFirstContent = isFirstContent, + isOriginalSeries = isOriginalSeries, + creatorNickname = creatorNickname + ) +}