// // ContentDetailViewModel.swift // SodaLive // // Created by klaus on 2023/08/11. // import Foundation import Combine import FirebaseDynamicLinks final class ContentDetailViewModel: ObservableObject { private let repository = ContentRepository() private let reportRepository = ReportRepository() private var userRepository = UserRepository() private var subscription = Set() @Published var errorMessage = "" @Published var isShowPopup = false @Published var isLoading = false @Published var isShowPreviewAlert = false @Published var isExpandDescription = false @Published var isShowDonationPopup = false @Published var isShowShareView = false @Published var shareMessage = "" @Published private(set) var audioContent: GetAudioContentDetailResponse? @Published var orderType: OrderType? @Published var isShowReportMenu = false @Published var isShowReportView = false @Published var isShowDeleteConfirm = false var contentId: Int = 0 { didSet { getAudioContentDetail() } } func getAudioContentDetail() { audioContent = nil isLoading = true repository.getAudioContentDetail(audioContentId: contentId) .sink { result in switch result { case .finished: DEBUG_LOG("finish") case .failure(let error): ERROR_LOG(error.localizedDescription) } } receiveValue: { [unowned 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.audioContent = data } else { if let message = decoded.message { self.errorMessage = message } else { self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." } self.isShowPopup = true } } catch { print(error) self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self.isShowPopup = true } self.isLoading = false } .store(in: &subscription) } func creatorFollow(userId: Int) { isLoading = true userRepository.creatorFollow(creatorId: userId) .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 { self.getAudioContentDetail() } 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 creatorUnFollow(userId: Int) { isLoading = true userRepository.creatorUnFollow(creatorId: userId) .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 { self.getAudioContentDetail() } 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 likeContent() { isLoading = true repository.likeContent(audioContentId: contentId) .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(ApiResponse.self, from: responseData) if decoded.success { self.getAudioContentDetail() } 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 shareAudioContent(contentImage: String, contentTitle: String) { isLoading = true guard let link = URL(string: "https://yozm.day/?audio_content_id=\(contentId)") else { return } let dynamicLinksDomainURIPrefix = "https://yozm.page.link" guard let linkBuilder = DynamicLinkComponents(link: link, domainURIPrefix: dynamicLinksDomainURIPrefix) else { self.errorMessage = "공유링크를 생성하지 못했습니다.\n다시 시도해 주세요." self.isShowPopup = true return } linkBuilder.iOSParameters = DynamicLinkIOSParameters(bundleID: "kr.co.vividnext.yozm") linkBuilder.iOSParameters?.appStoreID = "1630284226" linkBuilder.androidParameters = DynamicLinkAndroidParameters(packageName: "kr.co.vividnext.yozm") let socialMetaTagParameters = DynamicLinkSocialMetaTagParameters() socialMetaTagParameters.title = contentTitle socialMetaTagParameters.descriptionText = "지금 요즘라이브에서 이 콘텐츠 감상하기" socialMetaTagParameters.imageURL = URL(string: contentImage) linkBuilder.socialMetaTagParameters = socialMetaTagParameters guard let longDynamicLink = linkBuilder.url else { self.errorMessage = "공유링크를 생성하지 못했습니다.\n다시 시도해 주세요." self.isShowPopup = true return } DEBUG_LOG("The long URL is: \(longDynamicLink)") DynamicLinkComponents.shortenURL(longDynamicLink, options: nil) { [unowned self] url, warnings, error in let shortUrl = url?.absoluteString let urlString = shortUrl != nil ? shortUrl! : longDynamicLink.absoluteString self.isLoading = false self.shareMessage = urlString self.isShowShareView = true } } func registerComment(comment: String) { if comment.trimmingCharacters(in: .whitespaces).isEmpty { return } isLoading = true repository.registerComment(audioContentId: contentId, comment: comment) .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 { self.getAudioContentDetail() } 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 order(orderType: OrderType) { isShowPreviewAlert = false isLoading = true repository.orderAudioContent(audioContentId: contentId, orderType: orderType) .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 { self.orderType = nil self.errorMessage = "구매가 완료되었습니다." self.isShowPopup = true self.getAudioContentDetail() ContentPlayManager.shared.conditionalStopAudio(contentId: contentId) } 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 report(type: ReportType, audioContentId: Int? = nil, reason: String = "프로필 신고") { isLoading = true let request = ReportRequest(type: type, reason: reason, reportedMemberId: nil, cheersId: nil, audioContentId: audioContentId) reportRepository.report(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 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 deleteAudioContent(onSuccess: @escaping () -> Void) { isLoading = true repository.deleteAudioContent(audioContentId: contentId) .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 { self.orderType = nil self.errorMessage = "삭제되었습니다" self.isShowPopup = true onSuccess() } 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 donation(can: Int, comment: String) { if can <= 0 { self.errorMessage = "1코인 이상 후원하실 수 있습니다." self.isShowPopup = true } else if comment.trimmingCharacters(in: .whitespaces).isEmpty { self.errorMessage = "함께 보낼 메시지를 입력하세요." self.isShowPopup = true } else { isLoading = true repository.donation(contentId: contentId, can: can, comment: comment) .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 { UserDefaults.set(UserDefaults.int(forKey: .can) - can, forKey: .can) self.errorMessage = "\(can)코인을 후원하셨습니다." self.isShowPopup = true self.getAudioContentDetail() } 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) } } }