iap - wip
This commit is contained in:
236
Shared/views/PurchaseButtonView.swift
Normal file
236
Shared/views/PurchaseButtonView.swift
Normal file
@@ -0,0 +1,236 @@
|
||||
//
|
||||
// PurchaseButtonView.swift
|
||||
// Feels
|
||||
//
|
||||
// Created by Trey Tartt on 7/7/22.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import StoreKit
|
||||
|
||||
struct PurchaseButtonView: View {
|
||||
enum ViewStatus: String {
|
||||
case needToBuy
|
||||
case error
|
||||
case success
|
||||
case subscribed
|
||||
}
|
||||
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
||||
@AppStorage(UserDefaultsStore.Keys.textColor.rawValue, store: GroupUserDefaults.groupDefaults) private var textColor: Color = DefaultTextColor.textColor
|
||||
var iapManager: IAPManager
|
||||
|
||||
private let height: Float
|
||||
private let showManageSubClosure: (() -> Void)?
|
||||
|
||||
@State var isPurchasing: Bool = false
|
||||
|
||||
@State private var viewStatus: ViewStatus = .needToBuy {
|
||||
didSet {
|
||||
isPurchasing = false
|
||||
}
|
||||
}
|
||||
|
||||
public init(height: Float, iapManager: IAPManager, showManageSubClosure: (() -> Void)? = nil) {
|
||||
self.height = height
|
||||
self.showManageSubClosure = showManageSubClosure
|
||||
self.iapManager = iapManager
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
switch viewStatus {
|
||||
case .needToBuy, .error:
|
||||
buyOptionsView
|
||||
.frame(height: CGFloat(height))
|
||||
.background(theme.currentTheme.secondaryBGColor)
|
||||
case .success:
|
||||
subscribedView
|
||||
.frame(height: CGFloat(height))
|
||||
.background(theme.currentTheme.secondaryBGColor)
|
||||
case .subscribed:
|
||||
subscribedView
|
||||
.frame(height: CGFloat(height))
|
||||
.background(theme.currentTheme.secondaryBGColor)
|
||||
}
|
||||
}
|
||||
.onAppear{
|
||||
if let _ = iapManager.currentSubscription {
|
||||
viewStatus = .subscribed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var buyOptionsSetingsView: some View {
|
||||
GeometryReader { metrics in
|
||||
VStack(spacing: 20) {
|
||||
Text(String(localized: "purchase_view_title"))
|
||||
.foregroundColor(textColor)
|
||||
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
|
||||
.frame(height: 50)
|
||||
.padding([.leading, .trailing])
|
||||
VStack(alignment: .leading) {
|
||||
ForEach(iapManager.sortedSubscriptionKeysByPriceOptions, id: \.self) { product in
|
||||
HStack {
|
||||
Button(action: {
|
||||
purchase(product: product)
|
||||
}, label: {
|
||||
Text("\(product.displayPrice)\n\(product.displayName)")
|
||||
.foregroundColor(.white)
|
||||
.bold()
|
||||
.frame(maxWidth: .infinity)
|
||||
.contentShape(Rectangle())
|
||||
})
|
||||
.frame(maxWidth: .infinity)
|
||||
.frame(height: 50)
|
||||
.padding()
|
||||
.background(RoundedRectangle(cornerRadius: 10).fill(iapManager.colorForIAPButton(iapIdentifier: product.id)))
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding([.leading, .leading])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var buyOptionsView: some View {
|
||||
VStack {
|
||||
ZStack {
|
||||
VStack(spacing: 20) {
|
||||
Text(String(localized: "purchase_view_title"))
|
||||
.font(.body)
|
||||
.bold()
|
||||
.foregroundColor(textColor)
|
||||
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
HStack {
|
||||
ForEach(iapManager.sortedSubscriptionKeysByPriceOptions) { product in
|
||||
Button(action: {
|
||||
purchase(product: product)
|
||||
}, label: {
|
||||
Text("\(product.displayPrice)\n\(product.displayName)")
|
||||
.foregroundColor(.white)
|
||||
.bold()
|
||||
.frame(maxWidth: .infinity)
|
||||
.contentShape(Rectangle())
|
||||
})
|
||||
.padding()
|
||||
.frame(maxWidth: .infinity)
|
||||
.background(RoundedRectangle(cornerRadius: 10).fill(iapManager.colorForIAPButton(iapIdentifier: product.id)))
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding([.leading, .trailing])
|
||||
.frame(minWidth: 0, maxWidth: .infinity)
|
||||
|
||||
}
|
||||
.background(.ultraThinMaterial)
|
||||
.frame(minWidth: 0, maxWidth: .infinity)
|
||||
}
|
||||
.background(.clear)
|
||||
}
|
||||
|
||||
private var successView: some View {
|
||||
HStack {
|
||||
Text("it worked")
|
||||
}
|
||||
.background(.green)
|
||||
}
|
||||
|
||||
private var errorView: some View {
|
||||
HStack {
|
||||
Text("something broke")
|
||||
}
|
||||
.background(.red)
|
||||
}
|
||||
|
||||
private var subscribedView: some View {
|
||||
VStack(alignment: .leading) {
|
||||
Text(String(localized: "purchase_view_current_subscription"))
|
||||
.font(.title3)
|
||||
.padding(.leading)
|
||||
|
||||
Divider()
|
||||
|
||||
if let currentProduct = iapManager.currentSubscription,
|
||||
let value = iapManager.subscriptions[currentProduct] {
|
||||
HStack {
|
||||
VStack (alignment: .leading, spacing: 10) {
|
||||
Text(currentProduct.displayName)
|
||||
.font(.title3)
|
||||
Text(currentProduct.displayPrice)
|
||||
.font(.title3)
|
||||
}.padding([.leading, .trailing])
|
||||
|
||||
ForEach(value!.status, id: \.self) { singleStatus in
|
||||
StatusInfoView(product: currentProduct, status: singleStatus)
|
||||
.padding([.leading])
|
||||
.font(.body)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button(action: {
|
||||
showManageSubClosure?()
|
||||
}, label: {
|
||||
Text(String(localized: "purchase_view_cancel"))
|
||||
.foregroundColor(.red)
|
||||
})
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding([.bottom])
|
||||
.multilineTextAlignment(.center)
|
||||
|
||||
Divider()
|
||||
|
||||
showOtherSubOptions
|
||||
}
|
||||
}
|
||||
|
||||
private var showOtherSubOptions: some View {
|
||||
VStack (spacing: 10) {
|
||||
HStack {
|
||||
ForEach(iapManager.sortedSubscriptionKeysByPriceOptions, id: \.self) { product in
|
||||
if product.id != iapManager.nextRenewllOption?.id {
|
||||
Button(action: {
|
||||
purchase(product: product)
|
||||
}, label: {
|
||||
Text("\(product.displayPrice)\n\(product.displayName)")
|
||||
.foregroundColor(.white)
|
||||
.font(.headline)
|
||||
})
|
||||
.contentShape(Rectangle())
|
||||
.padding()
|
||||
.frame(maxWidth: .infinity)
|
||||
.background(RoundedRectangle(cornerRadius: 10).fill(iapManager.colorForIAPButton(iapIdentifier: product.id)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding([.leading, .trailing])
|
||||
}
|
||||
|
||||
private var purchasingView: some View {
|
||||
HStack {
|
||||
Text("purcasing")
|
||||
}
|
||||
.background(.yellow)
|
||||
}
|
||||
|
||||
private func purchase(product: Product) {
|
||||
isPurchasing = true
|
||||
Task {
|
||||
do {
|
||||
if let _ = try await iapManager.purchase(product) {
|
||||
viewStatus = .success
|
||||
}
|
||||
} catch {
|
||||
viewStatus = .error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct PurchaseButtonView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
PurchaseButtonView(height: 175, iapManager: IAPManager())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user