|
|
|
|
@ -29,15 +29,17 @@ fileprivate enum Feature: Int, Identifiable, CaseIterable { |
|
|
|
|
|
|
|
|
|
struct StoreView: View, StoreDelegate { |
|
|
|
|
|
|
|
|
|
@StateObject var store: Store = Store() |
|
|
|
|
@StateObject private var store: Store = Store() |
|
|
|
|
|
|
|
|
|
@State var errorMessage: String? = nil |
|
|
|
|
@State private var errorMessage: String? = nil |
|
|
|
|
|
|
|
|
|
@Binding var isPresented: Bool |
|
|
|
|
|
|
|
|
|
var body: some View { |
|
|
|
|
|
|
|
|
|
Group { |
|
|
|
|
if !self.store.products.isEmpty { |
|
|
|
|
PlanView() |
|
|
|
|
PlanView(isPresented: self.$isPresented) |
|
|
|
|
.environmentObject(self.store) |
|
|
|
|
} else { |
|
|
|
|
ProgressView() |
|
|
|
|
@ -69,9 +71,11 @@ struct PlanView: View { |
|
|
|
|
|
|
|
|
|
@EnvironmentObject var store: Store |
|
|
|
|
|
|
|
|
|
// var productName: String |
|
|
|
|
// var price: String |
|
|
|
|
@State var _loadingProduct: String? = nil |
|
|
|
|
@State var _purchased: Bool = false |
|
|
|
|
|
|
|
|
|
@Binding var isPresented: Bool |
|
|
|
|
|
|
|
|
|
var body: some View { |
|
|
|
|
|
|
|
|
|
VStack { |
|
|
|
|
@ -107,17 +111,26 @@ struct PlanView: View { |
|
|
|
|
} label: { |
|
|
|
|
HStack { |
|
|
|
|
Spacer() |
|
|
|
|
VStack { |
|
|
|
|
|
|
|
|
|
if let plan = StorePlan(rawValue: product.id) { |
|
|
|
|
Text("\(product.displayPrice) / \(plan.formattedPeriod)").font(.title3) |
|
|
|
|
|
|
|
|
|
if product.id == self._loadingProduct { |
|
|
|
|
if self._purchased { |
|
|
|
|
Image(systemName: "checkmark.circle.fill") |
|
|
|
|
} else { |
|
|
|
|
Text("Plan not found") |
|
|
|
|
ProgressView() |
|
|
|
|
.progressViewStyle(.circular).tint(.white) |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
VStack { |
|
|
|
|
if let plan = StorePlan(rawValue: product.id) { |
|
|
|
|
Text("\(product.displayPrice) / \(plan.formattedPeriod)").font(.title3) |
|
|
|
|
} else { |
|
|
|
|
Text("Plan not found") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
Spacer() |
|
|
|
|
} |
|
|
|
|
}.frame(height: 44.0) |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
.buttonStyle(.borderedProminent) |
|
|
|
|
.fontWeight(.medium) |
|
|
|
|
@ -128,7 +141,15 @@ struct PlanView: View { |
|
|
|
|
|
|
|
|
|
fileprivate func _purchase(product: Product) { |
|
|
|
|
Task { |
|
|
|
|
try await store.purchase(product) |
|
|
|
|
self._loadingProduct = product.id |
|
|
|
|
let result = try await store.purchase(product) |
|
|
|
|
switch result { |
|
|
|
|
case .none: |
|
|
|
|
self._loadingProduct = nil |
|
|
|
|
case .some: |
|
|
|
|
self._purchased = true |
|
|
|
|
self.isPresented = false |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -192,6 +213,6 @@ struct PlayerWrapperView: View { |
|
|
|
|
|
|
|
|
|
struct StoreView_Previews: PreviewProvider { |
|
|
|
|
static var previews: some View { |
|
|
|
|
PlanView().environmentObject(Store()) |
|
|
|
|
PlanView(isPresented: .constant(false)).environmentObject(Store()) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|