87 lines
3.0 KiB
Swift
87 lines
3.0 KiB
Swift
import Foundation
|
||
import StoreKit
|
||
import SwiftUI
|
||
|
||
public struct SponsorView: View {
|
||
@Environment(\.openURL) private var openURL
|
||
|
||
@State private var isLoading = true
|
||
@State private var products: [Product] = []
|
||
@State private var subscriptionError: Error?
|
||
@State private var isPurchasing = false
|
||
@State private var alert: Alert?
|
||
|
||
public init() {}
|
||
public var body: some View {
|
||
FormView {
|
||
Section {
|
||
EmptyView()
|
||
} footer: {
|
||
Text("**If I’ve defended your modern life, please consider sponsoring me.**")
|
||
.frame(maxWidth: .infinity, alignment: .leading)
|
||
}
|
||
|
||
Section("Without commission") {
|
||
FormButton("GitHub Sponsor (recommended)") {
|
||
openURL(URL(string: "https://github.com/sponsors/nekohasekai")!)
|
||
}
|
||
FormButton("Other methods") {
|
||
openURL(URL(string: "https://sekai.icu/sponsor/")!)
|
||
}
|
||
}
|
||
Section("Via App Store") {
|
||
if isLoading {
|
||
ProgressView()
|
||
.onAppear {
|
||
Task.detached {
|
||
await loadProducts()
|
||
}
|
||
}
|
||
} else if let subscriptionError {
|
||
Text("Sponsor via App Store not available: \(subscriptionError.localizedDescription)")
|
||
} else {
|
||
ForEach(products, id: \.id) { it in
|
||
FormButton(it.displayName) {
|
||
isPurchasing = true
|
||
Task.detached {
|
||
do {
|
||
let result = try await it.purchase()
|
||
switch result {
|
||
case .success:
|
||
alert = Alert(title: Text("Success"), message: Text("Thank u."))
|
||
case .pending:
|
||
break
|
||
case .userCancelled:
|
||
break
|
||
}
|
||
} catch {
|
||
alert = Alert(error)
|
||
}
|
||
isPurchasing = false
|
||
}
|
||
}
|
||
.disabled(isPurchasing)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.alertBinding($alert)
|
||
.navigationTitle("Sponsor")
|
||
#if os(iOS)
|
||
.navigationBarTitleDisplayMode(.inline)
|
||
#endif
|
||
}
|
||
|
||
private func loadProducts() async {
|
||
defer {
|
||
isLoading = false
|
||
}
|
||
do {
|
||
let productIds = ["sponsor_1_1", "sponsor_10", "sponsor_100"]
|
||
products = try await Product.products(for: productIds)
|
||
} catch {
|
||
subscriptionError = error
|
||
}
|
||
}
|
||
}
|