Commit 4d5d2068 by Demid Merzlyakov

InApp: hide ads when the app is purchased.

parent 8c8185a9
......@@ -252,6 +252,7 @@
CEC5275D25E8E50B00DA58A5 /* WdtDailySummary.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEC5275C25E8E50B00DA58A5 /* WdtDailySummary.swift */; };
CEC5276025E92DDA00DA58A5 /* WdtHourlySummary.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEC5275F25E92DDA00DA58A5 /* WdtHourlySummary.swift */; };
CEC7D8C42639FAF600B8836D /* Global.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEC7D8C32639FAF500B8836D /* Global.swift */; };
CEC7D8EE2639FE2700B8836D /* OLInAppStoreManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEC7D8ED2639FE2700B8836D /* OLInAppStoreManager.swift */; };
CEC8FBAF2639756A0001A6BF /* OnboardingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEC8FBAE2639756A0001A6BF /* OnboardingViewController.swift */; };
CEC8FBB2263976240001A6BF /* OnboardingCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEC8FBB1263976240001A6BF /* OnboardingCoordinator.swift */; };
CEC8FBB5263976400001A6BF /* OnboardingViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEC8FBB4263976400001A6BF /* OnboardingViewModel.swift */; };
......@@ -575,6 +576,7 @@
CEC5275C25E8E50B00DA58A5 /* WdtDailySummary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WdtDailySummary.swift; sourceTree = "<group>"; };
CEC5275F25E92DDA00DA58A5 /* WdtHourlySummary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WdtHourlySummary.swift; sourceTree = "<group>"; };
CEC7D8C32639FAF500B8836D /* Global.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Global.swift; sourceTree = "<group>"; };
CEC7D8ED2639FE2700B8836D /* OLInAppStoreManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OLInAppStoreManager.swift; sourceTree = "<group>"; };
CEC8FBAE2639756A0001A6BF /* OnboardingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewController.swift; sourceTree = "<group>"; };
CEC8FBB1263976240001A6BF /* OnboardingCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingCoordinator.swift; sourceTree = "<group>"; };
CEC8FBB4263976400001A6BF /* OnboardingViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewModel.swift; sourceTree = "<group>"; };
......@@ -694,6 +696,7 @@
CD1237C1255D5C5900C98139 /* 1Weather */ = {
isa = PBXGroup;
children = (
CEC7D8EC2639FE1B00B8836D /* InApps */,
CE14445D2638B6A8008E2162 /* 1Weather.entitlements */,
CE13B78926247474007CBD4D /* External */,
CE13B7EC262480B3007CBD4D /* Ads */,
......@@ -1505,6 +1508,14 @@
path = ModelObjects;
sourceTree = "<group>";
};
CEC7D8EC2639FE1B00B8836D /* InApps */ = {
isa = PBXGroup;
children = (
CEC7D8ED2639FE2700B8836D /* OLInAppStoreManager.swift */,
);
path = InApps;
sourceTree = "<group>";
};
CEC8FBAD263975170001A6BF /* Onboarding */ = {
isa = PBXGroup;
children = (
......@@ -2097,6 +2108,7 @@
CD86245E25E646350097F3FB /* SunUvView.swift in Sources */,
CDF8F12D26208E7B00DB384A /* MapCurrentTimeView.swift in Sources */,
CEAFF08325DFC67F00DF4EBF /* Location.swift in Sources */,
CEC7D8EE2639FE2700B8836D /* OLInAppStoreManager.swift in Sources */,
CDECDB052629A6600087F9F2 /* RadarLayer.swift in Sources */,
CEFB857226174F7A00C5CDD2 /* Storage.swift in Sources */,
CD82300725D6A73F00A05501 /* TodayConditionButton.swift in Sources */,
......
......@@ -13,3 +13,5 @@ let kEventInAppPurchasedCompleted = "EventInAppPurchasedCompleted"
let a9AppKey = "2e440b094f7c44b4bae7044b764c61ac"
let kAdMoPubInitializationAdUnitId = "05bff78d4a4245bd98ff6b595c134889"
let kOLAppMetricsKey: String = "OLAppMetricsKey"
//MARK: - InApp
let kInAppOneWeatherProId = "com.onelouder.oneweather.inapp1"
//
// OLInAppStoreManager.swift
// OneWeather
//
// Created by Steven G Pint on 5/16/17.
// Copyright © 2017 OneLouder, Inc. All rights reserved.
//
import UIKit
import StoreKit
// Ported from ObjC
protocol OLInAppStoreManagerUIDelegate: class {
func viewControllerForPresentation() -> UIViewController
}
protocol OLInAppStoreManagerDelegate: NSObjectProtocol {
func inAppStoreManager(_ inAppStoreManager: OLInAppStoreManager, purchaseCompletedForProductId productId: String)
func inAppStoreManager(_ inAppStoreManager: OLInAppStoreManager, purchaseWillBeAdded payment: SKPayment)
func inAppStoreManager(_ inAppStoreManager: OLInAppStoreManager, purchaseFailedFor transaction: SKPaymentTransaction)
func inAppStoreManager(_ inAppStoreManager: OLInAppStoreManager, restoredCompletedForProductId productId: String)
func inAppStoreManager(_ inAppStoreManager: OLInAppStoreManager, restoreFailedWithError error: Error)
func inAppStoreManager(_ inAppStoreManager: OLInAppStoreManager, restoreFailedWithMessage message: String)
}
class OLInAppStoreManager: NSObject {
private let log = Logger(componentName: "OLInAppStoreManager")
var productIds = [String]()
weak var delegate: OLInAppStoreManagerDelegate?
weak var uiDelegate: OLInAppStoreManagerUIDelegate?
// SHARED INSTANCE
static let shared = OLInAppStoreManager()
private override init() {
super.init()
}
// MARK: - public methods
func attemptPurchase(forProductId productId: String) {
if SKPaymentQueue.canMakePayments() {
productIds.append(productId)
let request = SKProductsRequest(productIdentifiers: Set<String>([productId]))
request.delegate = self
request.start()
} else {
showAlert("inapp.alert.prohibited.title".localized(), message: "inapp.error.parental.control.cant.make.purchase".localized())
}
}
func attemptRestore(forProductId productId: String) {
if SKPaymentQueue.canMakePayments() {
SKPaymentQueue.default().add(self)
SKPaymentQueue.default().restoreCompletedTransactions()
} else {
showAlert("inapp.alert.prohibited.title".localized(), message: "inapp.error.parental.control.cant.store".localized())
}
}
public func showAlert(_ title: String?, message: String?) -> Void {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "inapp.alert.ok".localized(), style: .default, handler: nil))
self.uiDelegate?.viewControllerForPresentation().present(alert, animated: true, completion: nil)
}
}
// MARK: - SKProductsRequestDelegate
extension OLInAppStoreManager: SKProductsRequestDelegate {
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
var validProduct: SKProduct? = nil
for product: SKProduct in response.products {
if productIds.contains(product.productIdentifier) {
validProduct = product
break
}
}
if let validProduct = validProduct {
let payment = SKPayment(product: validProduct)
delegate?.inAppStoreManager(self, purchaseWillBeAdded: payment)
SKPaymentQueue.default().add(self)
SKPaymentQueue.default().add(payment)
//[self updateToProLabel:NSLocalizedString(@"Confirming purchase...", nil) isUpdating:YES];
} else {
showAlert("inapp.alert.product.not.available.title".localized(), message: "inapp.alert.product.not.available.text".localized())
}
}
}
// MARK: - SKPaymentTransactionObserver - required
extension OLInAppStoreManager: SKPaymentTransactionObserver {
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction: SKPaymentTransaction in transactions {
switch transaction.transactionState {
case .purchased:
delegate?.inAppStoreManager(self, purchaseCompletedForProductId: transaction.payment.productIdentifier)
SKPaymentQueue.default().finishTransaction(transaction)
case .failed:
if let error = transaction.error {
log.error("SKPaymentTransactionStateFailedError: \(error)")
}
else {
log.error("SKPaymentTransactionStateFailedError: unknown error")
}
delegate?.inAppStoreManager(self, purchaseFailedFor: transaction)
SKPaymentQueue.default().finishTransaction(transaction)
case .restored:
delegate?.inAppStoreManager(self, restoredCompletedForProductId: transaction.payment.productIdentifier)
SKPaymentQueue.default().finishTransaction(transaction)
default:
break
}
}
}
func paymentQueue(_ queue: SKPaymentQueue, updatedDownloads downloads: [SKDownload]) {
log.debug("paymentQueue:updatedDownloads")
}
// MARK: - SKPaymentTransactionObserver - optional
func paymentQueue(_ queue: SKPaymentQueue, removedTransactions transactions: [SKPaymentTransaction]) {
log.debug("paymentQueue:removedTransactions")
}
func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: Error) {
log.error("paymentQueue:restoreCompletedTransactionsFailedWithError: \(error)")
delegate?.inAppStoreManager(self, restoreFailedWithError: error)
}
func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
log.info("paymentQueueRestoreCompletedTransactionsFinished productId: \(queue.transactions.first?.payment.productIdentifier ?? "None")")
if let transaction = queue.transactions.first, kInAppOneWeatherProId == transaction.payment.productIdentifier {
delegate?.inAppStoreManager(self, restoredCompletedForProductId: transaction.payment.productIdentifier)
} else {
delegate?.inAppStoreManager(self, restoreFailedWithMessage: "inapp.restoration.error.no.purchases".localized())
}
}
}
// MARK: - SKRequestDelegate
extension OLInAppStoreManager: SKRequestDelegate {
func requestDidFinish(_ request: SKRequest) {
log.debug("requestDidFinish")
}
func request(_ request: SKRequest, didFailWithError error: Error) {
log.error("Failed to connect with error: \(error)")
}
}
......@@ -204,3 +204,12 @@
"health.airquality.status.unhealthy" = "Unhealthy";
"health.airquality.status.veryUnhealthy" = "Very Unhealthy";
"health.airquality.status.hazardous" = "Hazardous";
// InApp
"inapp.alert.prohibited.title" = "Prohibited";
"inapp.error.parental.control.cant.make.purchase" = "Parental Control is enabled, cannot make a purchase!";
"inapp.error.parental.control.cant.store" = "Parental Control is enabled, cannot store!";
"inapp.alert.product.not.available.title" = "Product Not Available";
"inapp.alert.product.not.available.text" = "Please contact support.";
"inapp.restoration.error.no.purchases" = "There are no purchases to restore";
"inapp.alert.ok" = "Ok";
......@@ -23,8 +23,8 @@ let DOWN_ARROW = "\u{2193}"
// isPro
func isAppPro() -> Bool {
if let metricsLog = UserDefaults.standard.dictionary(forKey: kOLAppMetricsKey), let event = metricsLog[kEventInAppPurchasedCompleted] {
return event != nil
if let metricsLog = UserDefaults.standard.dictionary(forKey: kOLAppMetricsKey) {
return metricsLog[kEventInAppPurchasedCompleted] != nil
}
return false
}
......
......@@ -42,7 +42,12 @@ fileprivate struct HeaderSection: NWSAlertTableViewSection {
fileprivate struct ExtendedInfoSection: NWSAlertTableViewSection {
private var alert: NWSAlert
private let countOfAds = 1
private var countOfAds: Int {
if !isAppPro() && AdConfigManager.shared.adConfig.adsEnabled {
return 1
}
return 0
}
init(alert: NWSAlert) {
self.alert = alert
......@@ -57,6 +62,9 @@ fileprivate struct ExtendedInfoSection: NWSAlertTableViewSection {
}
func type(forRow row: Int) -> NWSAlertCellType {
guard countOfAds > 0 else {
return .extendedInfoBlock
}
if numberOfRows == 1 {
return .ad
}
......
......@@ -188,7 +188,7 @@ class TodayCellFactory: CellFactoryProtocol {
private func setupHiddenRows() {
var rowsToHide = Set<TodayCellType>()
if !AdConfigManager.shared.adConfig.adsEnabled {
if isAppPro() || !AdConfigManager.shared.adConfig.adsEnabled {
rowsToHide.insert(.ad)
}
......
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