TSPurchaseVideoTimesVC.swift 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. //
  2. // TSPurchaseVideoTimesVC.swift
  3. // AIEmoji
  4. //
  5. // Created by 100Years on 2025/8/6.
  6. //
  7. import Combine
  8. import SwiftUI
  9. import SwiftUIX
  10. class TSPurchaseVideoTimesVM : ObservableObject{
  11. @Published var selectedType: PremiumPeriod = .purchase(.videoNum2)
  12. /// 订阅publisher
  13. let buyPublisher = PassthroughSubject<Bool,Never>()
  14. /// 订阅publisher
  15. let closePagePublisher = PassthroughSubject<Bool,Never>()
  16. }
  17. class TSPurchaseVideoTimesVC: TSBaseVC {
  18. var isShowAlertModel:Bool//是否以弹窗的样式展现
  19. init(isShowAlertModel: Bool) {
  20. self.isShowAlertModel = isShowAlertModel
  21. super.init()
  22. }
  23. @MainActor required init?(coder: NSCoder) {
  24. fatalError("init(coder:) has not been implemented")
  25. }
  26. var cancellabel: [AnyCancellable] = []
  27. var viewModel: TSPurchaseVideoTimesVM = .init()
  28. var buyPeriod:PremiumPeriod = .year
  29. var isHandlePurchaseStateChanged = false //是否处理购买状态变化
  30. lazy var fullVC: UIHostingController<TSPurchaseVideoTimesView> = {
  31. let vc = UIHostingController(rootView: TSPurchaseVideoTimesView(viewModel: viewModel))
  32. vc.view.backgroundColor = .clear
  33. return vc
  34. }()
  35. lazy var alertVC: UIHostingController<TSPurchaseVideoTimesAlertView> = {
  36. let vc = UIHostingController(rootView: TSPurchaseVideoTimesAlertView(viewModel: viewModel))
  37. vc.view.backgroundColor = .clear
  38. return vc
  39. }()
  40. override func createView() {
  41. if isShowAlertModel {
  42. setUpAlerView()
  43. }else{
  44. setUpFullView()
  45. }
  46. }
  47. override func dealThings() {
  48. addNotifaction()
  49. onPurchaseStateChanged()
  50. NotificationCenter.default.addObserver(forName: .kPurchasePrepared, object: nil, queue: OperationQueue.main) { [weak self] _ in
  51. guard let self = self else { return }
  52. viewModel.selectedType = viewModel.selectedType
  53. }
  54. }
  55. func addNotifaction() {
  56. viewModel.buyPublisher.receive(on: DispatchQueue.main).sink { [weak self] _ in
  57. guard let self = self else { return }
  58. isHandlePurchaseStateChanged = true
  59. PurchaseManager.default.pay(for: self.viewModel.selectedType)
  60. }.store(in: &cancellabel)
  61. viewModel.closePagePublisher.receive(on: DispatchQueue.main).sink { [weak self] _ in
  62. guard let self = self else { return }
  63. closePage()
  64. }.store(in: &cancellabel)
  65. }
  66. }
  67. extension TSPurchaseVideoTimesVC {
  68. func setUpFullView(){
  69. addNormalNavBarView()
  70. setPageTitle("")
  71. contentView.snp.updateConstraints { make in
  72. make.top.equalTo(0)
  73. }
  74. let bgColorView = UIView(frame: UIScreen.main.bounds)
  75. bgColorView.addGradientBg(colors: ["#13052C".uiCGColor,"#160B2C".uiCGColor],startPoint: CGPoint(x: 0.5, y: 0),endPoint: CGPoint(x: 0.5, y: 1.0))
  76. contentView.addSubview(bgColorView)
  77. contentView.addSubview(fullVC.view)
  78. fullVC.view.snp.makeConstraints { make in
  79. make.leading.trailing.bottom.top.equalToSuperview()
  80. }
  81. }
  82. }
  83. extension TSPurchaseVideoTimesVC {
  84. func setUpAlerView(){
  85. setNavBarViewHidden(true)
  86. self.view.backgroundColor = .black.withAlphaComponent(0.5)
  87. contentView.addSubview(alertVC.view)
  88. alertVC.view.snp.makeConstraints { make in
  89. make.leading.trailing.bottom.top.equalToSuperview()
  90. }
  91. }
  92. }
  93. extension TSPurchaseVideoTimesVC {
  94. func onPurchaseStateChanged(){
  95. PurchaseManager.default.onPurchaseStateChanged = { [weak self] manager,state,object in
  96. guard let self = self else { return }
  97. if isHandlePurchaseStateChanged == false {
  98. debugPrint("purchaseManager.onPurchaseStateChanged 不处理")
  99. return
  100. }
  101. DispatchQueue.main.async {
  102. switch state {
  103. case .none:
  104. break
  105. case .loading:
  106. TSToastShared.showLoading(text: "Getting price".localized,containerView: self.view)
  107. case .loadSuccess:
  108. TSToastShared.hideLoading()
  109. case .loadFail:
  110. TSToastShared.hideLoading()
  111. let message = "Failed to get the price, will automatically retry in 5 seconds".localized
  112. TSToastShared.showToast(text: message)
  113. DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
  114. PurchaseManager.default.requestProducts()
  115. }
  116. case .paying:
  117. TSToastShared.showLoading(text: "Purchasing now".localized,containerView: self.view)
  118. case .paySuccess:
  119. TSToastShared.hideLoading()
  120. var loadingText = "Congratulations on your purchase! You have %d video effect uses. Try now!".localized
  121. if let purchaseNum = self.viewModel.selectedType.purchaseNum {
  122. loadingText = String(format: "Congratulations on your purchase! You have %d video effect uses. Try now!".localized, purchaseNum)
  123. }
  124. debugPrint(loadingText)
  125. TSToastShared.showToast(text:loadingText)
  126. DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
  127. self.closePage()
  128. }
  129. case .payFail:
  130. TSToastShared.hideLoading()
  131. if let str = object as? String {
  132. TSToastShared.showToast(text: str)
  133. }
  134. case .restoreing:
  135. TSToastShared.showLoading(text: "Restoring now".localized,containerView: self.view)
  136. case .restoreSuccess:
  137. TSToastShared.hideLoading()
  138. var loadingText = "Congratulations on your purchase! You have %d video effect uses. Try now!".localized
  139. if let purchaseNum = self.viewModel.selectedType.purchaseNum {
  140. loadingText = String(format: "Congratulations on your purchase! You have %d video effect uses. Try now!".localized, purchaseNum)
  141. }
  142. debugPrint(loadingText)
  143. TSToastShared.showToast(text:loadingText)
  144. DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
  145. self.closePage()
  146. }
  147. case .restoreFail:
  148. TSToastShared.hideLoading()
  149. let loadingText = (object as? String) ?? "Failed to restore subscribe, please try again".localized
  150. debugPrint(loadingText)
  151. TSToastShared.showToast(text: loadingText)
  152. case .verifying:
  153. #if DEBUG
  154. TSToastShared.showLoading(text: "Verifying receipt...".localized,containerView: self.view)
  155. #endif
  156. case .verifySuccess:
  157. break
  158. case .verifyFail:
  159. #if DEBUG
  160. TSToastShared.hideLoading()
  161. let message = (object as? String) ?? "Failed to validate receipt".localized
  162. TSToastShared.showToast(text:message)
  163. #endif
  164. }
  165. }
  166. debugPrint("PurchaseManager onPurchaseStateChanged=\(String(describing: state))")
  167. }
  168. }
  169. @objc func closePage(){
  170. TSToastShared.hideLoading()
  171. self.dismiss(animated: true)
  172. NotificationCenter.default.post(name: .kCloseTSPurchaseVC, object: nil)
  173. }
  174. }