TSPurchaseMembershipVC.swift 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. //
  2. // TSPurchaseMembershipVC.swift
  3. // TSLiveWallpaper
  4. //
  5. // Created by 100Years on 2025/1/13.
  6. //
  7. class TSPurchaseMembership111VC: TSBaseVC {
  8. var closePageBlock:(()->Void)?
  9. var buyPeriod:PremiumPeriod = .year
  10. lazy var purchaseManager: PurchaseManager = {
  11. let purchaseManager = PurchaseManager.default
  12. return purchaseManager
  13. }()
  14. lazy var yearCell: TSPurchaseMembershipCell = {
  15. let yearCell = TSPurchaseMembershipCell()
  16. yearCell.titleLabel.text = "Year".localized
  17. yearCell.priceLabel.text = purchaseManager.price(for: .year)
  18. yearCell.selectedImageView.isHidden = false
  19. yearCell.onTapd = { [weak self] in
  20. guard let self = self else { return }
  21. monthCell.selectedImageView.isHidden = true
  22. buyPeriod = .year
  23. }
  24. return yearCell
  25. }()
  26. lazy var monthCell: TSPurchaseMembershipCell = {
  27. let monthCell = TSPurchaseMembershipCell()
  28. monthCell.titleLabel.text = "Month".localized
  29. monthCell.priceLabel.text = purchaseManager.price(for: .month)
  30. monthCell.onTapd = { [weak self] in
  31. guard let self = self else { return }
  32. yearCell.selectedImageView.isHidden = true
  33. buyPeriod = .month
  34. }
  35. return monthCell
  36. }()
  37. lazy var submitBtn: UIButton = {
  38. let submitBtn = TSViewTool.createNormalSubmitBtn(title: "Continue") { [weak self] in
  39. guard let self = self else { return }
  40. purchaseManager.pay(for: buyPeriod)
  41. }
  42. submitBtn.cornerRadius = 24.0
  43. return submitBtn
  44. }()
  45. lazy var textLabel: UILabel = {
  46. let label = UILabel()
  47. label.numberOfLines = 0
  48. label.textAlignment = .center
  49. label.font = .font(size: 8)
  50. label.textColor = UIColor.fromHex("#FFFFFF",alpha: 0.4)
  51. let fullText = "Recurring billing, cancel anytime. Payment will be charged to your iTunes account at confirmation of purchase. Subscriptions automatically renew for the same applicable term and price, unless auto-renew is turned off at least 24 hours before the end of the current period."
  52. let highlightedText = "Recurring billing, cancel anytime."
  53. let attributedString = NSMutableAttributedString(string: fullText)
  54. if let range = fullText.range(of: highlightedText) {
  55. let nsRange = NSRange(range, in: fullText)
  56. attributedString.addAttributes([
  57. .foregroundColor: UIColor.fromHex("#12FFF7"), // 高亮颜色
  58. ], range: nsRange)
  59. }
  60. label.attributedText = attributedString
  61. return label
  62. }()
  63. override func createView() {
  64. addNormalNavBarView()
  65. _ = setNavigationItem("", imageName: "close_gray", direction: .left, action: #selector(closePage))
  66. let topView = creatTopView()
  67. contentView.addSubview(topView)
  68. topView.snp.makeConstraints { make in
  69. make.leading.equalTo(0)
  70. make.trailing.equalTo(0)
  71. make.top.equalTo(20)
  72. }
  73. contentView.addSubview(yearCell)
  74. contentView.addSubview(monthCell)
  75. contentView.addSubview(submitBtn)
  76. yearCell.snp.makeConstraints { make in
  77. make.leading.equalTo(16)
  78. make.trailing.equalTo(-16)
  79. make.height.equalTo(74)
  80. make.top.equalTo(topView.snp.bottom).offset(72)
  81. }
  82. monthCell.snp.makeConstraints { make in
  83. make.leading.equalTo(16)
  84. make.trailing.equalTo(-16)
  85. make.height.equalTo(74)
  86. make.top.equalTo(yearCell.snp.bottom).offset(12)
  87. }
  88. submitBtn.snp.makeConstraints { make in
  89. make.leading.equalTo(16)
  90. make.trailing.equalTo(-16)
  91. make.height.equalTo(48)
  92. make.top.equalTo(monthCell.snp.bottom).offset(28)
  93. }
  94. contentView.addSubview(textLabel)
  95. textLabel.snp.makeConstraints { make in
  96. make.leading.equalTo(16)
  97. make.trailing.equalTo(-16)
  98. make.height.equalTo(48)
  99. make.top.equalTo(submitBtn.snp.bottom).offset(12)
  100. }
  101. let bottomView = creatBottomLabel()
  102. contentView.addSubview(bottomView)
  103. bottomView.snp.makeConstraints { make in
  104. make.height.equalTo(17)
  105. make.centerX.equalToSuperview()
  106. make.top.equalTo(textLabel.snp.bottom).offset(8)
  107. }
  108. }
  109. override func dealThings() {
  110. purchaseManager.onPurchaseStateChanged = { [weak self] manager,state,object in
  111. guard let self = self else { return }
  112. DispatchQueue.main.async {
  113. switch state {
  114. case .none:
  115. break
  116. case .loading:
  117. TSToastShared.showLoading(text: "Getting price".localized)
  118. case .loadSuccess:
  119. TSToastShared.hideLoading()
  120. case .loadFail:
  121. TSToastShared.hideLoading()
  122. let message = "Get price failure, Will automatically retry in 5 seconds".localized
  123. TSToastShared.showToast(text: message)
  124. DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
  125. PurchaseManager.default.requestProducts()
  126. }
  127. case .paying:
  128. TSToastShared.showLoading(text: "Purchasing now".localized)
  129. case .paySuccess:
  130. TSToastShared.hideLoading()
  131. let loadingText = manager.isVip ? "Congratulation you have become VIP".localized : "Finish".localized
  132. TSToastShared.showToast(text:loadingText)
  133. if manager.isVip {
  134. DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
  135. self.closePage()
  136. }
  137. }
  138. case .payFail:
  139. TSToastShared.hideLoading()
  140. if let str = object as? String {
  141. TSToastShared.showToast(text: str)
  142. }
  143. case .restoreing:
  144. TSToastShared.showLoading(text: "Restoring now".localized)
  145. case .restoreSuccess:
  146. TSToastShared.hideLoading()
  147. let loadingText = manager.isVip ? "Congratulation you have become VIP".localized : "Couldn't Restore Subscription".localized
  148. debugPrint(loadingText)
  149. TSToastShared.showToast(text:loadingText)
  150. if manager.isVip {
  151. DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
  152. self.closePage()
  153. }
  154. }
  155. case .restoreFail:
  156. TSToastShared.hideLoading()
  157. let loadingText = (object as? String) ?? "Failed to restore subscribe, please try again".localized
  158. debugPrint(loadingText)
  159. TSToastShared.showToast(text: loadingText)
  160. case .verifying:
  161. #if DEBUG
  162. TSToastShared.showLoading(text: "Verifying receipt...".localized)
  163. #endif
  164. case .verifySuccess:
  165. break
  166. case .verifyFail:
  167. #if DEBUG
  168. TSToastShared.hideLoading()
  169. let message = (object as? String) ?? "Verify receipt failed"
  170. TSToastShared.showToast(text:message)
  171. #endif
  172. }
  173. }
  174. debugPrint("PurchaseManager onPurchaseStateChanged=\(String(describing: state))")
  175. }
  176. }
  177. @objc func closePage(){
  178. closePageBlock?()
  179. TSToastShared.hideLoading()
  180. self.dismiss(animated: true)
  181. }
  182. }
  183. extension TSPurchaseMembership111VC {
  184. func creatTopView() -> UIView {
  185. let topView = UIView()
  186. let vipImageView = UIImageView.createImageView(imageName: "vip_big_icon")
  187. topView.addSubview(vipImageView)
  188. let liveImageView = UIImageView.createImageView(imageName: "dmanagepro")
  189. topView.addSubview(liveImageView)
  190. let cell0 = creatCell(text: "All Premium Wallpapers")
  191. topView.addSubview(cell0)
  192. let cell1 = creatCell(text: "Unlimited Video To Live")
  193. topView.addSubview(cell1)
  194. let cell2 = creatCell(text: "100% No Ads")
  195. topView.addSubview(cell2)
  196. vipImageView.snp.makeConstraints { make in
  197. make.top.equalTo(0)
  198. make.centerX.equalToSuperview()
  199. make.width.equalTo(124)
  200. make.height.equalTo(102)
  201. }
  202. liveImageView.snp.makeConstraints { make in
  203. make.top.equalTo(vipImageView.snp.bottom).offset(12)
  204. make.centerX.equalToSuperview()
  205. }
  206. cell0.snp.makeConstraints { make in
  207. make.top.equalTo(liveImageView.snp.bottom).offset(40)
  208. make.leading.equalTo(76)
  209. make.trailing.equalTo(-10)
  210. make.height.equalTo(24)
  211. }
  212. cell1.snp.makeConstraints { make in
  213. make.top.equalTo(cell0.snp.bottom).offset(18)
  214. make.leading.equalTo(76)
  215. make.trailing.equalTo(-10)
  216. make.height.equalTo(24)
  217. }
  218. cell2.snp.makeConstraints { make in
  219. make.top.equalTo(cell1.snp.bottom).offset(18)
  220. make.leading.equalTo(76)
  221. make.trailing.equalTo(-10)
  222. make.height.equalTo(24)
  223. make.bottom.equalToSuperview()
  224. }
  225. return topView
  226. }
  227. func creatCell(text:String) -> UIView {
  228. let cellView = UIView()
  229. let vipImageView = UIImageView.createImageView(imageName: "check")
  230. cellView.addSubview(vipImageView)
  231. let label = UILabel.createLabel(text: text,font: .font(size: 16),textColor: .lesserText)
  232. cellView.addSubview(label)
  233. vipImageView.snp.makeConstraints { make in
  234. make.width.height.equalTo(24)
  235. make.leading.top.bottom.equalTo(0)
  236. }
  237. label.snp.makeConstraints { make in
  238. make.trailing.top.bottom.equalTo(0)
  239. make.leading.equalTo(vipImageView.snp.trailing).offset(8)
  240. }
  241. return cellView
  242. }
  243. func creatBottomLabel() -> UIView {
  244. let bgView = UIView()
  245. let termsLable = UILabel.createLabel(text: " Terms of us ".localized,font: .font(size: 12),textColor: .textAssist)
  246. termsLable.isUserInteractionEnabled = true
  247. termsLable.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(clickTermsLabel)))
  248. let privacyLable = UILabel.createLabel(text: "| Privacy Policy ".localized,font: .font(size: 12),textColor: .textAssist)
  249. privacyLable.isUserInteractionEnabled = true
  250. privacyLable.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(clickPrivacyLable)))
  251. let restoreLable = UILabel.createLabel(text: "| Restore ".localized,font: .font(size: 12),textColor: .textAssist)
  252. restoreLable.isUserInteractionEnabled = true
  253. restoreLable.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(clickRestoreLable)))
  254. bgView.addSubview(termsLable)
  255. termsLable.snp.makeConstraints { make in
  256. make.leading.top.bottom.equalTo(0)
  257. }
  258. bgView.addSubview(privacyLable)
  259. privacyLable.snp.makeConstraints { make in
  260. make.leading.equalTo(termsLable.snp.trailing)
  261. make.top.bottom.equalTo(0)
  262. }
  263. bgView.addSubview(restoreLable)
  264. restoreLable.snp.makeConstraints { make in
  265. make.leading.equalTo(privacyLable.snp.trailing)
  266. make.top.bottom.trailing.equalTo(0)
  267. }
  268. return bgView
  269. }
  270. @objc func clickTermsLabel() {
  271. let vc = TSBusinessWebVC(urlType: .terms)
  272. vc.hidesBottomBarWhenPushed = true
  273. kPresentModalVC(target: self, modelVC: vc)
  274. }
  275. @objc func clickPrivacyLable() {
  276. let vc = TSBusinessWebVC(urlType: .privacy)
  277. vc.hidesBottomBarWhenPushed = true
  278. kPresentModalVC(target: self, modelVC: vc)
  279. }
  280. @objc func clickRestoreLable() {
  281. purchaseManager.restorePremium()
  282. }
  283. }
  284. class TSPurchaseMembershipCell: TSBaseView {
  285. var onTapd:(()->Void)?
  286. lazy var titleLabel: UILabel = {
  287. let titleLabel = UILabel.createLabel(font: .font(size: 14),textColor: .textAssist)
  288. return titleLabel
  289. }()
  290. lazy var priceLabel: UILabel = {
  291. let titleLabel = UILabel.createLabel(font: .font(size: 18,weight: .medium),textColor: .mainText)
  292. return titleLabel
  293. }()
  294. lazy var selectedImageView: UIImageView = {
  295. let selectedImageView = UIImageView.createImageView(imageName: "radiobox_selected")
  296. selectedImageView.isHidden = true
  297. return selectedImageView
  298. }()
  299. override func creatUI() {
  300. contentView.backgroundColor = .fromHex("FFFFFF", alpha: 0.1)
  301. contentView.layer.cornerRadius = 16.0
  302. contentView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(clickBg)))
  303. contentView.addSubview(titleLabel)
  304. contentView.addSubview(priceLabel)
  305. contentView.addSubview(selectedImageView)
  306. titleLabel.snp.makeConstraints { make in
  307. make.leading.equalTo(16)
  308. make.top.equalTo(15)
  309. make.height.equalTo(14)
  310. }
  311. priceLabel.snp.makeConstraints { make in
  312. make.leading.equalTo(16)
  313. make.bottom.equalTo(-15)
  314. make.height.equalTo(18)
  315. }
  316. selectedImageView.snp.makeConstraints { make in
  317. make.trailing.equalTo(-16)
  318. make.centerY.equalToSuperview()
  319. make.width.height.equalTo(24)
  320. }
  321. }
  322. @objc func clickBg(){
  323. selectedImageView.isHidden = false
  324. onTapd?()
  325. }
  326. }
  327. extension TSPurchaseMembership111VC{
  328. static func show(target:UIViewController,closePageBlock:(()->Void)?){
  329. // let vc = TSPurchaseMembershipVC()
  330. // vc.closePageBlock = closePageBlock
  331. // let navi = TSBaseNavigationC(rootViewController: vc)
  332. // navi.modalPresentationStyle = .overFullScreen
  333. // target.present(navi, animated: true)
  334. }
  335. }