From 0ea2a1055470b79df1f7c134b1ec3bb037cedf4d Mon Sep 17 00:00:00 2001 From: klaus Date: Tue, 23 Jun 2026 17:17:17 +0900 Subject: [PATCH] =?UTF-8?q?feat(content):=20=EC=B6=94=EC=B2=9C=20=EB=B0=B0?= =?UTF-8?q?=EB=84=88=20=EA=B2=BD=EB=A1=9C=EB=A5=BC=20=EC=97=B0=EA=B2=B0?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/AudioRecommendationsUiModels.kt | 54 +++++++++++++++++++ .../v2/main/content/ui/ContentBannerBinder.kt | 44 +++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/ui/ContentBannerBinder.kt diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/model/AudioRecommendationsUiModels.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/model/AudioRecommendationsUiModels.kt index 08d608f2..a5ef012c 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/model/AudioRecommendationsUiModels.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/model/AudioRecommendationsUiModels.kt @@ -1,6 +1,14 @@ package kr.co.vividnext.sodalive.v2.main.content.model +import android.content.Context +import android.content.Intent +import android.net.Uri +import kr.co.vividnext.sodalive.BuildConfig +import kr.co.vividnext.sodalive.audio_content.series.detail.SeriesDetailActivity +import kr.co.vividnext.sodalive.common.Constants +import kr.co.vividnext.sodalive.settings.event.EventDetailActivity import kr.co.vividnext.sodalive.settings.event.EventItem +import kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivity import kr.co.vividnext.sodalive.v2.widget.AudioContentTag data class ContentBannerSection( @@ -27,6 +35,52 @@ data class ContentBannerUiModel( val link: String? ) +sealed interface ContentBannerRoute { + data class Event(val eventItem: EventItem) : ContentBannerRoute + + data class Creator(val creatorId: Long) : ContentBannerRoute + + data class Series(val seriesId: Long) : ContentBannerRoute + + data class Link(val url: String, val isWebUrl: Boolean) : ContentBannerRoute +} + +fun ContentBannerUiModel.toContentBannerRoute(): ContentBannerRoute? { + eventItem?.let { return ContentBannerRoute.Event(it) } + creatorId?.takeIf { it > 0 }?.let { return ContentBannerRoute.Creator(it) } + seriesId?.takeIf { it > 0 }?.let { return ContentBannerRoute.Series(it) } + + val routeLink = link?.trim()?.takeIf { it.isNotBlank() } ?: return null + val uri = runCatching { Uri.parse(routeLink) }.getOrNull() ?: return null + val scheme = uri.scheme?.lowercase() ?: return null + val isWebUrl = scheme == "http" || scheme == "https" + val isInternalDeepLink = scheme == BuildConfig.APPSCHEME || + (isWebUrl && uri.host.equals(contentBannerAppLinkHost(), ignoreCase = true)) + if (!isWebUrl && !isInternalDeepLink) return null + return ContentBannerRoute.Link( + url = routeLink, + isWebUrl = isWebUrl && !isInternalDeepLink + ) +} + +fun ContentBannerRoute.toContentBannerIntent(context: Context): Intent { + return when (this) { + is ContentBannerRoute.Event -> Intent(context, EventDetailActivity::class.java).apply { + putExtra(Constants.EXTRA_EVENT, eventItem) + } + + is ContentBannerRoute.Creator -> CreatorChannelActivity.newIntent(context, creatorId) + + is ContentBannerRoute.Series -> Intent(context, SeriesDetailActivity::class.java).apply { + putExtra(Constants.EXTRA_SERIES_ID, seriesId) + } + + is ContentBannerRoute.Link -> Intent(Intent.ACTION_VIEW, Uri.parse(url)) + } +} + +private fun contentBannerAppLinkHost(): String = "${BuildConfig.APPSCHEME}.onelink.me" + data class ContentOriginalSeriesUiModel( val seriesId: Long, val coverImageUrl: String? diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/ui/ContentBannerBinder.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/ui/ContentBannerBinder.kt new file mode 100644 index 00000000..e78fd59b --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/ui/ContentBannerBinder.kt @@ -0,0 +1,44 @@ +package kr.co.vividnext.sodalive.v2.main.content.ui + +import kr.co.vividnext.sodalive.extensions.loadUrl +import kr.co.vividnext.sodalive.v2.main.content.model.ContentBannerSection +import kr.co.vividnext.sodalive.v2.main.content.model.ContentBannerUiModel +import kr.co.vividnext.sodalive.v2.widget.banner.BannerItem +import kr.co.vividnext.sodalive.v2.widget.banner.BannerView + +class ContentBannerBinder( + private val bannerView: BannerView +) { + private var onBannerClick: ((ContentBannerUiModel) -> Unit)? = null + + init { + bannerView.setOnBindBannerImage { imageView, item -> + if (item.imageUrl.isBlank()) imageView.setImageDrawable(null) else imageView.loadUrl(item.imageUrl) + } + bannerView.setOnBannerClickListener { item -> onBannerClick?.invoke(item.toContentBannerUiModel()) } + } + + fun setOnBannerClick(listener: ((ContentBannerUiModel) -> Unit)?) { + onBannerClick = listener + } + + fun bind(section: ContentBannerSection) { + bannerView.setItems(section.items.map { it.toBannerItem() }) + } + + private fun ContentBannerUiModel.toBannerItem(): BannerItem = BannerItem( + imageUrl = imageUrl, + eventItem = eventItem, + creatorId = creatorId, + seriesId = seriesId, + link = link + ) + + private fun BannerItem.toContentBannerUiModel(): ContentBannerUiModel = ContentBannerUiModel( + imageUrl = imageUrl, + eventItem = eventItem, + creatorId = creatorId, + seriesId = seriesId, + link = link + ) +}