From f98f625200e46611ed97be526e717527bab49527 Mon Sep 17 00:00:00 2001 From: Yu Sung Date: Thu, 4 Sep 2025 06:57:02 +0900 Subject: [PATCH] =?UTF-8?q?feat(chat-room):=20=EC=B1=84=ED=8C=85=20?= =?UTF-8?q?=EC=BF=BC=ED=84=B0=20=EA=B5=AC=EB=A7=A4=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Chat/Talk/Room/ChatRoomRepository.swift | 4 ++ .../Sources/Chat/Talk/Room/ChatRoomView.swift | 3 +- .../Chat/Talk/Room/ChatRoomViewModel.swift | 66 +++++++++++++++++++ SodaLive/Sources/Chat/Talk/TalkApi.swift | 10 +++ 4 files changed, 82 insertions(+), 1 deletion(-) diff --git a/SodaLive/Sources/Chat/Talk/Room/ChatRoomRepository.swift b/SodaLive/Sources/Chat/Talk/Room/ChatRoomRepository.swift index 712fe4c..9c9f8b9 100644 --- a/SodaLive/Sources/Chat/Talk/Room/ChatRoomRepository.swift +++ b/SodaLive/Sources/Chat/Talk/Room/ChatRoomRepository.swift @@ -54,4 +54,8 @@ class ChatRoomRepository { func getChatQuotaStatus() -> AnyPublisher { return talkApi.requestPublisher(.getChatQuotaStatus) } + + func purchaseChatQuota() -> AnyPublisher { + return talkApi.requestPublisher(.purchaseChatQuota(request: ChatQuotaPurchaseRequest())) + } } diff --git a/SodaLive/Sources/Chat/Talk/Room/ChatRoomView.swift b/SodaLive/Sources/Chat/Talk/Room/ChatRoomView.swift index 69b9db2..e3a1f5f 100644 --- a/SodaLive/Sources/Chat/Talk/Room/ChatRoomView.swift +++ b/SodaLive/Sources/Chat/Talk/Room/ChatRoomView.swift @@ -132,7 +132,7 @@ struct ChatRoomView: View { if viewModel.showQuotaNoticeView { ChatQuotaNoticeItemView(remainingTime: viewModel.countdownText) { - + viewModel.purchaseChatQuota() } .id(viewModel.messages.count) .padding(.bottom, 12) @@ -230,6 +230,7 @@ struct ChatRoomView: View { } } .onAppear { + viewModel.getMemberInfo() viewModel.enterRoom(roomId: roomId) } .onDisappear { diff --git a/SodaLive/Sources/Chat/Talk/Room/ChatRoomViewModel.swift b/SodaLive/Sources/Chat/Talk/Room/ChatRoomViewModel.swift index f0917c8..63cfce0 100644 --- a/SodaLive/Sources/Chat/Talk/Room/ChatRoomViewModel.swift +++ b/SodaLive/Sources/Chat/Talk/Room/ChatRoomViewModel.swift @@ -163,6 +163,33 @@ final class ChatRoomViewModel: ObservableObject { .store(in: &subscription) } + func getMemberInfo() { + userRepository.getMemberInfo() + .sink { result in + switch result { + case .finished: + DEBUG_LOG("finish") + case .failure(let error): + ERROR_LOG(error.localizedDescription) + } + } receiveValue: { response in + let responseData = response.data + + do { + let jsonDecoder = JSONDecoder() + let decoded = try jsonDecoder.decode(ApiResponse.self, from: responseData) + + if let data = decoded.data, decoded.success { + UserDefaults.set(data.can, forKey: .can) + UserDefaults.set(data.point, forKey: .point) + } + } catch { + print(error) + } + } + .store(in: &subscription) + } + func purchaseChatMessage() { guard let selectedMessage = selectedMessage else { return @@ -212,7 +239,46 @@ final class ChatRoomViewModel: ObservableObject { } func purchaseChatQuota() { + isLoading = true + repository.purchaseChatQuota() + .sink { result in + switch result { + case .finished: + DEBUG_LOG("finish") + case .failure(let error): + ERROR_LOG(error.localizedDescription) + } + } receiveValue: { [weak self] response in + let responseData = response.data + + do { + let jsonDecoder = JSONDecoder() + let decoded = try jsonDecoder.decode(ApiResponse.self, from: responseData) + + if let data = decoded.data, decoded.success { + self?.updateQuota(totalRemaining: data.totalRemaining, nextRechargeAtEpoch: data.nextRechargeAtEpoch) + + let can = UserDefaults.int(forKey: .can) + UserDefaults.set(can - 30, forKey: .can) + } else { + if let message = decoded.message { + self?.errorMessage = message + } else { + self?.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." + } + + self?.isShowPopup = true + } + + self?.isLoading = false + } catch { + self?.isLoading = false + self?.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." + self?.isShowPopup = true + } + } + .store(in: &subscription) } private func checkQuotaStatus() { diff --git a/SodaLive/Sources/Chat/Talk/TalkApi.swift b/SodaLive/Sources/Chat/Talk/TalkApi.swift index fb60492..914e30b 100644 --- a/SodaLive/Sources/Chat/Talk/TalkApi.swift +++ b/SodaLive/Sources/Chat/Talk/TalkApi.swift @@ -16,6 +16,7 @@ enum TalkApi { case getChatRoomMessages(roomId: Int, cursor: Int?, limit: Int) case getChatQuotaStatus + case purchaseChatQuota(request: ChatQuotaPurchaseRequest) case purchaseMessage(roomId: Int, messageId: Int64, request: ChatMessagePurchaseRequest) } @@ -43,6 +44,9 @@ extension TalkApi: TargetType { case .getChatQuotaStatus: return "/api/chat/quota/me" + case .purchaseChatQuota: + return "/api/chat/quota/purchase" + case .purchaseMessage(let roomId, let messageId, _): return "/api/chat/room/\(roomId)/messages/\(messageId)/purchase" } @@ -68,6 +72,9 @@ extension TalkApi: TargetType { case .getChatQuotaStatus: return .get + case .purchaseChatQuota: + return .post + case .purchaseMessage: return .post } @@ -111,6 +118,9 @@ extension TalkApi: TargetType { case .getChatQuotaStatus: return .requestPlain + case .purchaseChatQuota(let request): + return .requestJSONEncodable(request) + case .purchaseMessage(_, _, let request): return .requestJSONEncodable(request) }