268 lines
10 KiB
Swift
268 lines
10 KiB
Swift
//
|
||
// SubscriptionsViewController.swift
|
||
// Earthquake Network
|
||
//
|
||
// Created by Busi Andrea on 29/07/2020.
|
||
// Copyright © 2020 Earthquake Network. All rights reserved.
|
||
//
|
||
|
||
import UIKit
|
||
import StoreKit
|
||
|
||
|
||
class SubscriptionsViewController: UITableViewController {
|
||
|
||
private static let SegueIdentifierSubscriptionDetail = "ShowSubscriptionDetail"
|
||
private static let CellHeightDescription: CGFloat = 320.0
|
||
|
||
// sezioni
|
||
private enum TableSection: CaseIterable {
|
||
case active
|
||
case description
|
||
case monthly
|
||
case yearly
|
||
|
||
var sectionTitle: String? {
|
||
switch self {
|
||
case .monthly: return NSLocalizedString("Abbonamenti mensili", comment: "")
|
||
case .yearly: return NSLocalizedString("Abbonamenti annuali", comment: "")
|
||
default: return nil
|
||
}
|
||
}
|
||
}
|
||
|
||
private let sections = TableSection.allCases
|
||
|
||
private var allProducts = [SKProduct]()
|
||
private var monthlyProducts = [SKProduct]()
|
||
private var yearlyProducts = [SKProduct]()
|
||
/// Product already bought by the user
|
||
private var subscribedProduct: SKProduct?
|
||
/// Availability for subscriptions
|
||
private var availability: EQNPurchaseAvailability?
|
||
/// Tells if products are loading
|
||
private var isLoading = false
|
||
/// Tells if a restore is in progress
|
||
private var isRestorePurchase = false
|
||
|
||
// MARK: - View Lifecycle
|
||
|
||
override func viewDidLoad() {
|
||
super.viewDidLoad()
|
||
|
||
addObservers()
|
||
configureUI()
|
||
}
|
||
|
||
override func viewWillAppear(_ animated: Bool) {
|
||
super.viewWillAppear(animated)
|
||
|
||
loadData()
|
||
checkAvailabilities()
|
||
}
|
||
|
||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||
if segue.identifier == Self.SegueIdentifierSubscriptionDetail,
|
||
let controller = segue.destination as? SubscriptionDetailViewController,
|
||
let product = sender as? SKProduct {
|
||
controller.product = product
|
||
}
|
||
}
|
||
|
||
// MARK: - Private
|
||
|
||
private func addObservers() {
|
||
NotificationCenter.default.addObserver(self, selector: #selector(handlePurchaseNotification(_:)),
|
||
name: .IAPHelperPurchaseNotification,
|
||
object: nil)
|
||
|
||
NotificationCenter.default.addObserver(self, selector: #selector(fail(_:)),
|
||
name: .IAPHelperPurchaseNotificationFail,
|
||
object: nil)
|
||
}
|
||
|
||
private func configureUI() {
|
||
let restoreButton = UIBarButtonItem(title: NSLocalizedString("purchase_pro_restore", comment: ""),
|
||
style: .plain,
|
||
target: self,
|
||
action: #selector(restoreTapped(_:)))
|
||
navigationItem.rightBarButtonItem = restoreButton
|
||
|
||
tableView.rowHeight = UITableView.automaticDimension
|
||
tableView.estimatedRowHeight = Self.CellHeightDescription;
|
||
}
|
||
|
||
private func updateUI() {
|
||
monthlyProducts.removeAll()
|
||
yearlyProducts.removeAll()
|
||
|
||
// creates list to show
|
||
let isDiscountAvailable = checkDiscountPrice()
|
||
allProducts.forEach { (product) in
|
||
if isDiscountAvailable {
|
||
if product.productIdentifier == VersioneProProducts.Identifier.Subscription10kMonthly ||
|
||
product.productIdentifier == VersioneProProducts.Identifier.Subscription100kMonthly {
|
||
monthlyProducts.append(product)
|
||
} else if product.productIdentifier == VersioneProProducts.Identifier.Subscription10kYearlyDiscounted ||
|
||
product.productIdentifier == VersioneProProducts.Identifier.Subscription100kYearlyDiscounted {
|
||
yearlyProducts.append(product)
|
||
}
|
||
} else {
|
||
if product.productIdentifier == VersioneProProducts.Identifier.Subscription10kMonthly ||
|
||
product.productIdentifier == VersioneProProducts.Identifier.Subscription100kMonthly {
|
||
monthlyProducts.append(product)
|
||
}
|
||
else if product.productIdentifier == VersioneProProducts.Identifier.Subscription10kYearly ||
|
||
product.productIdentifier == VersioneProProducts.Identifier.Subscription100kYearly {
|
||
yearlyProducts.append(product)
|
||
}
|
||
}
|
||
}
|
||
|
||
tableView.reloadData()
|
||
}
|
||
|
||
private func loadData() {
|
||
isLoading = true
|
||
|
||
VersioneProProducts.store.requestProducts{ [weak self] success, products in
|
||
self?.isLoading = false
|
||
|
||
guard let self = self, let products = products, success == true else { return }
|
||
|
||
let purchased = products.filter { (product) -> Bool in
|
||
let isPurchased = VersioneProProducts.store.isProductPurchased(product.productIdentifier)
|
||
let isSubscription = VersioneProProducts.Identifier.isSubscription(for: product.productIdentifier)
|
||
return isPurchased && isSubscription
|
||
}
|
||
self.subscribedProduct = purchased.first
|
||
self.allProducts = products.sorted(by: { $0.productIdentifier > $1.productIdentifier })
|
||
|
||
self.updateUI()
|
||
}
|
||
}
|
||
|
||
private func checkDiscountPrice() -> Bool {
|
||
let downloaded = EQNManager.manager().rete_smartphone?.subscriptionsDiscounted
|
||
return downloaded ?? false
|
||
}
|
||
|
||
private func checkAvailabilities() {
|
||
EQNPurchaseUtility.availableSubscriptions { (availability) in
|
||
DispatchQueue.main.async {
|
||
self.availability = availability
|
||
self.updateUI()
|
||
}
|
||
}
|
||
}
|
||
|
||
// MARK: - Actions
|
||
|
||
@objc func restoreTapped(_ sender: AnyObject) {
|
||
isRestorePurchase = true
|
||
VersioneProProducts.store.restorePurchases()
|
||
}
|
||
|
||
// MARK: - Notifications
|
||
|
||
@objc func fail(_ notification: Notification){
|
||
VersioneProProducts.store.loadPurchase()
|
||
}
|
||
|
||
@objc func handlePurchaseNotification(_ notification: Notification) {
|
||
if isRestorePurchase {
|
||
isRestorePurchase = false
|
||
|
||
let alert = UIAlertController(title: NSLocalizedString("purchase_pro_restore_alert_title", comment: ""),
|
||
message: NSLocalizedString("purchase_pro_restore_alert_message", comment: ""), preferredStyle: .alert)
|
||
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
|
||
present(alert, animated: true, completion: nil)
|
||
}
|
||
|
||
VersioneProProducts.store.loadPurchase()
|
||
loadData()
|
||
}
|
||
|
||
// MARK: - Table view data source
|
||
|
||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||
sections.count
|
||
}
|
||
|
||
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
|
||
let tableSection = sections[section]
|
||
if let cell = tableView.dequeueReusableCell(withIdentifier: "SectionHeaderCell") as? SubscriptionsHeaderTableViewCell {
|
||
cell.title = tableSection.sectionTitle
|
||
cell.isLoading = isLoading
|
||
return cell
|
||
}
|
||
return nil
|
||
}
|
||
|
||
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
|
||
let tableSection = sections[section]
|
||
if tableSection.sectionTitle != nil {
|
||
return 50
|
||
}
|
||
return 10
|
||
}
|
||
|
||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||
let tableSection = sections[section]
|
||
switch tableSection {
|
||
case .active: return 1
|
||
case .description: return 1
|
||
case .monthly: return monthlyProducts.count
|
||
case .yearly: return yearlyProducts.count
|
||
}
|
||
}
|
||
|
||
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
|
||
let tableSection = sections[indexPath.section]
|
||
if tableSection == .description {
|
||
// autolayout in description doesn't work 🤷♂️
|
||
return Self.CellHeightDescription
|
||
}
|
||
return UITableView.automaticDimension
|
||
}
|
||
|
||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||
let tableSection = sections[indexPath.section]
|
||
if tableSection == .active {
|
||
let cell = tableView.dequeueReusableCell(withIdentifier: "ActiveSubscriptionsCell", for: indexPath) as! SubscriptionsActiveTableViewCell
|
||
cell.product = subscribedProduct
|
||
return cell
|
||
}
|
||
if tableSection == .description {
|
||
let cell = tableView.dequeueReusableCell(withIdentifier: "DescriptionCell", for: indexPath)
|
||
return cell
|
||
}
|
||
|
||
let products = tableSection == .monthly ? monthlyProducts : yearlyProducts
|
||
let cell = tableView.dequeueReusableCell(withIdentifier: "SubscriptionCell", for: indexPath) as! SubscriptionProductTableViewCell
|
||
cell.product = products[indexPath.row]
|
||
cell.availability = availability
|
||
return cell
|
||
}
|
||
|
||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||
tableView.deselectRow(at: indexPath, animated: true)
|
||
|
||
let tableSection = sections[indexPath.section]
|
||
if tableSection == .monthly || tableSection == .yearly {
|
||
let products = tableSection == .monthly ? monthlyProducts : yearlyProducts
|
||
performSegue(withIdentifier: Self.SegueIdentifierSubscriptionDetail, sender: products[indexPath.row])
|
||
}
|
||
}
|
||
}
|
||
|
||
extension SubscriptionsViewController: StoryboardInitializable {
|
||
static var storyboardName: String {
|
||
"Main"
|
||
}
|
||
|
||
static var storyboardControllerId: String {
|
||
"subscriptionsController"
|
||
}
|
||
}
|