From de90b34cd497f74888eb287a1506e1f9e093e55d Mon Sep 17 00:00:00 2001 From: klaus Date: Fri, 19 Jun 2026 00:09:59 +0900 Subject: [PATCH] =?UTF-8?q?fix(dm):=20USER=5FCREATOR=20DM=20push=20?= =?UTF-8?q?=EB=9D=BC=EC=9A=B0=ED=8C=85=EC=9D=84=20=EB=B3=B4=EC=A0=95?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sodalive/main/DeepLinkActivity.kt | 19 +++++++ .../sodalive/v2/main/MainV2Activity.kt | 12 +++++ .../main/DeepLinkActivitySourceTest.kt | 49 +++++++++++++++++++ .../v2/main/MainV2ActivitySourceTest.kt | 26 ++++++++++ 4 files changed, 106 insertions(+) create mode 100644 app/src/test/java/kr/co/vividnext/sodalive/main/DeepLinkActivitySourceTest.kt create mode 100644 app/src/test/java/kr/co/vividnext/sodalive/v2/main/MainV2ActivitySourceTest.kt diff --git a/app/src/main/java/kr/co/vividnext/sodalive/main/DeepLinkActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/main/DeepLinkActivity.kt index 939cbefa..4fd95956 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/main/DeepLinkActivity.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/main/DeepLinkActivity.kt @@ -17,6 +17,7 @@ import kr.co.vividnext.sodalive.mypage.can.payment.CanPaymentActivity import kr.co.vividnext.sodalive.splash.SplashActivity import kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivity import kr.co.vividnext.sodalive.v2.main.MainV2Activity +import kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomActivity import java.util.Locale class DeepLinkActivity : AppCompatActivity() { @@ -43,6 +44,13 @@ class DeepLinkActivity : AppCompatActivity() { } } + if (SodaLiveApp.isAppInForeground && deepLinkExtras != null && isUserCreatorChat(deepLinkExtras)) { + if (routeForegroundDeepLink(deepLinkExtras)) { + finish() + return + } + } + if (SodaLiveApp.isAppInForeground && LiveRoomActivity.isForeground && deepLinkExtras != null) { LocalBroadcastManager.getInstance(applicationContext).sendBroadcast( Intent(Constants.ACTION_LIVE_ROOM_DEEPLINK_CONFIRM).apply { @@ -106,6 +114,7 @@ class DeepLinkActivity : AppCompatActivity() { } putQuery("room_id") + putQuery("chat_type") putQuery("channel_id") putQuery("message_id") putQuery("audition_id") @@ -131,6 +140,7 @@ class DeepLinkActivity : AppCompatActivity() { } } + copyString("chat_type") copyString("room_id") copyString("channel_id") copyString("message_id") @@ -267,6 +277,11 @@ class DeepLinkActivity : AppCompatActivity() { val communityPostId = bundle.getString(Constants.EXTRA_COMMUNITY_POST_ID)?.toLongOrNull() ?: bundle.getLong(Constants.EXTRA_COMMUNITY_POST_ID).takeIf { it > 0 } + if (isUserCreatorChat(bundle) && roomId != null && roomId > 0) { + startActivity(DmChatRoomActivity.newIntentByRoomId(applicationContext, roomId)) + return true + } + when { roomId != null && roomId > 0 -> { routeLiveInMain(roomId) @@ -317,6 +332,10 @@ class DeepLinkActivity : AppCompatActivity() { return routeByDeepLinkValue(deepLinkValue = deepLinkValue, deepLinkValueId = deepLinkValueId) } + private fun isUserCreatorChat(bundle: Bundle): Boolean { + return bundle.getString("chat_type") == "USER_CREATOR" + } + private fun routeByDeepLinkValue(deepLinkValue: String?, deepLinkValueId: Long?): Boolean { if (deepLinkValue.isNullOrBlank()) { return false diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2Activity.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2Activity.kt index fecd2942..d408c610 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2Activity.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2Activity.kt @@ -49,6 +49,7 @@ import kr.co.vividnext.sodalive.settings.notification.NotificationSettingsDialog import kr.co.vividnext.sodalive.user.login.LoginActivity import kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivity import kr.co.vividnext.sodalive.v2.main.chat.ChatMainFragment +import kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomActivity import kr.co.vividnext.sodalive.v2.main.chat.model.ChatRoomFilter import kr.co.vividnext.sodalive.v2.main.home.HomeMainFragment import kotlinx.coroutines.Job @@ -549,6 +550,8 @@ class MainV2Activity : BaseActivity(ActivityMainV2Binding } private fun executeBundleRoute(bundle: Bundle): Boolean { + val roomId = bundle.getString("room_id")?.toLongOrNull() + ?: bundle.getLong(Constants.EXTRA_ROOM_ID).takeIf { it > 0 } val channelId = bundle.getString("channel_id")?.toLongOrNull() ?: bundle.getLong(Constants.EXTRA_USER_ID).takeIf { it > 0 } val messageId = bundle.getString("message_id")?.toLongOrNull() @@ -562,6 +565,11 @@ class MainV2Activity : BaseActivity(ActivityMainV2Binding val communityPostId = bundle.getString(Constants.EXTRA_COMMUNITY_POST_ID)?.toLongOrNull() ?: bundle.getLong(Constants.EXTRA_COMMUNITY_POST_ID).takeIf { it > 0 } + if (isUserCreatorChat(bundle) && roomId != null && roomId > 0) { + startActivity(DmChatRoomActivity.newIntentByRoomId(applicationContext, roomId)) + return true + } + when { channelId != null && channelId > 0 -> { startActivity( @@ -607,6 +615,10 @@ class MainV2Activity : BaseActivity(ActivityMainV2Binding return !deepLinkValue.isNullOrBlank() && routeByDeepLinkValue(deepLinkValue, deepLinkValueId) } + private fun isUserCreatorChat(bundle: Bundle): Boolean { + return bundle.getString("chat_type") == "USER_CREATOR" + } + private fun routeByDeepLinkValue(deepLinkValue: String, deepLinkValueId: Long?): Boolean { return when (deepLinkValue.lowercase(Locale.ROOT)) { "series" -> { diff --git a/app/src/test/java/kr/co/vividnext/sodalive/main/DeepLinkActivitySourceTest.kt b/app/src/test/java/kr/co/vividnext/sodalive/main/DeepLinkActivitySourceTest.kt new file mode 100644 index 00000000..34a90bfb --- /dev/null +++ b/app/src/test/java/kr/co/vividnext/sodalive/main/DeepLinkActivitySourceTest.kt @@ -0,0 +1,49 @@ +package kr.co.vividnext.sodalive.main + +import org.junit.Assert.assertTrue +import org.junit.Test +import java.io.File + +class DeepLinkActivitySourceTest { + + @Test + fun `DeepLinkActivity는 USER_CREATOR push room_id를 DM 채팅방으로 라우팅한다`() { + val source = projectFile("app/src/main/java/kr/co/vividnext/sodalive/main/DeepLinkActivity.kt").readText() + + assertTrue(source.contains("import kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomActivity")) + assertTrue(source.contains("copyString(\"chat_type\")")) + assertTrue(source.contains("private fun isUserCreatorChat(bundle: Bundle): Boolean")) + assertTrue(source.contains("bundle.getString(\"chat_type\") == \"USER_CREATOR\"")) + assertTrue(source.contains("DmChatRoomActivity.newIntentByRoomId(applicationContext, roomId)")) + assertTrue(source.contains("if (isUserCreatorChat(bundle) && roomId != null && roomId > 0)")) + } + + @Test + fun `DeepLinkActivity는 URL query chat_type도 deepLinkExtras에 보존한다`() { + val source = projectFile("app/src/main/java/kr/co/vividnext/sodalive/main/DeepLinkActivity.kt").readText() + val queryCopyStart = source.indexOf("if (data != null)") + val extrasNormalizeStart = source.indexOf("extras.getString(\"postId\")", queryCopyStart) + val queryCopySource = source.substring(queryCopyStart, extrasNormalizeStart) + + assertTrue(queryCopySource.contains("putQuery(\"chat_type\")")) + assertTrue(queryCopySource.contains("putQuery(\"room_id\")")) + } + + @Test + fun `USER_CREATOR push는 LiveRoom foreground confirm broadcast보다 먼저 foreground route를 시도한다`() { + val source = projectFile("app/src/main/java/kr/co/vividnext/sodalive/main/DeepLinkActivity.kt").readText() + + val dmRouteIndex = source.indexOf("routeForegroundDeepLink(deepLinkExtras)") + val liveRoomBroadcastIndex = source.indexOf("Constants.ACTION_LIVE_ROOM_DEEPLINK_CONFIRM") + + assertTrue(dmRouteIndex >= 0) + assertTrue(liveRoomBroadcastIndex >= 0) + assertTrue(dmRouteIndex < liveRoomBroadcastIndex) + } + + private fun projectFile(relativePath: String): File { + val candidates = listOf(File(relativePath), File("../$relativePath")) + return candidates.firstOrNull { it.exists() } + ?: error("Project file not found: $relativePath") + } +} diff --git a/app/src/test/java/kr/co/vividnext/sodalive/v2/main/MainV2ActivitySourceTest.kt b/app/src/test/java/kr/co/vividnext/sodalive/v2/main/MainV2ActivitySourceTest.kt new file mode 100644 index 00000000..20f6f453 --- /dev/null +++ b/app/src/test/java/kr/co/vividnext/sodalive/v2/main/MainV2ActivitySourceTest.kt @@ -0,0 +1,26 @@ +package kr.co.vividnext.sodalive.v2.main + +import org.junit.Assert.assertTrue +import org.junit.Test +import java.io.File + +class MainV2ActivitySourceTest { + + @Test + fun `MainV2Activity는 USER_CREATOR push room_id를 DM 채팅방으로 라우팅한다`() { + val source = projectFile("app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2Activity.kt").readText() + + assertTrue(source.contains("import kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomActivity")) + assertTrue(source.contains("private fun isUserCreatorChat(bundle: Bundle): Boolean")) + assertTrue(source.contains("bundle.getString(\"chat_type\") == \"USER_CREATOR\"")) + assertTrue(source.contains("val roomId = bundle.getString(\"room_id\")?.toLongOrNull()")) + assertTrue(source.contains("DmChatRoomActivity.newIntentByRoomId(applicationContext, roomId)")) + assertTrue(source.contains("if (isUserCreatorChat(bundle) && roomId != null && roomId > 0)")) + } + + private fun projectFile(relativePath: String): File { + val candidates = listOf(File(relativePath), File("../$relativePath")) + return candidates.firstOrNull { it.exists() } + ?: error("Project file not found: $relativePath") + } +}