Files
swiftGrammar/AIGrammar/View/IAPView.swift
2024-08-12 10:49:20 +08:00

191 lines
7.7 KiB
Swift

//
// IAPView.swift
// AIGrammar
//
// Created by oscar on 2024/7/9.
//
import SwiftUI
struct VIPPaymentView: View {
@Environment(\.presentationMode) var presentationMode
@State private var showingToast = false
@State private var toastText = ""
let features = ["Grammar Check & Spelling Correction", "Words & Dictionary", "Translate"]
let freeValues = ["2 Times / Day", "2 Times / Day", "2 Times / Day"]
let premiumValues = ["Unlimited", "Unlimited", "Unlimited"]
let products = [
("Premium Weekly", "$4.99", "Billed Weekly", "weekly", IAPProduct.premiumFeature1),
("Premium Monthly", "$9.99 / month", "Billed Monthly", "monthly", IAPProduct.premiumFeature2),
("Premium Yearly", "$49.99 / year", "Billed Yearly", "yearly", IAPProduct.premiumFeature3)
]
@State private var selectedProductIndex: Int = 1 //
@State private var selectedPlanText: String = "Billed Monthly"
@EnvironmentObject var iapManager: IAPManager // IAPManager
var body: some View {
NavigationView {
VStack {
HStack {
Text("PREMIUM")
.bold()
.foregroundColor(Color(red: 1.0, green: 0.8, blue: 0.0)) //
//.foregroundColor(.yellow)
.padding()
.background(Color.orange)
.cornerRadius(20)
Spacer()
Button("Close") {
presentationMode.wrappedValue.dismiss()
}
}
.padding()
List {
Section(header: Text("Get Premium Features").font(.headline)) {
HStack {
Text("Features")
.frame(width: 120, alignment: .leading)
Spacer()
Text("Free")
.frame(width: 120, alignment: .center)
Spacer()
Text("Premium")
.frame(width: 80, alignment: .center)
}
.font(.headline)
ForEach(Array(zip(features, zip(freeValues, premiumValues))), id: \.0) { item in
HStack {
Text(item.0)
.frame(width: 120, alignment: .leading)
Spacer()
Text(item.1.0) // Free values
.frame(width: 120, alignment: .center)
Spacer()
Text(item.1.1) // Premium values
.frame(width: 80, alignment: .center)
}
.font(.subheadline)
}
}
}
ForEach(products.indices, id: \.self) { index in
Button(action: {
// do someting
}) {
HStack {
Image(systemName: selectedProductIndex == index ? "checkmark.circle.fill" : "circle")
.foregroundColor(selectedProductIndex == index ? .green : .secondary)
.padding(.horizontal, 4)
VStack(alignment: .leading) {
if products[index].0 == "Premium Yearly" {
// "Premium Yearly"
Text(products[index].0) + Text(" ⚡️") + Text(" 58% off")
.bold()
.foregroundColor(.red) // 使
.font(.subheadline)
} else {
Text(products[index].0)
}
Text(products[index].1)
.font(.subheadline)
}
Spacer()
Text(products[index].2)
.font(.subheadline)
.foregroundColor(.secondary)
}
.padding(.vertical, 10)
.background(self.selectedProductIndex == index ? Color.yellow : Color.clear)
.cornerRadius(5)
.padding(.horizontal, 20) //
.onTapGesture {
self.selectedProductIndex = index
self.selectedPlanText = products[index].2
}
}
}
Spacer()
Button("Purchase") {
// Handle purchase logic here
buyProduct()
}
.padding(.vertical, 15)
.padding(.horizontal, 80)
.foregroundColor(.white)
.background(Color.green)
.cornerRadius(15)
.frame(minWidth: 0, maxWidth: .infinity)
.shadow(radius: 2) //
.font(.headline) //
.padding(.top, 50)
Text((selectedPlanText ) + ", Cancel Anytime")
.font(.footnote)
.padding(.vertical, 5)
}
.navigationBarHidden(true)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color(.systemBackground))
.toast(isPresented: $showingToast, dismissAfter: 5.0, onDismiss: {
// Toast
presentationMode.wrappedValue.dismiss() //
}) {
HStack {
Image(systemName: "exclamationmark.bubble")
.foregroundColor(.yellow)
Text(toastText)
.foregroundColor(.black)
}
.padding()
.background(Color.white)
.cornerRadius(8)
.shadow(radius: 10)
}
}
private func buyProduct() {
let productId = products[selectedProductIndex].4
logger.info("selected productId: \(productId.rawValue)")
if let product = iapManager.products.first(where: { $0.id == productId.rawValue }) {
Task {
await iapManager.buy(product: product) { result in
switch result {
case .success(let message):
self.toastText = message
self.showingToast = true
presentationMode.wrappedValue.dismiss()
// vip
InitApp.shared.refreshUserInfo()
case .failure(let error):
self.toastText = error.localizedDescription
self.showingToast = true
}
}
}
} else {
logger.error("Product not found")
toastText = "Error loading product list, please try again later"
self.showingToast = true
}
}
}
struct VIPPaymentView_Previews: PreviewProvider {
static var previews: some View {
VIPPaymentView()
}
}