forked from RevenueCat/purchases-ios
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPaywallView.swift
144 lines (119 loc) · 4.58 KB
/
PaywallView.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//
// PaywallView.swift
// Magic Weather SwiftUI
//
// Created by Cody Kerns on 1/19/21.
//
import SwiftUI
import RevenueCat
/*
An example paywall that uses the current offering.
*/
struct PaywallView: View {
/// - This binding is passed from ContentView: `paywallPresented`
@Binding var isPresented: Bool
/// - State for displaying an overlay view
@State
private(set) var isPurchasing: Bool = false
/// - The current offering saved from PurchasesDelegateHandler
private(set) var offering: Offering? = UserViewModel.shared.offerings?.current
private let footerText = "Don't forget to add your subscription terms and conditions. Read more about this here: https://www.revenuecat.com/blog/schedule-2-section-3-8-b"
@State private var error: NSError?
@State private var displayError: Bool = false
var body: some View {
NavigationView {
ZStack {
/// - The paywall view list displaying each package
List {
Section(header: Text("\nMagic Weather Premium"), footer: Text(footerText)) {
ForEach(offering?.availablePackages ?? []) { package in
PackageCellView(package: package) { (package) in
/// - Set 'isPurchasing' state to `true`
isPurchasing = true
/// - Purchase a package
do {
let result = try await Purchases.shared.purchase(package: package)
/// - Set 'isPurchasing' state to `false`
self.isPurchasing = false
if !result.userCancelled {
self.isPresented = false
}
} catch {
self.isPurchasing = false
self.error = error as NSError
self.displayError = true
}
}
}
}
}
.listStyle(InsetGroupedListStyle())
.navigationBarTitle("✨ Magic Weather Premium")
.navigationBarTitleDisplayMode(.inline)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.edgesIgnoringSafeArea(.bottom)
/// - Display an overlay during a purchase
Rectangle()
.foregroundColor(Color.black)
.opacity(isPurchasing ? 0.5: 0.0)
.edgesIgnoringSafeArea(.all)
}
}
.navigationViewStyle(StackNavigationViewStyle())
.colorScheme(.dark)
.alert(
isPresented: self.$displayError,
error: self.error,
actions: { _ in
Button(role: .cancel,
action: { self.displayError = false },
label: { Text("OK") })
},
message: { Text($0.recoverySuggestion ?? "Please try again") }
)
}
}
/* The cell view for each package */
struct PackageCellView: View {
let package: Package
let onSelection: (Package) async -> Void
var body: some View {
Button {
Task {
await self.onSelection(self.package)
}
} label: {
self.buttonLabel
}
.buttonStyle(.plain)
}
private var buttonLabel: some View {
HStack {
VStack {
HStack {
Text(package.storeProduct.localizedTitle)
.font(.title3)
.bold()
Spacer()
}
HStack {
Text(package.terms(for: package))
.font(.subheadline)
.foregroundColor(.secondary)
Spacer()
}
}
.padding([.top, .bottom], 8.0)
Spacer()
Text(package.localizedPriceString)
.font(.title3)
.bold()
}
.contentShape(Rectangle()) // Make the whole cell tappable
}
}
extension NSError: LocalizedError {
public var errorDescription: String? {
return self.localizedDescription
}
}