From 643fb9fa8eb2b04b777a6a0966346c61e6ae55ca Mon Sep 17 00:00:00 2001 From: klaus Date: Thu, 9 Jul 2026 07:43:47 +0900 Subject: [PATCH] =?UTF-8?q?feat(creator-channel):=20FanTalk=20=EB=8B=B5?= =?UTF-8?q?=EA=B8=80=20API=20=EC=9D=91=EB=8B=B5=EC=9D=84=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vividnext/sodalive/explorer/ExplorerApi.kt | 5 +++-- .../channel/data/CreatorChannelRepository.kt | 17 +++++++++++++++++ .../model/CreatorChannelFanTalkMappers.kt | 15 +++++++++++++-- .../fantalk/CreatorChannelFanTalkActionTest.kt | 3 ++- .../CreatorChannelFanTalkWriteViewModelTest.kt | 5 +++-- 5 files changed, 38 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/kr/co/vividnext/sodalive/explorer/ExplorerApi.kt b/app/src/main/java/kr/co/vividnext/sodalive/explorer/ExplorerApi.kt index 97958610..a62d8939 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/explorer/ExplorerApi.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/explorer/ExplorerApi.kt @@ -13,6 +13,7 @@ import kr.co.vividnext.sodalive.explorer.profile.channel_donation.PostChannelDon import kr.co.vividnext.sodalive.explorer.profile.donation.GetDonationAllResponse import kr.co.vividnext.sodalive.explorer.profile.follow.GetFollowerListResponse import kr.co.vividnext.sodalive.live.room.detail.GetRoomDetailUser +import kr.co.vividnext.sodalive.v2.creator.channel.fantalk.data.CreatorChannelFanTalkReplyResponse import retrofit2.http.Body import retrofit2.http.GET import retrofit2.http.Header @@ -73,13 +74,13 @@ interface ExplorerApi { fun writeCheers( @Body request: PostWriteCheersRequest, @Header("Authorization") authHeader: String - ): Single> + ): Single> @PUT("/explorer/profile/cheers") fun modifyCheers( @Body request: PutModifyCheersRequest, @Header("Authorization") authHeader: String - ): Single> + ): Single> @POST("/explorer/profile/channel-donation") fun postChannelDonation( diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/data/CreatorChannelRepository.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/data/CreatorChannelRepository.kt index 9e3217a6..a41961e9 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/data/CreatorChannelRepository.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/data/CreatorChannelRepository.kt @@ -196,4 +196,21 @@ class CreatorChannelRepository( content = content, token = token ) + + fun writeFanTalkReply(fanTalkId: Long, creatorId: Long, content: String, token: String) = explorerRepository.writeCheers( + parentCheersId = fanTalkId, + creatorId = creatorId, + content = content, + token = token + ) + + fun modifyFanTalkReply(replyFanTalkId: Long, content: String, token: String) = explorerRepository.modifyCheers( + request = PutModifyCheersRequest(cheersId = replyFanTalkId, content = content), + token = token + ) + + fun deleteFanTalkReply(replyFanTalkId: Long, token: String) = explorerRepository.modifyCheers( + request = PutModifyCheersRequest(cheersId = replyFanTalkId, isActive = false), + token = token + ) } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/model/CreatorChannelFanTalkMappers.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/model/CreatorChannelFanTalkMappers.kt index 060f2156..d6fad5eb 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/model/CreatorChannelFanTalkMappers.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/model/CreatorChannelFanTalkMappers.kt @@ -23,11 +23,22 @@ private fun CreatorChannelFanTalkResponse.toFanTalkUiModel( writerProfileImageUrl = writerProfileImageUrl, content = content, createdAtText = relativeTimeTextFormatter.format(createdAtUtc), - reply = creatorReplies.firstOrNull()?.toReplyUiModel(relativeTimeTextFormatter), + reply = creatorReplies.orEmpty().firstOrNull()?.toFanTalkReplyUiModel(relativeTimeTextFormatter), rightAction = toRightAction(isOwner = isOwner, currentUserId = currentUserId) ) -private fun CreatorChannelFanTalkReplyResponse.toReplyUiModel( +fun CreatorChannelFanTalkReplyResponse.toFanTalkReplyUiModel( + relativeTimeTextFormatter: UtcRelativeTimeTextFormatter +) = CreatorChannelFanTalkReplyUiModel( + fanTalkId = fanTalkId, + writerId = writerId, + writerNickname = writerNickname, + writerProfileImageUrl = writerProfileImageUrl, + content = content, + createdAtText = relativeTimeTextFormatter.format(createdAtUtc) +) + +fun CreatorChannelFanTalkResponse.toFanTalkReplyUiModel( relativeTimeTextFormatter: UtcRelativeTimeTextFormatter ) = CreatorChannelFanTalkReplyUiModel( fanTalkId = fanTalkId, diff --git a/app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/CreatorChannelFanTalkActionTest.kt b/app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/CreatorChannelFanTalkActionTest.kt index 91639526..ea7fa129 100644 --- a/app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/CreatorChannelFanTalkActionTest.kt +++ b/app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/CreatorChannelFanTalkActionTest.kt @@ -16,6 +16,7 @@ import kr.co.vividnext.sodalive.common.ApiResponse import kr.co.vividnext.sodalive.common.AndroidUtcRelativeTimeTextFormatter import kr.co.vividnext.sodalive.common.SharedPreferenceManager import kr.co.vividnext.sodalive.v2.creator.channel.data.CreatorChannelRepository +import kr.co.vividnext.sodalive.v2.creator.channel.fantalk.data.CreatorChannelFanTalkReplyResponse import kr.co.vividnext.sodalive.v2.creator.channel.fantalk.data.CreatorChannelFanTalkResponse import kr.co.vividnext.sodalive.v2.creator.channel.fantalk.data.CreatorChannelFanTalkTabResponse import org.junit.After @@ -104,7 +105,7 @@ class CreatorChannelFanTalkActionTest { Single.just(ApiResponse(true, fanTalkResponse(ids = listOf(2L)), null)) ) whenever(repository.deleteFanTalk(1L, "Bearer test-token")) - .thenReturn(Single.just(ApiResponse(true, Any(), "deleted"))) + .thenReturn(Single.just(ApiResponse(true, null, "deleted"))) viewModel.loadFanTalks(100L, isOwner = false) viewModel.deleteFanTalk(1L) diff --git a/app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/write/CreatorChannelFanTalkWriteViewModelTest.kt b/app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/write/CreatorChannelFanTalkWriteViewModelTest.kt index ba64da50..747322d0 100644 --- a/app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/write/CreatorChannelFanTalkWriteViewModelTest.kt +++ b/app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/write/CreatorChannelFanTalkWriteViewModelTest.kt @@ -13,6 +13,7 @@ import io.reactivex.rxjava3.schedulers.Schedulers import kr.co.vividnext.sodalive.common.ApiResponse import kr.co.vividnext.sodalive.common.SharedPreferenceManager import kr.co.vividnext.sodalive.v2.creator.channel.data.CreatorChannelRepository +import kr.co.vividnext.sodalive.v2.creator.channel.fantalk.data.CreatorChannelFanTalkReplyResponse import org.junit.After import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse @@ -106,7 +107,7 @@ class CreatorChannelFanTalkWriteViewModelTest { @Test fun `활성 상태에서 submit하면 trim content와 토큰으로 FanTalk 등록 API를 호출한다`() { whenever(repository.writeFanTalk(100L, "응원합니다", "Bearer test-token")) - .thenReturn(Single.just(ApiResponse(true, null, null))) + .thenReturn(Single.just(ApiResponse(true, null, null))) viewModel.onContentChanged(" 응원합니다 ") viewModel.submit(creatorId = 100L) @@ -132,7 +133,7 @@ class CreatorChannelFanTalkWriteViewModelTest { @Test fun `등록 실패 시 입력값을 유지하고 서버 message를 우선 toast로 emit한다`() { whenever(repository.writeFanTalk(100L, "응원합니다", "Bearer test-token")) - .thenReturn(Single.just(ApiResponse(false, null, "서버 실패"))) + .thenReturn(Single.just(ApiResponse(false, null, "서버 실패"))) viewModel.onContentChanged(" 응원합니다 ") viewModel.submit(creatorId = 100L)