// // LiveViewModel.swift // SodaLive // // Created by klaus on 2023/08/09. // import Foundation import Combine final class LiveViewModel: ObservableObject { private let repository = LiveRepository() private let eventRepository = EventRepository() private let liveRecommendRepository = LiveRecommendRepository() private var subscription = Set() @Published private(set) var eventBannerItems = [EventItem]() @Published private(set) var liveNowItems = [GetRoomListResponse]() @Published private(set) var liveReservationItems = [GetRoomListResponse]() @Published private(set) var recommendLiveItems: [GetRecommendLiveResponse] = [] @Published private(set) var recommendChannelItems: [GetRecommendChannelResponse] = [] @Published private(set) var followedChannelItems: [GetRecommendChannelResponse] = [] @Published var errorMessage = "" @Published var isShowPopup = false @Published var isRefresh = false @Published var isLoading = false @Published var isRecommendLiveLoading = false @Published var isRecommendChannelLoading = false @Published var isFollowedChannelLoading = false @Published var paymentDialogTitle = "" @Published var paymentDialogDesc = "" @Published var isShowPaymentDialog = false @Published var paymentDialogConfirmAction = {} @Published var paymentDialogConfirmTitle = "" @Published var secretOrPasswordDialogCoin = 0 @Published var passwordDialogConfirmAction: (Int) -> Void = { _ in } @Published var isShowPasswordDialog = false @Published var isFollowingList = UserDefaults.bool(forKey: .isFollowedChannel) { didSet { UserDefaults.set(isFollowingList, forKey: .isFollowedChannel) } } let paymentDialogCancelTitle = "취소" var page = 1 var isLast = false private let pageSize = 10 func hidePopup() { isShowPaymentDialog = false isShowPasswordDialog = false paymentDialogTitle = "" paymentDialogDesc = "" paymentDialogConfirmAction = {} secretOrPasswordDialogCoin = 0 passwordDialogConfirmAction = { _ in } } func getSummary() { getFollowedChannelList() getRecommendChannelList() getRecommendLive() isLoading = true eventBannerItems.removeAll() liveNowItems.removeAll() liveReservationItems.removeAll() let liveNow = repository.roomList( request: GetRoomListRequest( timezone: TimeZone.current.identifier, dateString: nil, status: .NOW, page: 1, size: 10 ) ) let liveReservation = repository.roomList( request: GetRoomListRequest( timezone: TimeZone.current.identifier, dateString: nil, status: .RESERVATION, page: 1, size: 10 ) ) let event = eventRepository.getEvents() Publishers .CombineLatest3(liveNow, liveReservation, event) .sink { result in switch result { case .finished: DEBUG_LOG("finish") case .failure(let error): ERROR_LOG(error.localizedDescription) } } receiveValue: { (now, reservation, eventResponse) in let nowData = now.data let reservationData = reservation.data let eventData = eventResponse.data let jsonDecoder = JSONDecoder() do { let nowDecoded = try jsonDecoder.decode(ApiResponse<[GetRoomListResponse]>.self, from: nowData) if let data = nowDecoded.data, nowDecoded.success { self.liveNowItems.removeAll() self.liveNowItems.append(contentsOf: data) } else { if let message = nowDecoded.message { self.errorMessage = message } else { self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." } self.isShowPopup = true } } catch { self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self.isShowPopup = true } do { let reservationDecoded = try jsonDecoder.decode(ApiResponse<[GetRoomListResponse]>.self, from: reservationData) if let data = reservationDecoded.data, reservationDecoded.success { self.liveReservationItems.removeAll() self.liveReservationItems.append(contentsOf: data) } else { if let message = reservationDecoded.message { self.errorMessage = message } else { self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." } self.isShowPopup = true } } catch { self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self.isShowPopup = true } do { let eventDecoded = try jsonDecoder.decode(ApiResponse.self, from: eventData) if let data = eventDecoded.data, eventDecoded.success { self.eventBannerItems.removeAll() self.eventBannerItems.append(contentsOf: data.eventList) } else { if let message = eventDecoded.message { self.errorMessage = message } else { self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." } self.isShowPopup = true } } catch { self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self.isShowPopup = true } self.isLoading = false self.isRefresh = false } .store(in: &subscription) } func enterRoom(roomId: Int, onSuccess: (() -> Void)? = nil, password: Int? = nil) { isLoading = true let request = EnterOrQuitLiveRoomRequest(roomId: roomId, password: password) repository.enterRoom(request: request) .sink { result in switch result { case .finished: DEBUG_LOG("finish") case .failure(let error): ERROR_LOG(error.localizedDescription) } } receiveValue: { [unowned self] response in self.isLoading = false let responseData = response.data do { let jsonDecoder = JSONDecoder() let decoded = try jsonDecoder.decode(ApiResponseWithoutData.self, from: responseData) if decoded.success { AppState.shared.roomId = roomId if let onSuccess = onSuccess { onSuccess() } else { if roomId > 0 { AppState.shared.isShowPlayer = true } } } else { if let message = decoded.message { self.errorMessage = message } else { self.errorMessage = "라이브에 입장하지 못했습니다.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." } self.isShowPopup = true } } catch { self.errorMessage = "라이브에 입장하지 못했습니다.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self.isShowPopup = true } } .store(in: &subscription) } func startLive(roomId: Int) { isLoading = true repository.startLive(roomId: roomId) .sink { result in switch result { case .finished: DEBUG_LOG("finish") case .failure(let error): ERROR_LOG(error.localizedDescription) } } receiveValue: { [unowned self] response in self.isLoading = false let responseData = response.data do { let jsonDecoder = JSONDecoder() let decoded = try jsonDecoder.decode(ApiResponseWithoutData.self, from: responseData) if decoded.success { getSummary() enterRoom(roomId: roomId) } else { if let message = decoded.message { self.errorMessage = message } else { self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." } self.isShowPopup = true } } catch { self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self.isShowPopup = true } } .store(in: &subscription) } private func getFollowedChannelList() { followedChannelItems.removeAll() isFollowedChannelLoading = true liveRecommendRepository.getFollowedChannelList() .sink { result in switch result { case .finished: DEBUG_LOG("finish") case .failure(let error): ERROR_LOG(error.localizedDescription) } } receiveValue: { [unowned self] response in self.isFollowedChannelLoading = false let responseData = response.data do { let jsonDecoder = JSONDecoder() let decoded = try jsonDecoder.decode(ApiResponse<[GetRecommendChannelResponse]>.self, from: responseData) if let data = decoded.data, decoded.success { self.followedChannelItems.append(contentsOf: data) } else { if let message = decoded.message { self.errorMessage = message } else { self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." } self.isShowPopup = true } } catch { self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self.isShowPopup = true } } .store(in: &subscription) } private func getRecommendChannelList() { recommendChannelItems.removeAll() isRecommendChannelLoading = true liveRecommendRepository.getRecommendChannelList() .sink { result in switch result { case .finished: DEBUG_LOG("finish") case .failure(let error): ERROR_LOG(error.localizedDescription) } } receiveValue: { [unowned self] response in self.isRecommendChannelLoading = false let responseData = response.data do { let jsonDecoder = JSONDecoder() let decoded = try jsonDecoder.decode(ApiResponse<[GetRecommendChannelResponse]>.self, from: responseData) if let data = decoded.data, decoded.success { self.recommendChannelItems.append(contentsOf: data) } else { if let message = decoded.message { self.errorMessage = message } else { self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." } self.isShowPopup = true } } catch { self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self.isShowPopup = true } } .store(in: &subscription) } private func getRecommendLive() { recommendLiveItems.removeAll() isRecommendLiveLoading = true liveRecommendRepository.getRecommendLive() .sink { result in switch result { case .finished: DEBUG_LOG("finish") case .failure(let error): ERROR_LOG(error.localizedDescription) } } receiveValue: { [unowned self] response in self.isRecommendLiveLoading = false let responseData = response.data do { let jsonDecoder = JSONDecoder() let decoded = try jsonDecoder.decode(ApiResponse<[GetRecommendLiveResponse]>.self, from: responseData) if let data = decoded.data, decoded.success { self.recommendLiveItems.append(contentsOf: data) } else { if let message = decoded.message { self.errorMessage = message } else { self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." } self.isShowPopup = true } } catch { self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self.isShowPopup = true } } .store(in: &subscription) } }