iap: move StoreKit logic out of DamusPurpleView and into a new PurpleStoreKitManager

This commit moves most of StoreKit-specific logic that was embedded into
DamusPurpleView and places it into a new PurpleStoreKitManager struct,
to make code more reusable and readable by separating view concerns from
StoreKit-specific concerns.

Most of the code here should be in feature parity with the previous
behavior. However, a few logical improvements were made alongside this
refactoring:

- Improved StoreKit transaction update monitoring logic: Previously the
  view would stop listening for purchase updates after the first update.
  However, I made the program continuously listen for purchase updates,
  as recommended by Apple's documentation
  (https://developer.apple.com/documentation/storekit/transaction/3851206-updates)

- Improved/simplified logic around getting extra information from the
  products: Information and the handling of product information was
  spread in a few separate places. I incorporated those bits of
  information into central and uniform interfaces on DamusPurpleType, to
  simplify logic and future changes.

Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
Daniel D’Aquino
2024-02-19 10:38:43 -08:00
committed by William Casarin
parent 2525799c8a
commit d694c26b83
5 changed files with 123 additions and 68 deletions
+7
View File
@@ -6,10 +6,12 @@
//
import Foundation
import StoreKit
class DamusPurple: StoreObserverDelegate {
let settings: UserSettingsStore
let keypair: Keypair
var storekit_manager: StoreKitManager
@MainActor
var account_cache: [Pubkey: Account]
@@ -18,6 +20,7 @@ class DamusPurple: StoreObserverDelegate {
self.settings = settings
self.keypair = keypair
self.account_cache = [:]
self.storekit_manager = .init()
}
// MARK: Functions
@@ -123,6 +126,10 @@ class DamusPurple: StoreObserverDelegate {
try await self.create_account(pubkey: pubkey)
}
func make_iap_purchase(product: Product) async throws -> Product.PurchaseResult {
return try await self.storekit_manager.purchase(product: product)
}
func send_receipt() async {
// Get the receipt if it's available.
if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL,