Store a _groceryState JSON field on each recipe to track which ingredients have been added, completed, or removed. Uses per-item last-writer-wins conflict resolution with ISO 8601 timestamps. Debounced push (2s) avoids excessive API calls; pull reconciles on recipe open and app launch. Includes a settings toggle to enable/disable sync. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
183 lines
6.3 KiB
Swift
183 lines
6.3 KiB
Swift
//
|
|
// UserSettings.swift
|
|
// Nextcloud Cookbook iOS Client
|
|
//
|
|
// Created by Vincent Meilinger on 15.09.23.
|
|
//
|
|
|
|
|
|
import Foundation
|
|
import Combine
|
|
|
|
class UserSettings: ObservableObject {
|
|
|
|
static let shared = UserSettings()
|
|
|
|
@Published var username: String {
|
|
didSet {
|
|
UserDefaults.standard.set(username, forKey: "username")
|
|
}
|
|
}
|
|
|
|
@Published var token: String {
|
|
didSet {
|
|
UserDefaults.standard.set(token, forKey: "token")
|
|
}
|
|
}
|
|
|
|
@Published var authString: String {
|
|
didSet {
|
|
UserDefaults.standard.set(authString, forKey: "authString")
|
|
}
|
|
}
|
|
|
|
@Published var serverAddress: String {
|
|
didSet {
|
|
UserDefaults.standard.set(serverAddress, forKey: "serverAddress")
|
|
}
|
|
}
|
|
|
|
@Published var serverProtocol: String {
|
|
didSet {
|
|
UserDefaults.standard.set(serverProtocol, forKey: "serverProtocol")
|
|
}
|
|
}
|
|
|
|
@Published var cookbookApiVersion: CookbookApiVersion {
|
|
didSet {
|
|
UserDefaults.standard.set(cookbookApiVersion, forKey: "cookbookApiVersion")
|
|
}
|
|
}
|
|
|
|
@Published var onboarding: Bool {
|
|
didSet {
|
|
UserDefaults.standard.set(onboarding, forKey: "onboarding")
|
|
}
|
|
}
|
|
|
|
@Published var defaultCategory: String {
|
|
didSet {
|
|
UserDefaults.standard.set(defaultCategory, forKey: "defaultCategory")
|
|
}
|
|
}
|
|
|
|
@Published var language: String {
|
|
didSet {
|
|
UserDefaults.standard.set(language, forKey: "language")
|
|
}
|
|
}
|
|
|
|
@Published var storeRecipes: Bool {
|
|
didSet {
|
|
UserDefaults.standard.set(storeRecipes, forKey: "storeRecipes")
|
|
}
|
|
}
|
|
|
|
@Published var storeImages: Bool {
|
|
didSet {
|
|
UserDefaults.standard.set(storeImages, forKey: "storeImages")
|
|
}
|
|
}
|
|
|
|
@Published var storeThumb: Bool {
|
|
didSet {
|
|
UserDefaults.standard.set(storeThumb, forKey: "storeThumb")
|
|
}
|
|
}
|
|
|
|
@Published var lastUpdate: Date {
|
|
didSet {
|
|
UserDefaults.standard.set(lastUpdate, forKey: "lastUpdate")
|
|
}
|
|
}
|
|
|
|
@Published var expandNutritionSection: Bool {
|
|
didSet {
|
|
UserDefaults.standard.set(expandNutritionSection, forKey: "expandNutritionSection")
|
|
}
|
|
}
|
|
|
|
@Published var expandKeywordSection: Bool {
|
|
didSet {
|
|
UserDefaults.standard.set(expandKeywordSection, forKey: "expandKeywordSection")
|
|
}
|
|
}
|
|
|
|
@Published var expandInfoSection: Bool {
|
|
didSet {
|
|
UserDefaults.standard.set(expandInfoSection, forKey: "expandInfoSection")
|
|
}
|
|
}
|
|
|
|
@Published var keepScreenAwake: Bool {
|
|
didSet {
|
|
UserDefaults.standard.set(keepScreenAwake, forKey: "keepScreenAwake")
|
|
}
|
|
}
|
|
|
|
@Published var decimalNumberSeparator: String {
|
|
didSet {
|
|
UserDefaults.standard.set(decimalNumberSeparator, forKey: "decimalNumberSeparator")
|
|
}
|
|
}
|
|
|
|
@Published var groceryListMode: String {
|
|
didSet {
|
|
UserDefaults.standard.set(groceryListMode, forKey: "groceryListMode")
|
|
}
|
|
}
|
|
|
|
@Published var remindersListIdentifier: String {
|
|
didSet {
|
|
UserDefaults.standard.set(remindersListIdentifier, forKey: "remindersListIdentifier")
|
|
}
|
|
}
|
|
|
|
@Published var grocerySyncEnabled: Bool {
|
|
didSet {
|
|
UserDefaults.standard.set(grocerySyncEnabled, forKey: "grocerySyncEnabled")
|
|
}
|
|
}
|
|
|
|
init() {
|
|
self.username = UserDefaults.standard.object(forKey: "username") as? String ?? ""
|
|
self.token = UserDefaults.standard.object(forKey: "token") as? String ?? ""
|
|
self.authString = UserDefaults.standard.object(forKey: "authString") as? String ?? ""
|
|
self.serverAddress = UserDefaults.standard.object(forKey: "serverAddress") as? String ?? ""
|
|
self.serverProtocol = UserDefaults.standard.object(forKey: "serverProtocol") as? String ?? "https://"
|
|
self.cookbookApiVersion = UserDefaults.standard.object(forKey: "cookbookApiVersion") as? CookbookApiVersion ?? .v1
|
|
self.onboarding = UserDefaults.standard.object(forKey: "onboarding") as? Bool ?? true
|
|
self.defaultCategory = UserDefaults.standard.object(forKey: "defaultCategory") as? String ?? ""
|
|
self.language = UserDefaults.standard.object(forKey: "language") as? String ?? SupportedLanguage.DEVICE.rawValue
|
|
self.storeRecipes = UserDefaults.standard.object(forKey: "storeRecipes") as? Bool ?? true
|
|
self.storeImages = UserDefaults.standard.object(forKey: "storeImages") as? Bool ?? true
|
|
self.storeThumb = UserDefaults.standard.object(forKey: "storeThumb") as? Bool ?? true
|
|
self.lastUpdate = UserDefaults.standard.object(forKey: "lastUpdate") as? Date ?? Date.distantPast
|
|
self.expandNutritionSection = UserDefaults.standard.object(forKey: "expandNutritionSection") as? Bool ?? false
|
|
self.expandKeywordSection = UserDefaults.standard.object(forKey: "expandKeywordSection") as? Bool ?? false
|
|
self.expandInfoSection = UserDefaults.standard.object(forKey: "expandInfoSection") as? Bool ?? false
|
|
self.keepScreenAwake = UserDefaults.standard.object(forKey: "keepScreenAwake") as? Bool ?? true
|
|
self.decimalNumberSeparator = UserDefaults.standard.object(forKey: "decimalNumberSeparator") as? String ?? "."
|
|
self.groceryListMode = UserDefaults.standard.object(forKey: "groceryListMode") as? String ?? GroceryListMode.inApp.rawValue
|
|
self.remindersListIdentifier = UserDefaults.standard.object(forKey: "remindersListIdentifier") as? String ?? ""
|
|
self.grocerySyncEnabled = UserDefaults.standard.object(forKey: "grocerySyncEnabled") as? Bool ?? true
|
|
|
|
if authString == "" {
|
|
if token != "" && username != "" {
|
|
let loginString = "\(self.username):\(self.token)"
|
|
let loginData = loginString.data(using: String.Encoding.utf8)!
|
|
authString = loginData.base64EncodedString()
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func setAuthString() {
|
|
if token != "" && username != "" {
|
|
let loginString = "\(self.username):\(self.token)"
|
|
let loginData = loginString.data(using: String.Encoding.utf8)!
|
|
self.authString = loginData.base64EncodedString()
|
|
}
|
|
}
|
|
}
|