import SwiftUI import SFSafeSymbols struct SettingsView: View { @EnvironmentObject var database: Database @Binding var isPresented: Bool @AppStorage("authKey") private var serverAuthenticationKey: String = "" @State private var imageCacheSize: Int = 0 var body: some View { NavigationView { VStack(alignment: .leading, spacing: 3) { Text("Authentication") .font(.footnote) .textCase(.uppercase) .foregroundColor(.secondary) .padding(.top) Group { FancyTextField(text: $serverAuthenticationKey, icon: .key, placeholder: "Server key") }.padding(.horizontal) Text("Statistics") .font(.footnote) .textCase(.uppercase) .foregroundColor(.secondary) .padding(.top) Group { SettingsStatisticRow(label: "Caps", value: "\(database.numberOfCaps)") SettingsStatisticRow(label: "Total images", value: "\(database.numberOfImages)") SettingsStatisticRow(label: "Images per cap", value: String(format: "%.1f", database.averageImageCount)) }.padding(.horizontal) Text("Classifier") .font(.footnote) .textCase(.uppercase) .foregroundColor(.secondary) .padding(.top) Group { SettingsStatisticRow(label: "Server Version", value: "\(database.serverClassifierVersion)") SettingsStatisticRow(label: "Local Version", value: "\(database.localClassifierVersion)") SettingsStatisticRow(label: "Recognized caps", value: "\(database.classifierClassCount)") HStack { Spacer() Button(action: updateClassifierVersion) { Label("Refresh", systemSymbol: .arrowCounterclockwise) } .disabled(database.classifierDownloadProgress != nil) .padding() if database.localClassifierVersion != database.serverClassifierVersion { Button(action: downloadNewClassifier) { Label("Download", systemSymbol: .squareAndArrowDown) } .disabled(database.classifierDownloadProgress != nil) .padding() } Spacer() } if let progress = database.classifierDownloadProgress { ClassifierDownloadView(progress: progress) } }.padding(.horizontal) Text("Storage") .font(.footnote) .textCase(.uppercase) .foregroundColor(.secondary) .padding(.top) Group { SettingsStatisticRow(label: "Image cache", value: byteString(imageCacheSize)) SettingsStatisticRow(label: "Database", value: byteString(database.databaseSize)) SettingsStatisticRow(label: "Classifier", value: byteString(database.classifierSize)) HStack { Spacer() Button(action: clearImageCache) { Label("Clear image cache", systemSymbol: .trash) } .padding() Spacer() } }.padding(.horizontal) Spacer() } .padding(.horizontal) .navigationTitle("Info") .onAppear(perform: updateImageCacheSize) } } private func updateImageCacheSize() { imageCacheSize = database.imageCacheSize() } private func clearImageCache() { Task { database.clearImageCache() DispatchQueue.main.async { updateImageCacheSize() } } } private func downloadNewClassifier() { Task { // Ensure that correct version is saved await database.updateServerClassifierVersion() await database.downloadClassifier() } } private func updateClassifierVersion() { Task { await database.updateServerClassifierVersion() } } private func hide() { isPresented = false } private func byteString(_ count: Int) -> String { ByteCountFormatter.string(fromByteCount: Int64(count), countStyle: .file) } } struct SettingsView_Previews: PreviewProvider { static var previews: some View { SettingsView(isPresented: .constant(true)) .environmentObject(Database.mock) //.previewLayout(.fixed(width: 375, height: 410)) } }