fix: retry StoreKit tip product lookup
This commit is contained in:
@@ -721,7 +721,7 @@ final class TipStore: ObservableObject {
|
||||
// (or restored transactions) are picked up.
|
||||
do {
|
||||
let fetched = try await Product.products(for: Self.tiers.map(\.id))
|
||||
products = Dictionary(uniqueKeysWithValues: fetched.map { ($0.id, $0) })
|
||||
merge(fetched)
|
||||
} catch {
|
||||
// No products yet (sideloaded build) — the buttons still show the
|
||||
// intended prices and report purchase attempts gracefully.
|
||||
@@ -729,24 +729,37 @@ final class TipStore: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
private func merge(_ fetched: [Product]) {
|
||||
products.merge(Dictionary(uniqueKeysWithValues: fetched.map { ($0.id, $0) })) { _, new in new }
|
||||
}
|
||||
|
||||
private func product(for tier: TipTier) async throws -> Product? {
|
||||
if let product = products[tier.id] { return product }
|
||||
|
||||
// TestFlight/App Store Connect product availability can lag the Settings
|
||||
// onAppear load. Re-query the tapped tier before falling back so a newly
|
||||
// approved IAP opens the system purchase sheet instead of showing stale
|
||||
// "not available" copy.
|
||||
let fetched = try await Product.products(for: [tier.id])
|
||||
merge(fetched)
|
||||
return fetched.first { $0.id == tier.id }
|
||||
}
|
||||
|
||||
func purchase(_ tier: TipTier) async {
|
||||
guard !purchaseInProgress else { return }
|
||||
purchaseInProgress = true
|
||||
defer { purchaseInProgress = false }
|
||||
|
||||
// If the product hasn't loaded (e.g. not configured in App Store
|
||||
// Connect yet), still allow the attempt so the user sees a clear
|
||||
// outcome rather than a dead button.
|
||||
guard let product = products[tier.id] else {
|
||||
showOutcome(
|
||||
NSLocalizedString("The tip isn't available in this build yet — check back after an App Store release.", comment: ""),
|
||||
icon: "info.circle.fill",
|
||||
tint: Color(.secondaryLabel)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
guard let product = try await product(for: tier) else {
|
||||
showOutcome(
|
||||
NSLocalizedString("This tip isn't available from the App Store yet. Please try again shortly.", comment: ""),
|
||||
icon: "info.circle.fill",
|
||||
tint: Color(.secondaryLabel)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
let result = try await product.purchase()
|
||||
switch result {
|
||||
case .success(let verification):
|
||||
|
||||
Reference in New Issue
Block a user