Commit cfd25127 by Dmitry Stepanets

- Added in-app checked

- Updated UI
parent f1cc460a
......@@ -164,7 +164,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func applicationDidBecomeActive(_ application: UIApplication) {
LocationManager.shared.updateEverythingIfNeeded()
storeManager.verifySubscriptions()
storeManager.verifyPurchases()
if #available(iOS 14, *) {
WidgetManager.shared.refreshAnalytics()
......
......@@ -4,7 +4,21 @@
],
"products" : [
{
"displayPrice" : "1.99",
"familyShareable" : false,
"internalID" : "22A7BDE0",
"localizations" : [
{
"description" : "",
"displayName" : "Upgrade to 1Weather Pro",
"locale" : "en_US"
}
],
"productID" : "com.onelouder.oneweather.inapp1",
"referenceName" : "1Weather Pro ",
"type" : "NonConsumable"
}
],
"settings" : {
"_timeRate" : 6
......
......@@ -91,7 +91,7 @@ public class StoreManager {
self.checkSubscriptionExpirationLocally()
self.completeTransactions()
self.updateProductInfo()
self.verifySubscriptions()
self.verifyPurchases()
#warning("Not implemented!")
//TODO: implement
......@@ -187,9 +187,44 @@ public class StoreManager {
}
}
public func verifySubscriptions() {
public func purchaseInApp() {
let log = self.log
log.info("Verify subscriptions...")
log.info("Purchase In-app start")
SwiftyStoreKit.purchaseProduct(kInAppOneWeatherProId, atomically: true) { result in
switch result {
case .success(let product):
if product.needsFinishTransaction {
SwiftyStoreKit.finishTransaction(product.transaction)
}
log.info("In app bought")
self.removeAdsPurchased = true
case .error(error: let error):
log.error("Purchase in-app: error for \(kInAppOneWeatherProId): \(error)")
}
}
}
public func restoreInApp() {
SwiftyStoreKit.restorePurchases(atomically: true) {[weak self] results in
if results.restoreFailedPurchases.count > 0 {
self?.log.error("Restore Failed: \(results.restoreFailedPurchases)")
}
else if results.restoredPurchases.count > 0 {
let ids = results.restoredPurchases.compactMap{ $0.productId }
if (ids.contains{ $0 == kInAppOneWeatherProId }) {
self?.log.info("Restore Success: \(results.restoredPurchases)")
self?.removeAdsPurchased = true
}
}
else {
self?.log.info("Nothing to Restore")
}
}
}
public func verifyPurchases() {
let log = self.log
log.info("Verify purchases...")
let service: AppleReceiptValidator.VerifyReceiptURLType
#if DEBUG
service = .sandbox
......@@ -201,6 +236,16 @@ public class StoreManager {
SwiftyStoreKit.verifyReceipt(using: appleValidator) { result in
switch result {
case .success(let receipt):
//In-app
let purchaseInAppResult = SwiftyStoreKit.verifyPurchase(productId: kInAppOneWeatherProId, inReceipt: receipt)
switch purchaseInAppResult {
case .purchased:
self.removeAdsPurchased = true
case .notPurchased:
self.removeAdsPurchased = false
}
//Subscriptions
let purchaseResult = SwiftyStoreKit.verifySubscriptions(ofType: .autoRenewable, productIds: self.allSubscriptionIds, inReceipt: receipt)
switch purchaseResult {
case .purchased(let expiryDate, let items):
......@@ -223,11 +268,11 @@ public class StoreManager {
log.error("Receipt verification failed: \(error)")
self.hasSubscription = false
self.everHadSubscription = false
self.removeAdsPurchased = false
self.subscriptionExpirationDate = nil
}
}
}
//MARK: - Observers management
public func add(observer: StoreManagerObserver) {
......@@ -264,6 +309,6 @@ public class StoreManager {
extension StoreManager: ConfigManagerDelegate {
public func dataUpdated(by configManager: ConfigManager) {
self.updateProductInfo()
self.verifySubscriptions()
self.verifyPurchases()
}
}
{
"images" : [
{
"filename" : "menu_restore.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}
......@@ -202,6 +202,7 @@
"menu.upgradeNow" = "Upgrade now";
"menu.settings" = "Settings";
"menu.subscriptionOverview" = "Premium";
"menu.restorePurchases" = "Restore purchases";
"menu.about" = "About us";
"menu.ad" = "Ad choices";
"menu.rateUs" = "Rate us";
......
......@@ -10,6 +10,7 @@ import UIKit
public enum MenuRow {
case settings
case subscriptionOverview
case restorePurchases
case about
case ad
case rateUs
......@@ -38,6 +39,8 @@ public enum MenuRow {
return UIImage(named: "menu_device_id")
case .subscriptionOverview:
return UIImage(named: "menu_crown")
case .restorePurchases:
return UIImage(named: "menu_restore")
}
}
......@@ -61,22 +64,26 @@ public enum MenuRow {
return "menu.deviceId".localized()
case .subscriptionOverview:
return "menu.subscriptionOverview".localized()
case .restorePurchases:
return "menu.restorePurchases".localized()
}
}
var roundedCorners:CACornerMask {
switch self {
case .settings:
if StoreManager.shared.hasSubscription {
return [.layerMinXMinYCorner, .layerMaxXMinYCorner]
if !StoreManager.shared.hasSubscription && StoreManager.shared.removeAdsPurchased {
return [.layerMinXMinYCorner, .layerMaxXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMaxYCorner]
}
else {
return [.layerMinXMinYCorner, .layerMaxXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMaxYCorner]
return [.layerMinXMinYCorner, .layerMaxXMinYCorner]
}
case .about:
return [.layerMinXMinYCorner, .layerMaxXMinYCorner]
case .restorePurchases:
return [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
case .subscriptionOverview:
return [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
case .about:
return [.layerMinXMinYCorner, .layerMaxXMinYCorner]
case .ad:
return []
case .rateUs:
......@@ -131,8 +138,14 @@ class MenuCellFactory<T>: CellFactory {
rows: [.settings, .subscriptionOverview])
}
else {
infoSectionItem = SectionItem(type: .info,
rows: [.settings])
if StoreManager.shared.removeAdsPurchased {
infoSectionItem = SectionItem(type: .info,
rows: [.settings])
}
else {
infoSectionItem = SectionItem(type: .info,
rows: [.settings, .restorePurchases])
}
}
let settingsSectionItem = SectionItem(type: .settings,
......
......@@ -23,6 +23,7 @@ class MenuHeaderView: UIView {
prepareView()
preparePremium()
updateUI()
reload()
}
required init?(coder: NSCoder) {
......@@ -34,6 +35,37 @@ class MenuHeaderView: UIView {
updateUI()
}
public func reload() {
if StoreManager.shared.removeAdsPurchased {
premiumHeadingLabel.font = AppFont.SFPro.regular(size: 16)
premiumHeadingLabel.text = "menu.upgradeTo".localized()
let descParagpraphStyle = NSMutableParagraphStyle()
descParagpraphStyle.minimumLineHeight = 20
let descriptionAttrString = NSAttributedString(string: "menu.premiumMembership".localized(),
attributes: [.foregroundColor : UIColor.white,
.paragraphStyle : descParagpraphStyle,
.font : AppFont.SFPro.bold(size: 24)])
premiumDescriptionLabel.attributedText = descriptionAttrString
buyButton.setTitle("menu.upgradeNow".localized(), for: .normal)
}
else {
premiumHeadingLabel.font = AppFont.SFPro.bold(size: 23)
premiumHeadingLabel.text = "menu.goPremium".localized()
let descParagpraphStyle = NSMutableParagraphStyle()
descParagpraphStyle.minimumLineHeight = 20
let descriptionAttrString = NSAttributedString(string: "menu.premium.desc".localized(),
attributes: [.foregroundColor : UIColor.white,
.paragraphStyle : descParagpraphStyle,
.font : AppFont.SFPro.regular(size: 14)])
premiumDescriptionLabel.attributedText = descriptionAttrString
buyButton.setTitle("menu.buyNow".localized(), for: .normal)
}
}
//Prvaite
private func updateUI() {
backgroundColor = ThemeManager.currentTheme.baseBackgroundColor
......@@ -80,35 +112,6 @@ private extension MenuHeaderView {
buyButton.addTarget(self, action: #selector(handleBuyButton), for: .touchUpInside)
premiumContainer.addSubview(buyButton)
if StoreManager.shared.removeAdsPurchased {
premiumHeadingLabel.font = AppFont.SFPro.regular(size: 16)
premiumHeadingLabel.text = "menu.upgradeTo".localized()
let descParagpraphStyle = NSMutableParagraphStyle()
descParagpraphStyle.minimumLineHeight = 20
let descriptionAttrString = NSAttributedString(string: "menu.premiumMembership".localized(),
attributes: [.foregroundColor : UIColor.white,
.paragraphStyle : descParagpraphStyle,
.font : AppFont.SFPro.bold(size: 24)])
premiumDescriptionLabel.attributedText = descriptionAttrString
buyButton.setTitle("menu.upgradeNow".localized(), for: .normal)
}
else {
premiumHeadingLabel.font = AppFont.SFPro.bold(size: 23)
premiumHeadingLabel.text = "menu.goPremium".localized()
let descParagpraphStyle = NSMutableParagraphStyle()
descParagpraphStyle.minimumLineHeight = 20
let descriptionAttrString = NSAttributedString(string: "menu.premium.desc".localized(),
attributes: [.foregroundColor : UIColor.white,
.paragraphStyle : descParagpraphStyle,
.font : AppFont.SFPro.regular(size: 14)])
premiumDescriptionLabel.attributedText = descriptionAttrString
buyButton.setTitle("menu.buyNow".localized(), for: .normal)
}
//Constraints
premiumContainer.snp.makeConstraints { (make) in
make.top.equalTo(30)
......
......@@ -63,6 +63,7 @@ class MenuViewController: UIViewController {
super.viewWillAppear(animated)
menuCellFactory.reload()
menuHeaderView.reload()
tableView.reloadData()
}
......@@ -157,6 +158,8 @@ extension MenuViewController: UITableViewDelegate {
viewModel.showDeviceId()
case .subscriptionOverview:
coordinator.openSubscriptionOverview()
case .restorePurchases:
viewModel.restorePurchases()
default:
break
}
......@@ -168,6 +171,7 @@ extension MenuViewController: StoreManagerObserver {
func storeManagerUpdatedStatus(_ storeManager: StoreManager) {
onMain {
self.menuCellFactory.reload()
self.menuHeaderView.reload()
self.tableView.reloadData()
}
}
......
......@@ -33,7 +33,7 @@ class SubscriptionOverviewViewController: UIViewController {
prepareScrollView()
//Verify new subscription
StoreManager.shared.verifySubscriptions()
StoreManager.shared.verifyPurchases()
}
}
......
......@@ -69,6 +69,10 @@ class MenuViewModel: NSObject, ViewModelProtocol {
}
}
public func restorePurchases() {
storeManager.restoreInApp()
}
public func viewAboutUs() {
self.delegate?.presentWebView(url: ONE_WEATHER_ABOUT_US_URL)
analytics(log: .ANALYTICS_VIEW_ABOUT)
......
......@@ -22,8 +22,7 @@ class SubscriptionViewModel: ViewModelProtocol {
}
public var isProUser: Bool {
return true
// storeManager.removeAdsPurchased
storeManager.removeAdsPurchased
}
public func purchase(subscription: SKProduct) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment