Skip to content

Commit

Permalink
Merge pull request #151 from superwall-me/develop
Browse files Browse the repository at this point in the history
v3.1.1
  • Loading branch information
yusuftor committed Jul 10, 2023
2 parents 72b26fa + 130023d commit 9e41733
Show file tree
Hide file tree
Showing 16 changed files with 1,726 additions and 992 deletions.
8 changes: 7 additions & 1 deletion .swiftpm/xcode/xcshareddata/xcschemes/SuperwallKit.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
shouldUseLaunchSchemeArgsEnv = "NO">
<CommandLineArguments>
<CommandLineArgument
argument = "SUPERWALL_UNIT_TESTS"
isEnabled = "YES">
</CommandLineArgument>
</CommandLineArguments>
<Testables>
<TestableReference
skipped = "NO">
Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

The changelog for `SuperwallKit`. Also see the [releases](https://github.com/superwall-me/Superwall-iOS/releases) on GitHub.

## 3.1.1

### Enhancements

- Adds `shouldShowPurchaseFailureAlert` as a `PaywallOption`. This defaults to `true`. If you're using a `PurchaseController`, set this to `false` to disable the alert that shows after the purchase fails.

### Fixes

- Fixes issue where a secondary paywall wouldn't present with the `transaction_fail` trigger.
- Fixes issue where the paywall preview wasn't obeying free trial/default paywall overrides.
- Fixes issue where preloaded paywalls may be associated with the incorrect experiment.

## 3.1.0

### Enhancements
Expand Down
6 changes: 6 additions & 0 deletions Sources/SuperwallKit/Config/Options/PaywallOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ public final class PaywallOptions: NSObject {
/// Defines the messaging of the alert presented to the user when restoring a transaction fails.
public var restoreFailed = RestoreFailed()

/// Shows an alert after a purchase fails. Defaults to `true`.
///
/// Set this to `false` if you're using a `PurchaseController` and want to show
/// your own alert after the purchase fails.
public var shouldShowPurchaseFailureAlert = true

/// Pre-loads and caches trigger paywalls and products when you initialize the SDK via ``Superwall/configure(apiKey:purchaseController:options:completion:)-52tke``. Defaults to `true`.
///
/// Set this to `false` to load and cache paywalls and products in a just-in-time fashion.
Expand Down
14 changes: 14 additions & 0 deletions Sources/SuperwallKit/Dependencies/DependencyContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -430,3 +430,17 @@ extension DependencyContainer: PurchaseManagerFactory {
)
}
}

// MARK: - Options Factory
extension DependencyContainer: OptionsFactory {
func makeSuperwallOptions() -> SuperwallOptions {
return configManager.options
}
}

