Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ The changelog for `SuperwallKit`. Also see the [releases](https://github.com/sup
### Enhancements

- Adds microphone permission request support.
- Adds post purchase actions support.

## 4.12.4

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ enum PaywallMessage: Decodable, Equatable {
case openUrlInSafari(_ url: URL)
case openPaymentSheet(_ url: URL)
case openDeepLink(url: URL)
case purchase(productId: String)
case purchase(productId: String, shouldDismiss: Bool)
case custom(data: String)
case customPlacement(name: String, params: JSON)
case userAttributesUpdated(attributes: JSON)
Expand Down Expand Up @@ -101,9 +101,11 @@ enum PaywallMessage: Decodable, Equatable {
}

// Everyone write to eventName, other may use the remaining keys
// Note: JSONDecoder.fromSnakeCase converts snake_case keys to camelCase automatically
private enum CodingKeys: String, CodingKey {
case messageType = "eventName"
case productId = "productIdentifier"
case shouldDismiss
case url
case link
case data
Expand Down Expand Up @@ -141,7 +143,8 @@ enum PaywallMessage: Decodable, Equatable {
return
case .purchase:
if let productId = try? values.decode(String.self, forKey: .productId) {
self = .purchase(productId: productId)
let shouldDismiss = try values.decodeIfPresent(Bool.self, forKey: .shouldDismiss) ?? true
self = .purchase(productId: productId, shouldDismiss: shouldDismiss)
return
}
case .restore:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,16 +126,25 @@ final class PaywallMessageHandler: WebEventDelegate {
await self.pass(placement: transactionStart, from: paywall)
}
case let .transactionComplete(trialEndDate, productIdentifier):
let freeTrialStart = SuperwallEventObjc.freeTrialStart.description
Task {
var payload: [String: Any] = ["product_identifier": productIdentifier]
// Send transaction_complete to trigger post-purchase actions
let transactionComplete = SuperwallEventObjc.transactionComplete.description
await self.pass(
placement: transactionComplete,
from: paywall,
payload: ["product_identifier": productIdentifier]
)

// Send freeTrial_start for notification scheduling
let freeTrialStart = SuperwallEventObjc.freeTrialStart.description
var freeTrialPayload: [String: Any] = ["product_identifier": productIdentifier]
if let trialEndDate {
payload["trial_end_date"] = Int(trialEndDate.timeIntervalSince1970 * 1000)
freeTrialPayload["trial_end_date"] = Int(trialEndDate.timeIntervalSince1970 * 1000)
}
await self.pass(
placement: freeTrialStart,
from: paywall,
payload: payload
payload: freeTrialPayload
)
}
case .transactionFail:
Expand Down Expand Up @@ -163,8 +172,8 @@ final class PaywallMessageHandler: WebEventDelegate {
openDeepLink(url)
case .restore:
restorePurchases()
case .purchase(productId: let id):
purchaseProduct(withId: id)
case let .purchase(productId: id, shouldDismiss: shouldDismiss):
purchaseProduct(withId: id, shouldDismiss: shouldDismiss)
case .custom(data: let name):
handleCustomEvent(name)
case let .customPlacement(name: name, params: params):
Expand Down Expand Up @@ -431,10 +440,18 @@ final class PaywallMessageHandler: WebEventDelegate {
delegate?.eventDidOccur(.initiateRestore)
}

private func purchaseProduct(withId id: String) {
private func purchaseProduct(
withId id: String,
shouldDismiss: Bool
) {
detectHiddenPaywallEvent("purchase")
hapticFeedback()
delegate?.eventDidOccur(.initiatePurchase(productId: id))
delegate?.eventDidOccur(
.initiatePurchase(
productId: id,
shouldDismiss: shouldDismiss
)
)
}

private func handleCustomEvent(_ customEvent: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import Foundation

enum PaywallWebEvent: Equatable {
case closed
case initiatePurchase(productId: String)
case initiatePurchase(
productId: String,
shouldDismiss: Bool
)
case initiateRestore
case custom(string: String)
case openedURL(url: URL)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/// The source of the purchase initiation.
enum PurchaseSource {
/// The purchase was initiated internally by the SDK.
case `internal`(String, PaywallViewController)
case `internal`(String, PaywallViewController, Bool)

/// The purchase was initiated externally by the user calling ``Superwall/purchase(_:)-7gwwe``.
case purchaseFunc(StoreProduct)
Expand All @@ -17,7 +17,7 @@ enum PurchaseSource {

func toRestoreSource() -> RestoreSource {
switch self {
case .internal(_, let paywallViewController): return .internal(paywallViewController)
case .internal(_, let paywallViewController, _): return .internal(paywallViewController)
case .purchaseFunc: return .external
case .observeFunc: return .external
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ final class TransactionManager {
let product: StoreProduct

switch purchaseSource {
case .internal(let productId, _):
case .internal(let productId, _, _):
guard let storeProduct = await storeKitManager.productsById[productId] else {
Logger.debug(
logLevel: .error,
Expand Down Expand Up @@ -126,7 +126,7 @@ final class TransactionManager {
case .observing:
break
case .purchasing(let purchaseSource):
if case let .internal(_, paywallViewController) = purchaseSource {
if case let .internal(_, paywallViewController, _) = purchaseSource {
await paywallViewController.togglePaywallSpinner(isHidden: true)
}
}
Expand Down Expand Up @@ -459,7 +459,7 @@ final class TransactionManager {
}

switch source {
case .internal(_, let paywallViewController):
case .internal(_, let paywallViewController, _):
Logger.debug(
logLevel: .debug,
scope: .transactions,
Expand Down Expand Up @@ -559,7 +559,7 @@ final class TransactionManager {
let shouldTrackTransactionStart = !(purchaseManager.isUsingSK2 && isObserved)

switch purchaseSource {
case .internal(_, let paywallViewController):
case .internal(_, let paywallViewController, _):
Logger.debug(
logLevel: .debug,
scope: .transactions,
Expand Down Expand Up @@ -633,7 +633,7 @@ final class TransactionManager {
}

switch source {
case .internal(_, let paywallViewController):
case let .internal(_, paywallViewController, shouldDismiss):
guard let product = await coordinator.product else {
return
}
Expand All @@ -658,12 +658,18 @@ final class TransactionManager {
await trackTransactionDidSucceed(transaction)

let superwallOptions = factory.makeSuperwallOptions()
if superwallOptions.paywalls.automaticallyDismiss {
let shouldDismissPaywall = superwallOptions.paywalls.automaticallyDismiss && shouldDismiss
if shouldDismissPaywall {
await Superwall.shared.dismiss(
paywallViewController,
result: .purchased(product)
)
}
if !shouldDismissPaywall {
await MainActor.run {
paywallViewController.togglePaywallSpinner(isHidden: true)
}
}
case .purchaseFunc,
.observeFunc:
Logger.debug(
Expand Down Expand Up @@ -704,7 +710,7 @@ final class TransactionManager {
}

switch source {
case .internal(_, let paywallViewController):
case .internal(_, let paywallViewController, _):
Logger.debug(
logLevel: .debug,
scope: .transactions,
Expand Down Expand Up @@ -764,7 +770,7 @@ final class TransactionManager {
}

switch source {
case .internal(_, let paywallViewController):
case .internal(_, let paywallViewController, _):
Logger.debug(
logLevel: .debug,
scope: .transactions,
Expand Down Expand Up @@ -894,7 +900,7 @@ final class TransactionManager {
let eventSource: InternalSuperwallEvent.Transaction.Source
let trialEndDate = product.trialPeriodEndDate
switch source {
case .internal(_, let paywallViewController):
case .internal(_, let paywallViewController, _):
paywallInfo = await paywallViewController.info
eventSource = .internal
await paywallViewController.webView.messageHandler
Expand Down
4 changes: 2 additions & 2 deletions Sources/SuperwallKit/Superwall.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1307,13 +1307,13 @@ extension Superwall: PaywallViewControllerEventDelegate {
result: .declined,
closeReason: .manualClose
)
case .initiatePurchase(let productId):
case let .initiatePurchase(productId, shouldDismiss):
if purchaseTask != nil {
return
}
purchaseTask = Task {
await dependencyContainer.transactionManager.purchase(
.internal(productId, paywallViewController)
.internal(productId, paywallViewController, shouldDismiss)
)
purchaseTask = nil
}
Expand Down
Loading