Files
Reflect/Shared/views/PurchaseButtonView.swift
2022-12-27 15:27:16 -06:00

237 lines
9.9 KiB
Swift

//
// PurchaseButtonView.swift
// Feels
//
// Created by Trey Tartt on 7/7/22.
//
import SwiftUI
import StoreKit
struct PurchaseButtonView: View {
@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
@AppStorage(UserDefaultsStore.Keys.firstLaunchDate.rawValue, store: GroupUserDefaults.groupDefaults) private var firstLaunchDate = Date()
var iapManager: IAPManager
private let showCountdownTimer: Bool
private let showManageSubClosure: (() -> Void)?
public init(iapManager: IAPManager, showManageSubClosure: (() -> Void)? = nil, showCountdownTimer: Bool = false) {
self.showManageSubClosure = showManageSubClosure
self.iapManager = iapManager
self.showCountdownTimer = showCountdownTimer
}
var body: some View {
ZStack {
// if we should show the iap warning that means no purchase which means
// we should show buy options
switch iapManager.showIAPWarning {
case true:
VStack {
buyOptionsView
.background(theme.currentTheme.secondaryBGColor)
}
case false:
subscribedView
.background(theme.currentTheme.secondaryBGColor)
}
}
}
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)
.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 {
theme.currentTheme.secondaryBGColor
if iapManager.isLoadingSubscriptions {
VStack(spacing: 20) {
Text(String(localized: "purchase_view_loading"))
.font(.body)
.bold()
.frame(minWidth: 0, maxWidth: .infinity, alignment: .center)
ProgressView()
}
} else {
VStack(spacing: 20) {
Text(String(localized: "purchase_view_title"))
.font(.body)
.bold()
.foregroundColor(textColor)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
.padding(.top)
if showCountdownTimer {
if let date = Calendar.current.date(byAdding: .day, value: 30, to: firstLaunchDate) {
HStack {
if iapManager.daysLeftBeforeIAP > 0 {
Text(String(localized: "purchase_view_current_subscription_expires_in"))
.font(.body)
.bold()
.foregroundColor(textColor)
Text(date, style: .relative)
.font(.body)
.bold()
.foregroundColor(textColor)
} else {
Text(String(localized: "purchase_view_current_subscription_expired_on"))
.font(.body)
.bold()
.foregroundColor(textColor)
Text(date, style: .date)
.font(.body)
.bold()
.foregroundColor(textColor)
}
}
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
}
Text(String(localized: "purchase_view_current_why_subscribe"))
.font(.body)
.bold()
.foregroundColor(textColor)
}
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())
.frame(height: 65)
})
.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 subscribedView: some View {
VStack(alignment: .leading) {
Text(String(localized: "purchase_view_current_subscription"))
.font(.title3)
.padding([.leading, .top])
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 func purchase(product: Product) {
Task {
try await iapManager.purchase(product)
}
}
}
struct PurchaseButtonView_Previews: PreviewProvider {
static var previews: some View {
PurchaseButtonView(iapManager: IAPManager())
}
}