feat(live): 온에어 라이브 매핑을 추가한다

This commit is contained in:
2026-06-26 23:43:05 +09:00
parent 6e04a10a3b
commit c3377e39e6
3 changed files with 181 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
package kr.co.vividnext.sodalive.v2.live.onair.model
import kr.co.vividnext.sodalive.v2.live.onair.data.HomeOnAirLivePageResponse
import kr.co.vividnext.sodalive.v2.live.onair.data.HomeOnAirLiveResponse
import java.text.NumberFormat
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.TimeZone
fun HomeOnAirLivePageResponse.toUiState(
deviceTimeZone: TimeZone = TimeZone.getDefault()
): HomeOnAirLiveUiState = HomeOnAirLiveUiState(
items = items.map { it.toUiModel(deviceTimeZone) },
page = page,
size = size,
hasNext = hasNext
)
fun HomeOnAirLiveResponse.toUiModel(
deviceTimeZone: TimeZone = TimeZone.getDefault()
): HomeOnAirLiveUiModel = HomeOnAirLiveUiModel(
roomId = roomId,
creatorNickname = creatorNickname,
creatorProfileImage = creatorProfileImage,
title = title,
liveTimeText = "LIVE ${beginDateTimeUtc.toLiveStartTime(deviceTimeZone)}",
price = price.toPriceUiModel()
)
private fun Int.toPriceUiModel(): HomeOnAirLivePriceUiModel {
return if (this > 0) {
HomeOnAirLivePriceUiModel.Paid(
amount = this,
amountText = NumberFormat.getNumberInstance(Locale.KOREA).format(this)
)
} else {
HomeOnAirLivePriceUiModel.Free
}
}
private fun String.toLiveStartTime(deviceTimeZone: TimeZone): String {
val parsedDate = UTC_DATE_FORMATS.firstNotNullOfOrNull { format ->
try {
format.parse(this)
} catch (_: ParseException) {
null
}
} ?: return "--:--"
return SimpleDateFormat("HH:mm", Locale.US).apply {
timeZone = deviceTimeZone
}.format(parsedDate)
}
private val UTC_DATE_FORMATS = listOf(
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
"yyyy-MM-dd'T'HH:mm:ss'Z'",
"yyyy-MM-dd'T'HH:mm:ss.SSS",
"yyyy-MM-dd'T'HH:mm:ss"
).map { pattern ->
SimpleDateFormat(pattern, Locale.US).apply {
timeZone = TimeZone.getTimeZone("UTC")
}
}

View File

@@ -0,0 +1,35 @@
package kr.co.vividnext.sodalive.v2.live.onair.model
data class HomeOnAirLiveUiState(
val items: List<HomeOnAirLiveUiModel>,
val page: Int,
val size: Int,
val hasNext: Boolean,
val isLoadingMore: Boolean = false,
val paginationErrorMessage: String? = null
)
data class HomeOnAirLiveUiModel(
val roomId: Long,
val creatorNickname: String,
val creatorProfileImage: String,
val title: String,
val liveTimeText: String,
val price: HomeOnAirLivePriceUiModel
)
sealed interface HomeOnAirLivePriceUiModel {
data class Paid(
val amount: Int,
val amountText: String
) : HomeOnAirLivePriceUiModel
data object Free : HomeOnAirLivePriceUiModel
}
sealed interface HomeOnAirLivePageUiState {
data object Loading : HomeOnAirLivePageUiState
data object Empty : HomeOnAirLivePageUiState
data class Content(val content: HomeOnAirLiveUiState) : HomeOnAirLivePageUiState
data class Error(val message: String?) : HomeOnAirLivePageUiState
}