201 lines
8.6 KiB
Swift
201 lines
8.6 KiB
Swift
//
|
||
// IAPView.swift
|
||
// AIGrammar
|
||
//
|
||
// Created by oscar on 2024/7/9.
|
||
//
|
||
import SwiftUI
|
||
import FirebaseAnalytics
|
||
|
||
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 = [
|
||
("Weekly", "$4.99 / week", "Billed as one payment of $4.99", "weekly", IAPProduct.premiumFeature1, "Billed Weekly"),
|
||
("Monthly", "$9.99 / month", "Billed as one payment of $9.99", "monthly", IAPProduct.premiumFeature2, "Billed Monthly"),
|
||
("Annual", "$4.16 / month", "Billed as one payment of $49.99", "yearly", IAPProduct.premiumFeature3, "Billed Yearly")
|
||
]
|
||
|
||
@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)
|
||
}
|
||
}
|
||
}
|
||
|
||
VStack(alignment: .leading) { // 使用 VStack 包装整个 ForEach 循环,并指定左对齐
|
||
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 == "Annual" {
|
||
// 特别为 "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(.caption)
|
||
Text(products[index].2)
|
||
.font(.subheadline)
|
||
}
|
||
.frame(maxWidth: .infinity, alignment: .leading) // 使每个 HStack 占据整个宽度,并左对齐
|
||
}
|
||
.padding(.vertical, 10)
|
||
.background(self.selectedProductIndex == index ? Color.yellow : Color.clear)
|
||
.cornerRadius(5)
|
||
.padding(.horizontal, 20) // 增加水平缩进
|
||
.onTapGesture {
|
||
self.selectedProductIndex = index
|
||
self.selectedPlanText = products[index].5
|
||
}
|
||
}
|
||
.frame(maxWidth: .infinity, alignment: .leading) // 使每个 HStack 占据整个宽度,并左对齐
|
||
}
|
||
}
|
||
.padding(.horizontal, 5) // 增加水平缩进
|
||
|
||
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, 20)
|
||
|
||
Text((selectedPlanText ) + ", Cancel Anytime")
|
||
.font(.footnote)
|
||
.padding(.vertical, 5)
|
||
}
|
||
.navigationBarHidden(true)
|
||
}
|
||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||
.background(Color(.systemBackground))
|
||
.toast(isPresented: $showingToast, dismissAfter: globalEnvironment.toastPresentMsNormal, 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)")
|
||
|
||
// 记录事件
|
||
Analytics.logEvent(globalAnalyticsEvents.eventPurchase, parameters: [
|
||
globalAnalyticsEvents.keyPurchaseItem: productId.rawValue as NSObject,
|
||
globalAnalyticsEvents.keyDeviceID: globalEnvironment.deviceID as NSObject
|
||
])
|
||
|
||
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()
|
||
}
|
||
}
|
||
|