feat(creator): 팬Talk 쓰기 화면을 연결한다

This commit is contained in:
Yu Sung
2026-07-06 22:54:20 +09:00
parent d129583d3b
commit 9c4c304fc6
11 changed files with 716 additions and 10 deletions

View File

@@ -0,0 +1,130 @@
import Foundation
import Combine
final class CreatorChannelFanTalkWriteViewModel: ObservableObject {
enum Mode {
case write
case modify(fanTalkId: Int, initialContent: String)
var initialContent: String {
if case .modify(_, let initialContent) = self {
return initialContent
}
return ""
}
}
private let repository = ExplorerRepository()
private var subscription = Set<AnyCancellable>()
let creatorId: Int
let mode: Mode
@Published var content: String
@Published var isLoading = false
@Published var errorMessage = ""
@Published var isShowPopup = false
@Published var shouldShowExitModal = false
let maxContentCount = 500
var canSend: Bool {
content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false
}
init(creatorId: Int, mode: Mode) {
self.creatorId = creatorId
self.mode = mode
content = mode.initialContent
}
func handleCancel() -> Bool {
guard canSend else { return true }
shouldShowExitModal = true
return false
}
func submit(onSuccess: @escaping () -> Void) {
guard canSend, isLoading == false else { return }
switch mode {
case .write:
writeCheers(onSuccess: onSuccess)
case .modify(let fanTalkId, _):
modifyCheers(fanTalkId: fanTalkId, onSuccess: onSuccess)
}
}
private func writeCheers(onSuccess: @escaping () -> Void) {
isLoading = true
repository.writeCheers(parentCheersId: nil, creatorId: creatorId, content: content)
.sink { [weak self] result in
guard let self else { return }
switch result {
case .finished:
DEBUG_LOG("finish")
case .failure(let error):
ERROR_LOG(error.localizedDescription)
self.applyFailureState()
}
} receiveValue: { [weak self] response in
self?.handleMutationResponse(response.data, onSuccess: onSuccess)
}
.store(in: &subscription)
}
private func modifyCheers(fanTalkId: Int, onSuccess: @escaping () -> Void) {
guard fanTalkId > 0 else {
errorMessage = I18n.Common.commonError
isShowPopup = true
return
}
isLoading = true
repository.modifyCheers(cheersId: fanTalkId, content: content, isActive: nil)
.sink { [weak self] result in
guard let self else { return }
switch result {
case .finished:
DEBUG_LOG("finish")
case .failure(let error):
ERROR_LOG(error.localizedDescription)
self.applyFailureState()
}
} receiveValue: { [weak self] response in
self?.handleMutationResponse(response.data, onSuccess: onSuccess)
}
.store(in: &subscription)
}
private func handleMutationResponse(_ data: Data, onSuccess: @escaping () -> Void) {
isLoading = false
do {
let decoded = try JSONDecoder().decode(ApiResponseWithoutData.self, from: data)
if decoded.success {
onSuccess()
} else {
errorMessage = decoded.message ?? I18n.Common.commonError
isShowPopup = true
}
} catch {
ERROR_LOG(error.localizedDescription)
errorMessage = I18n.Common.commonError
isShowPopup = true
}
}
private func applyFailureState() {
isLoading = false
errorMessage = I18n.Common.commonError
isShowPopup = true
}
}