Fix subscription screen: use product IDs and add close button
- Switch from groupID to productIDs for more reliable product loading - Add dismiss button overlay so users aren't trapped if products fail to load - Make productIdentifiers static for shared access Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3848,6 +3848,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Close" : {
|
||||||
|
"comment" : "An accessibility label for the button that dismisses the view.",
|
||||||
|
"isCommentAutoGenerated" : true
|
||||||
|
},
|
||||||
"content_view_delete_entry" : {
|
"content_view_delete_entry" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class IAPManager: ObservableObject {
|
|||||||
|
|
||||||
static let subscriptionGroupID = "21951685"
|
static let subscriptionGroupID = "21951685"
|
||||||
|
|
||||||
private let productIdentifiers: Set<String> = [
|
static let productIdentifiers: Set<String> = [
|
||||||
"com.88oakapps.reflect.IAP.subscriptions.monthly",
|
"com.88oakapps.reflect.IAP.subscriptions.monthly",
|
||||||
"com.88oakapps.reflect.IAP.subscriptions.yearly"
|
"com.88oakapps.reflect.IAP.subscriptions.yearly"
|
||||||
]
|
]
|
||||||
@@ -267,7 +267,7 @@ class IAPManager: ObservableObject {
|
|||||||
|
|
||||||
private func loadProducts() async {
|
private func loadProducts() async {
|
||||||
do {
|
do {
|
||||||
let products = try await Product.products(for: productIdentifiers)
|
let products = try await Product.products(for: Self.productIdentifiers)
|
||||||
availableProducts = products.filter { $0.type == .autoRenewable }
|
availableProducts = products.filter { $0.type == .autoRenewable }
|
||||||
} catch {
|
} catch {
|
||||||
AppLogger.iap.error("Failed to load products: \(error.localizedDescription)")
|
AppLogger.iap.error("Failed to load products: \(error.localizedDescription)")
|
||||||
@@ -284,7 +284,7 @@ class IAPManager: ObservableObject {
|
|||||||
if transaction.revocationDate != nil { continue }
|
if transaction.revocationDate != nil { continue }
|
||||||
|
|
||||||
// Check if this is one of our subscription products
|
// Check if this is one of our subscription products
|
||||||
guard productIdentifiers.contains(transaction.productID) else { continue }
|
guard Self.productIdentifiers.contains(transaction.productID) else { continue }
|
||||||
|
|
||||||
// Get the product for this transaction
|
// Get the product for this transaction
|
||||||
currentProduct = availableProducts.first { $0.id == transaction.productID }
|
currentProduct = availableProducts.first { $0.id == transaction.productID }
|
||||||
|
|||||||
@@ -27,13 +27,25 @@ struct ReflectSubscriptionStoreView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
SubscriptionStoreView(groupID: IAPManager.subscriptionGroupID) {
|
SubscriptionStoreView(productIDs: IAPManager.productIdentifiers) {
|
||||||
marketingContent
|
marketingContent
|
||||||
}
|
}
|
||||||
.subscriptionStoreControlStyle(.prominentPicker)
|
.subscriptionStoreControlStyle(.prominentPicker)
|
||||||
.storeButton(.visible, for: .restorePurchases)
|
.storeButton(.visible, for: .restorePurchases)
|
||||||
.subscriptionStoreButtonLabel(.multiline)
|
.subscriptionStoreButtonLabel(.multiline)
|
||||||
.tint(tintColor)
|
.tint(tintColor)
|
||||||
|
.overlay(alignment: .topTrailing) {
|
||||||
|
Button {
|
||||||
|
dismiss()
|
||||||
|
} label: {
|
||||||
|
Image(systemName: "xmark.circle.fill")
|
||||||
|
.font(.title2)
|
||||||
|
.symbolRenderingMode(.hierarchical)
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
}
|
||||||
|
.padding(16)
|
||||||
|
.accessibilityLabel("Close")
|
||||||
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
AnalyticsManager.shared.trackPaywallViewed(source: source)
|
AnalyticsManager.shared.trackPaywallViewed(source: source)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user