// // SettingsTabView.swift // Nextcloud Cookbook iOS Client // // Created by Vincent Meilinger on 29.05.25. // import Foundation import SwiftUI struct SettingsTabView: View { @ObservedObject var userSettings = UserSettings.shared @State private var avatarImage: UIImage? @State private var userData: UserData? @State private var showAlert: Bool = false @State private var alertType: SettingsAlert = .NONE @State private var presentLoginSheet: Bool = false enum SettingsAlert { case LOG_OUT, DELETE_CACHE, NONE func getTitle() -> String { switch self { case .LOG_OUT: return "Log out" case .DELETE_CACHE: return "Delete local data" default: return "Please confirm your action." } } func getMessage() -> String { switch self { case .LOG_OUT: return "Are you sure that you want to log out of your account?" case .DELETE_CACHE: return "Are you sure that you want to delete the downloaded recipes? This action will not affect any recipes stored on your server." default: return "" } } } var body: some View { Form { Section { if userSettings.authString.isEmpty { HStack(alignment: .center) { if let avatarImage = avatarImage { Image(uiImage: avatarImage) .resizable() .clipShape(Circle()) .frame(width: 100, height: 100) } if let userData = userData { VStack(alignment: .leading) { Text(userData.userDisplayName) .font(.title) .padding(.leading) Text("Username: \(userData.userId)") .font(.subheadline) .padding(.leading) // TODO: Add actions } } Spacer() } Button("Log out") { print("Log out.") alertType = .LOG_OUT showAlert = true } .tint(.red) } else { Button("Log in") { print("Log in.") presentLoginSheet.toggle() } } } header: { Text("Nextcloud") } footer: { Text("Log in to your Nextcloud account to sync your recipes. This requires a Nextcloud server with the Nextcloud Cookbook application installed.") } Section { Toggle(isOn: $userSettings.expandNutritionSection) { Text("Expand nutrition section") } Toggle(isOn: $userSettings.expandKeywordSection) { Text("Expand keyword section") } Toggle(isOn: $userSettings.expandInfoSection) { Text("Expand information section") } } header: { Text("Recipes") } footer: { Text("Configure which sections in your recipes are expanded by default.") } Section { Toggle(isOn: $userSettings.keepScreenAwake) { Text("Keep screen awake when viewing recipes") } } Section { HStack { Text("Decimal number format") Spacer() Picker("", selection: $userSettings.decimalNumberSeparator) { Text("Point (e.g. 1.42)").tag(".") Text("Comma (e.g. 1,42)").tag(",") } .pickerStyle(.menu) } } footer: { Text("This setting will take effect after the app is restarted. It affects the adjustment of ingredient quantities.") } Section { Toggle(isOn: $userSettings.storeRecipes) { Text("Offline recipes") } Toggle(isOn: $userSettings.storeImages) { Text("Store recipe images locally") } Toggle(isOn: $userSettings.storeThumb) { Text("Store recipe thumbnails locally") } } header: { Text("Downloads") } footer: { Text("Configure what is stored on your device.") } Section { Picker("Language", selection: $userSettings.language) { ForEach(SupportedLanguage.allValues, id: \.self) { lang in Text(lang.descriptor()).tag(lang.rawValue) } } } footer: { Text("If \'Same as Device\' is selected and your device language is not supported yet, this option will default to english.") } Section { Link("Visit the GitHub page", destination: URL(string: "https://github.com/VincentMeilinger/Nextcloud-Cookbook-iOS")!) } header: { Text("About") } footer: { Text("If you are interested in contributing to this project or simply wish to review its source code, we encourage you to visit the GitHub repository for this application.") } Section { Link("Get support", destination: URL(string: "https://vincentmeilinger.github.io/Nextcloud-Cookbook-Client-Support/")!) } header: { Text("Support") } footer: { Text("If you have any inquiries, feedback, or require assistance, please refer to the support page for contact information.") } Section { Button("Delete local data") { print("Clear cache.") alertType = .DELETE_CACHE showAlert = true } .tint(.red) } header: { Text("Other") } footer: { Text("Deleting local data will not affect the recipe data stored on your server.") } Section(header: Text("Acknowledgements")) { VStack(alignment: .leading) { if let url = URL(string: "https://github.com/scinfu/SwiftSoup") { Link("SwiftSoup", destination: url) .font(.headline) Text("An HTML parsing and web scraping library for Swift. Used for importing schema.org recipes from websites.") } } VStack(alignment: .leading) { if let url = URL(string: "https://github.com/techprimate/TPPDF") { Link("TPPDF", destination: url) .font(.headline) Text("A simple-to-use PDF builder for Swift. Used for generating recipe PDF documents.") } } } } .navigationTitle("Settings") .alert(alertType.getTitle(), isPresented: $showAlert) { Button("Cancel", role: .cancel) { } if alertType == .DELETE_CACHE { Button("Delete", role: .destructive) { deleteCachedData() } } } message: { Text(alertType.getMessage()) } .task { await getUserData() } .sheet(isPresented: $presentLoginSheet, onDismiss: {}) { V2LoginView() } } func getUserData() async { let (data, _) = await NextcloudApi.getAvatar() let (userData, _) = await NextcloudApi.getHoverCard() DispatchQueue.main.async { self.avatarImage = data self.userData = userData } } func deleteCachedData() { print("TODO: Delete cached data\n") } }