import Foundation import Combine final class CreatorChannelViewModel: ObservableObject { private let repository = CreatorChannelHomeRepository() private let userRepository = UserRepository() private var subscription = Set() @Published var isLoading = false @Published var response: CreatorChannelHomeResponse? @Published var hasLoaded = false @Published var selectedTab: CreatorChannelTab = .home @Published var isApiFailedPlaceholderVisible = false @Published var errorMessage = "" @Published var isShowPopup = false func fetchHome(creatorId: Int) { isLoading = true isApiFailedPlaceholderVisible = false repository.getHome(creatorId: creatorId) .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.applyApiFailedPlaceholderState() } } receiveValue: { [weak self] response in guard let self else { return } do { if let jsonString = String(data: response.data, encoding: .utf8) { DEBUG_LOG("CreatorChannelHome raw response: \(jsonString)") } let jsonDecoder = JSONDecoder() let decoded = try jsonDecoder.decode(ApiResponse.self, from: response.data) if let data = decoded.data, decoded.success { self.response = data self.selectedTab = .home self.isApiFailedPlaceholderVisible = false } else { if let message = decoded.message { ERROR_LOG(message) } self.applyApiFailedPlaceholderState() } } catch { ERROR_LOG(error.localizedDescription) print(error) self.applyApiFailedPlaceholderState() } self.hasLoaded = true self.isLoading = false } .store(in: &subscription) } func creatorFollow(follow: Bool = true, notify: Bool = true) { guard let creatorId = response?.creator.creatorId else { return } isLoading = true userRepository.creatorFollow(creatorId: creatorId, follow: follow, notify: notify) .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.isLoading = false } } receiveValue: { [weak self] response in guard let self else { return } do { let jsonDecoder = JSONDecoder() let decoded = try jsonDecoder.decode(ApiResponseWithoutData.self, from: response.data) if decoded.success { self.updateCreatorFollowState(isFollow: follow, isNotify: notify) } else { self.errorMessage = decoded.message ?? I18n.Common.commonError self.isShowPopup = true } } catch { ERROR_LOG(error.localizedDescription) self.errorMessage = I18n.Common.commonError self.isShowPopup = true } self.isLoading = false } .store(in: &subscription) } private func applyApiFailedPlaceholderState() { response = nil isApiFailedPlaceholderVisible = true hasLoaded = true isLoading = false } private func updateCreatorFollowState(isFollow: Bool, isNotify: Bool) { response?.creator.isFollow = isFollow response?.creator.isNotify = isNotify } }