// MARK: - Triggers Factory
extension DependencyContainer: TriggerFactory {
func makeTriggers() -> Set<String> {
return Set(configManager.triggersByEventName.keys)
}
}
8 changes: 8 additions & 0 deletions Sources/SuperwallKit/Dependencies/FactoryProtocols.swift
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,11 @@ protocol StoreTransactionFactory: AnyObject {
protocol PurchaseManagerFactory: AnyObject {
func makePurchaseManager() -> PurchaseManager
}

protocol OptionsFactory: AnyObject {
func makeSuperwallOptions() -> SuperwallOptions
}

protocol TriggerFactory: AnyObject {
func makeTriggers() -> Set<String>
}
2 changes: 1 addition & 1 deletion Sources/SuperwallKit/Misc/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ let sdkVersion = """
*/

let sdkVersion = """
3.1.0
3.1.1
"""
13 changes: 5 additions & 8 deletions Sources/SuperwallKit/Paywall/Request/PaywallRequestManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ actor PaywallRequestManager {
)

if var paywall = paywallsByHash[requestHash],
request.isDebuggerLaunched {
!request.isDebuggerLaunched {
paywall.experiment = request.responseIdentifiers.experiment
return paywall
}
Expand All @@ -58,9 +58,7 @@ actor PaywallRequestManager {

let task = Task<Paywall, Error> {
do {
let rawPaywall = try await getRawPaywall(
from: request
)
let rawPaywall = try await getRawPaywall(from: request)
let paywallWithProducts = try await addProducts(to: rawPaywall, request: request)

saveRequestHash(
Expand All @@ -86,10 +84,9 @@ actor PaywallRequestManager {
paywall: Paywall,
isDebuggerLaunched: Bool
) {
if isDebuggerLaunched {
return
}
paywallsByHash[requestHash] = paywall
activeTasks[requestHash] = nil
if !isDebuggerLaunched {
paywallsByHash[requestHash] = paywall
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ public class PaywallViewController: UIViewController, LoadingDelegate {
/// - Parameter isHidden: A `Bool` indicating whether to show or hide the spinner.
public func togglePaywallSpinner(isHidden: Bool) {
if isHidden {
if loadingState == .manualLoading {
if loadingState == .manualLoading || loadingState == .loadingPurchase {
loadingState = .ready
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ enum TransactionErrorLogic {
case presentAlert
}

static func handle(_ error: Error) -> ErrorOutcome {
static func handle(
_ error: Error,
triggers: Set<String>,
shouldShowPurchaseFailureAlert: Bool
) -> ErrorOutcome? {
if #available(iOS 15.0, *),
let error = error as? StoreKitError {
switch error {
Expand Down Expand Up @@ -49,6 +53,13 @@ enum TransactionErrorLogic {
}
}

return .presentAlert
let transactionFailExists = triggers.contains(SuperwallEventObjc.transactionFail.description)

if shouldShowPurchaseFailureAlert,
!transactionFailExists {
return .presentAlert
} else {
return nil
}
}
}
79 changes: 53 additions & 26 deletions Sources/SuperwallKit/StoreKit/Transactions/TransactionManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//
// Created by Yusuf Tör on 20/10/2022.
//
// swiftlint:disable type_body_length

import StoreKit
import UIKit
Expand All @@ -13,17 +14,19 @@ final class TransactionManager {
private unowned let storeKitManager: StoreKitManager
private unowned let sessionEventsManager: SessionEventsManager
private let purchaseManager: PurchaseManager
private let factory: PurchaseManagerFactory & OptionsFactory & TriggerFactory

/// The paywall view controller that the last product was purchased from.
private var lastPaywallViewController: PaywallViewController?

init(
storeKitManager: StoreKitManager,
sessionEventsManager: SessionEventsManager,
factory: PurchaseManagerFactory
factory: PurchaseManagerFactory & OptionsFactory & TriggerFactory
) {
self.storeKitManager = storeKitManager
self.sessionEventsManager = sessionEventsManager
self.factory = factory
purchaseManager = factory.makePurchaseManager()
}

Expand Down Expand Up @@ -53,14 +56,31 @@ final class TransactionManager {
transaction: transaction
)
case .failed(let error):
let outcome = TransactionErrorLogic.handle(error)
let superwallOptions = factory.makeSuperwallOptions()
guard let outcome = TransactionErrorLogic.handle(
error,
triggers: factory.makeTriggers(),
shouldShowPurchaseFailureAlert: superwallOptions.paywalls.shouldShowPurchaseFailureAlert
) else {
await trackFailure(
error: error,
product: product,
paywallViewController: paywallViewController
)
return await paywallViewController.togglePaywallSpinner(isHidden: true)
}
switch outcome {
case .cancelled:
await trackCancelled(
product: product,
from: paywallViewController
)
case .presentAlert:
await trackFailure(
error: error,
product: product,
paywallViewController: paywallViewController
)
await presentAlert(
forError: error,
product: product,
Expand All @@ -85,6 +105,35 @@ final class TransactionManager {

// MARK: - Transaction lifecycle

private func trackFailure(
error: Error,
product: StoreProduct,
paywallViewController: PaywallViewController
) async {
Logger.debug(
logLevel: .debug,
scope: .paywallTransactions,
message: "Transaction Error",
info: [
"product_id": product.productIdentifier,
"paywall_vc": paywallViewController
],
error: error
)

let paywallInfo = await paywallViewController.info
Task {
let trackedEvent = InternalSuperwallEvent.Transaction(
state: .fail(.failure(error.localizedDescription, product)),
paywallInfo: paywallInfo,
product: product,
model: nil
)
await Superwall.shared.track(trackedEvent)
await self.sessionEventsManager.triggerSession.trackTransactionError()
}
}

/// Tracks the analytics and logs the start of the transaction.
private func prepareToStartTransaction(
of product: StoreProduct,
Expand Down Expand Up @@ -144,7 +193,8 @@ final class TransactionManager {
product: product
)

if Superwall.shared.options.paywalls.automaticallyDismiss {
let superwallOptions = factory.makeSuperwallOptions()
if superwallOptions.paywalls.automaticallyDismiss {
await Superwall.shared.dismiss(
paywallViewController,
result: .purchased(productId: product.productIdentifier)
Expand Down Expand Up @@ -214,29 +264,6 @@ final class TransactionManager {
product: StoreProduct,
paywallViewController: PaywallViewController
) async {
Logger.debug(
logLevel: .debug,
scope: .paywallTransactions,
message: "Transaction Error",
info: [
"product_id": product.productIdentifier,
"paywall_vc": paywallViewController
],
error: error
)

let paywallInfo = await paywallViewController.info
Task.detached(priority: .utility) {
let trackedEvent = InternalSuperwallEvent.Transaction(
state: .fail(.failure(error.localizedDescription, product)),
paywallInfo: paywallInfo,
product: product,
model: nil
)
await Superwall.shared.track(trackedEvent)
await self.sessionEventsManager.triggerSession.trackTransactionError()
}

await paywallViewController.presentAlert(
title: "An error occurred",
message: error.localizedDescription
Expand Down
2 changes: 1 addition & 1 deletion Sources/SuperwallKit/Superwall.swift
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public final class Superwall: NSObject, ObservableObject {
// Code only executes when tests are running in a debug environment.
// This avoids lots of irrelevent error messages printed to console about Superwall not
// being configured, which slows down the tests.
if ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] != nil {
if ProcessInfo.processInfo.arguments.contains("SUPERWALL_UNIT_TESTS") {
let superwall = Superwall()
self.superwall = superwall
return superwall
Expand Down
2 changes: 1 addition & 1 deletion SuperwallKit.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|

s.name = "SuperwallKit"
s.version = "3.1.0"
s.version = "3.1.1"
s.summary = "Superwall: In-App Paywalls Made Easy"
s.description = "Paywall infrastructure for mobile apps :) we make things like editing your paywall and running price tests as easy as clicking a few buttons. superwall.com"

Expand Down
Loading

0 comments on commit 9e41733

Please sign in to comment.