refactor(live): 온에어 접근 가드를 공통화한다
This commit is contained in:
@@ -8,7 +8,6 @@ import androidx.core.view.isVisible
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.gson.Gson
|
||||
import kr.co.vividnext.sodalive.R
|
||||
import kr.co.vividnext.sodalive.audio_content.AudioContentPlayService
|
||||
import kr.co.vividnext.sodalive.audio_content.player.AudioContentPlayerService
|
||||
@@ -23,16 +22,10 @@ import kr.co.vividnext.sodalive.live.room.detail.GetRoomDetailResponse
|
||||
import kr.co.vividnext.sodalive.live.room.LiveRoomActivity
|
||||
import kr.co.vividnext.sodalive.live.room.dialog.LivePaymentDialog
|
||||
import kr.co.vividnext.sodalive.live.room.dialog.LiveRoomPasswordDialog
|
||||
import kr.co.vividnext.sodalive.mypage.MyPageViewModel
|
||||
import kr.co.vividnext.sodalive.mypage.auth.Auth
|
||||
import kr.co.vividnext.sodalive.mypage.auth.AuthVerifyRequest
|
||||
import kr.co.vividnext.sodalive.mypage.auth.BootpayResponse
|
||||
import kr.co.vividnext.sodalive.settings.ContentSettingsActivity
|
||||
import kr.co.vividnext.sodalive.settings.language.LanguageManager
|
||||
import kr.co.vividnext.sodalive.settings.language.LocaleHelper
|
||||
import kr.co.vividnext.sodalive.splash.SplashActivity
|
||||
import kr.co.vividnext.sodalive.user.login.LoginActivity
|
||||
import kr.co.vividnext.sodalive.v2.components.modal.V2ModalDialog
|
||||
import kr.co.vividnext.sodalive.v2.access.AccessRequirement
|
||||
import kr.co.vividnext.sodalive.v2.access.ensureV2Access
|
||||
import kr.co.vividnext.sodalive.v2.live.onair.model.HomeOnAirLivePageUiState
|
||||
import kr.co.vividnext.sodalive.v2.live.onair.model.canEnterHomeOnAirLiveRoom
|
||||
import kr.co.vividnext.sodalive.v2.live.onair.ui.HomeOnAirLiveAdapter
|
||||
@@ -49,7 +42,6 @@ class HomeOnAirLiveActivity : BaseActivity<ActivityHomeOnAirLiveBinding>(
|
||||
) {
|
||||
private val viewModel: HomeOnAirLiveViewModel by viewModel()
|
||||
private val liveViewModel: LiveViewModel by inject()
|
||||
private val myPageViewModel: MyPageViewModel by inject()
|
||||
private val loadingDialog: LoadingDialog by lazy { LoadingDialog(this, layoutInflater) }
|
||||
private val adapter = HomeOnAirLiveAdapter { enterLiveRoom(it.roomId) }
|
||||
private var isPageLoading = false
|
||||
@@ -118,14 +110,14 @@ class HomeOnAirLiveActivity : BaseActivity<ActivityHomeOnAirLiveBinding>(
|
||||
}
|
||||
|
||||
private fun enterLiveRoom(roomId: Long) {
|
||||
ensureLoginAndAdultAuth(isAdult = false) {
|
||||
ensureV2Access(AccessRequirement.Login) {
|
||||
liveViewModel.getRoomDetail(roomId) { roomDetail ->
|
||||
if (!canEnterHomeOnAirLiveRoom(roomDetail)) {
|
||||
Toast.makeText(applicationContext, R.string.common_error_unknown, Toast.LENGTH_LONG).show()
|
||||
return@getRoomDetail
|
||||
}
|
||||
|
||||
ensureLoginAndAdultAuth(isAdult = roomDetail.isAdult) {
|
||||
ensureV2Access(AccessRequirement.forAdultContent(roomDetail.isAdult)) {
|
||||
enterLiveRoom(roomId, roomDetail)
|
||||
}
|
||||
}
|
||||
@@ -173,70 +165,6 @@ class HomeOnAirLiveActivity : BaseActivity<ActivityHomeOnAirLiveBinding>(
|
||||
}
|
||||
}
|
||||
|
||||
private fun ensureLoginAndAdultAuth(isAdult: Boolean, onAuthed: () -> Unit) {
|
||||
if (SharedPreferenceManager.token.isBlank()) {
|
||||
showLoginActivity()
|
||||
return
|
||||
}
|
||||
|
||||
if (isAdult) {
|
||||
val isKoreanCountry = SharedPreferenceManager.countryCode.ifBlank { "KR" } == "KR"
|
||||
if (isKoreanCountry && !SharedPreferenceManager.isAuth) {
|
||||
V2ModalDialog(
|
||||
activity = this,
|
||||
layoutInflater = layoutInflater,
|
||||
title = getString(R.string.auth_title),
|
||||
desc = getString(R.string.auth_desc_live),
|
||||
confirmButtonTitle = getString(R.string.auth_go),
|
||||
confirmButtonClick = { startAuthFlow() },
|
||||
cancelButtonTitle = getString(R.string.cancel),
|
||||
cancelButtonClick = {}
|
||||
).show(screenWidth)
|
||||
return
|
||||
}
|
||||
|
||||
if (!SharedPreferenceManager.isAdultContentVisible) {
|
||||
startActivity(
|
||||
Intent(applicationContext, ContentSettingsActivity::class.java).apply {
|
||||
putExtra(Constants.EXTRA_SHOW_SENSITIVE_CONTENT_GUIDE, true)
|
||||
}
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
onAuthed()
|
||||
}
|
||||
|
||||
private fun showLoginActivity() {
|
||||
if (SharedPreferenceManager.token.isBlank()) {
|
||||
startActivity(
|
||||
Intent(applicationContext, LoginActivity::class.java).apply {
|
||||
putExtra(Constants.EXTRA_DATA, intent.extras)
|
||||
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun startAuthFlow() {
|
||||
Auth.auth(this, this) { json ->
|
||||
val bootpayResponse = Gson().fromJson(json, BootpayResponse::class.java)
|
||||
val request = AuthVerifyRequest(receiptId = bootpayResponse.data.receiptId)
|
||||
runOnUiThread {
|
||||
myPageViewModel.authVerify(request) {
|
||||
startActivity(
|
||||
Intent(applicationContext, SplashActivity::class.java).apply {
|
||||
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showPasswordDialog(roomId: Long, can: Int, onEnterRoomSuccess: () -> Unit) {
|
||||
LiveRoomPasswordDialog(
|
||||
activity = this,
|
||||
|
||||
@@ -7,6 +7,7 @@ import kr.co.vividnext.sodalive.v2.live.onair.model.canEnterHomeOnAirLiveRoom
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
|
||||
class HomeOnAirLiveEntryPolicyTest {
|
||||
|
||||
@@ -25,6 +26,27 @@ class HomeOnAirLiveEntryPolicyTest {
|
||||
assertFalse(canEnterHomeOnAirLiveRoom(roomDetail(channelName = " ")))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `라이브 입장은 로그인 상세 조회 성인 가드 기존 입장 순서를 유지한다`() {
|
||||
val source = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/live/onair/HomeOnAirLiveActivity.kt"
|
||||
).readText()
|
||||
val entrySource = sourceSection(
|
||||
source = source,
|
||||
startMarker = "private fun enterLiveRoom(roomId: Long) {",
|
||||
endMarker = "private fun enterLiveRoom(roomId: Long, roomDetail: GetRoomDetailResponse)"
|
||||
)
|
||||
val loginGuard = "ensureV2Access(AccessRequirement.Login)"
|
||||
val roomDetailQuery = "liveViewModel.getRoomDetail(roomId) { roomDetail ->"
|
||||
val adultGuard = "ensureV2Access(AccessRequirement.forAdultContent(roomDetail.isAdult))"
|
||||
val enterRoom = "enterLiveRoom(roomId, roomDetail)"
|
||||
|
||||
assertBefore(entrySource, loginGuard, roomDetailQuery)
|
||||
assertBefore(entrySource, roomDetailQuery, adultGuard)
|
||||
assertBefore(entrySource, adultGuard, enterRoom)
|
||||
assertFalse(source.contains("private fun ensureLoginAndAdultAuth"))
|
||||
}
|
||||
|
||||
private fun roomDetail(channelName: String?) = GetRoomDetailResponse(
|
||||
roomId = 1L,
|
||||
price = 0,
|
||||
@@ -55,4 +77,28 @@ class HomeOnAirLiveEntryPolicyTest {
|
||||
),
|
||||
participatingUsers = emptyList()
|
||||
)
|
||||
|
||||
private fun sourceSection(source: String, startMarker: String, endMarker: String): String {
|
||||
val start = source.indexOf(startMarker)
|
||||
val end = source.indexOf(endMarker, start)
|
||||
|
||||
assertTrue("start marker not found: $startMarker", start >= 0)
|
||||
assertTrue("end marker not found after: $startMarker", end > start)
|
||||
|
||||
return source.substring(start, end)
|
||||
}
|
||||
|
||||
private fun assertBefore(source: String, expectedBefore: String, expectedAfter: String) {
|
||||
val beforeIndex = source.indexOf(expectedBefore)
|
||||
val afterIndex = source.indexOf(expectedAfter, beforeIndex)
|
||||
|
||||
assertTrue("missing source: $expectedBefore", beforeIndex >= 0)
|
||||
assertTrue("missing source after $expectedBefore: $expectedAfter", afterIndex > beforeIndex)
|
||||
}
|
||||
|
||||
private fun projectFile(relativePath: String): File {
|
||||
val candidates = listOf(File(relativePath), File("../$relativePath"))
|
||||
return candidates.firstOrNull { it.exists() }
|
||||
?: error("Project file not found: $relativePath")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user