Files
swiftGrammar/AIGrammar/View/SettingsView.swift

292 lines
11 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// SettingsView.swift
// AIGrammar
//
// Created by oscar on 2024/3/27.
//
import SwiftUI
import ToastUI
import SafariServices
import FirebaseAnalytics
import SwiftyBeaver
struct FullScreenSafariView: UIViewControllerRepresentable {
let url: URL
var onDismiss: (() -> Void)?
func makeUIViewController(context: UIViewControllerRepresentableContext<FullScreenSafariView>) -> SFSafariViewController {
let safariViewController = SFSafariViewController(url: url)
safariViewController.delegate = context.coordinator
return safariViewController
}
func updateUIViewController(_ uiViewController: SFSafariViewController, context: UIViewControllerRepresentableContext<FullScreenSafariView>) {
//
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, SFSafariViewControllerDelegate {
var parent: FullScreenSafariView
init(_ parent: FullScreenSafariView) {
self.parent = parent
}
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
parent.onDismiss?()
}
}
}
struct SettingsView: View {
@EnvironmentObject var globalEnv: GlobalEnvironment //
@State private var isLoading = false //
@State private var showingToast = false // toast
@State private var toastText = ""
@State private var showVIPPaymentView = false
@EnvironmentObject var iapManager: IAPManager // IAPManager
@State private var showingFullSafari = false
@State private var currentSafariURL = globalEnvironment.userTermsURL
@State private var showingAdvancedSettings = false //
@State private var useSandboxEnvironment = false
@State private var useDevelopmentEnvironment = false
@State private var showingLogShareSheet = false
@State private var logFileURL: URL?
var body: some View {
NavigationView {
ScrollView {
VStack(spacing: 0) {
// Upgrade to Premium
settingItem(icon: "arrow.up.circle", text: "Upgrade to Premium", isBold: true)
.onTapGesture {
showVIPPaymentView = true
//
Analytics.logEvent(globalAnalyticsEvents.eventEnterPurchase, parameters: [
globalAnalyticsEvents.keyPurchaseEntry: globalAnalyticsEvents.valEntrySettingsBtn as NSObject,
globalAnalyticsEvents.keyDeviceID: globalEnvironment.deviceID as NSObject
])
}
// Feedback
settingItem(icon: "bubble.left", text: "Feedback")
.onTapGesture {
// Assuming there's a way to open App Store Feedback
openAppStoreFeedback()
}
// About
settingItem(icon: "info.circle", text: "Terms of Use")
.onTapGesture {
// Code to show About View
self.showingFullSafari = true
currentSafariURL = globalEnvironment.userTermsURL
}
// About
settingItem(icon: "info.circle", text: "Privacy Policy")
.onTapGesture {
// Code to show About View
self.showingFullSafari = true
currentSafariURL = globalEnvironment.userPrivacyURL
}
// Restore Purchases
settingItem(icon: "arrow.clockwise.circle", text: "Restore Purchases", isBold: true)
.onTapGesture {
restorePurchase()
}
}
.fullScreenCover(isPresented: $showingFullSafari) {
FullScreenSafariView(url: URL(string: currentSafariURL)!, onDismiss: {
self.showingFullSafari = false
})
}
// UI
gestureArea
if showingAdvancedSettings {
VStack {
Toggle("Sandbox", isOn: $useSandboxEnvironment)
Toggle("TestEnv", isOn: $useDevelopmentEnvironment)
HStack {
Button("View Logs") {
if let logURL = getLogFileURL() {
if FileManager.default.fileExists(atPath: logURL.path) {
logger.info("Log file exists: \(logURL.path)")
self.logFileURL = logURL
self.showingLogShareSheet = true
} else {
logger.error("Log file does not exist.")
self.toastText = "Log file not found."
self.showingToast = true
}
} else {
self.toastText = "Log file not found."
self.showingToast = true
}
}
Spacer()
Button("Save") {
saveSettings()
showingAdvancedSettings = false
}
}
.padding(.horizontal,15)
.padding(.top, 15)
}
.padding(.vertical,10)
.padding(.horizontal, 20)
.background(Color.white) // Ensure background fills the view
.cornerRadius(5)
}
}
.background(Color.pink.opacity(0.2)) // Ensure background fills the view
.navigationBarTitle("Settings", displayMode: .inline)
.fullScreenCover(isPresented: $showVIPPaymentView) {
VIPPaymentView()
}
.onDisappear {
self.showingAdvancedSettings = false //
}
}
.sheet(isPresented: $showingLogShareSheet) {
if let url = logFileURL {
ShareSheetLog(activityItems: [url])
}
}
.toast(isPresented: $showingToast, dismissAfter: globalEnvironment.toastPresentMsNormal) {
HStack {
Image(systemName: "exclamationmark.bubble")
.foregroundColor(.yellow)
Text(toastText)
.foregroundColor(.black)
}
.padding()
.background(Color.white)
.cornerRadius(8)
.shadow(radius: 10)
}
//
if isLoading {
LoadingView()
}
}
//
private var gestureArea: some View {
Color.clear
.contentShape(Rectangle()) //
.frame(height: 50) //
.gesture(
DragGesture(minimumDistance: 50, coordinateSpace: .global)
.onEnded { value in
//
if abs(value.translation.width) > 50 && abs(value.translation.height) < 100 {
//
logger.info("Advanced Settings.")
showingAdvancedSettings.toggle()
}
}
)
}
//
private func saveSettings() {
globalEnvironment.SetEnv(isSandBox: useSandboxEnvironment, isTestEnv: useDevelopmentEnvironment)
}
@ViewBuilder
private func settingItem(icon: String, text: String, isBold: Bool = false) -> some View {
HStack {
Image(systemName: icon) // Icon on the left side
.foregroundColor(.gray)
Text(text)
.font(.subheadline)
.fontWeight(isBold ? .bold : .regular) // Conditional bold based on isBold parameter
.padding(4)
Spacer()
}
.padding()
.background(Color.white) // Background for each setting item
.padding(.horizontal, 0) // Add some horizontal padding
// Indent divider to align with the text and extend to the edge
Divider()
.padding(.leading, 30)
.padding(.trailing, 10)
}
private func openAppStoreFeedback() {
let appID = globalEnvironment.APPID // ID
let urlStr = "https://apps.apple.com/app/id\(appID)?action=write-review"
if let url = URL(string: urlStr) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
}
func restorePurchase(){
Task {
await iapManager.restorePurchases() { result in
switch result {
case .success(_):
self.toastText = "Restored Sucess!"
self.showingToast = true
case .failure(_):
self.toastText = "Oh, something went wrong, please try again later."
self.showingToast = true
}
}
}
}
//
func loadData() {
isLoading = true
}
func loadComplete(){
isLoading = false
}
}
struct ShareSheetLog: UIViewControllerRepresentable {
var activityItems: [Any]
func makeUIViewController(context: Context) -> UIActivityViewController {
let controller = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
return controller
}
func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {
// Nothing to update here
}
}
struct SettingsView_Previews: PreviewProvider {
static var previews: some View {
SettingsView()
}
}
#Preview {
SettingsView()
}