// // LocalData.swift // Reader // // Created by Shadowfacts on 11/25/21. // import Foundation import Fervor import CryptoKit struct LocalData { private init() {} private static let encoder = JSONEncoder() private static let decoder = JSONDecoder() private static var defaults = UserDefaults(suiteName: "group.net.shadowfacts.Reader")! static var accounts: [Account] { get { guard let data = defaults.data(forKey: "accounts"), let accounts = try? decoder.decode([Account].self, from: data) else { return [] } return accounts } set { let data = try! encoder.encode(newValue) defaults.set(data, forKey: "accounts") } } static var mostRecentAccountID: Data? { get { return defaults.data(forKey: "mostRecentAccountID") } set { defaults.set(newValue, forKey: "mostRecentAccountID") } } static func mostRecentAccount() -> Account? { guard let id = mostRecentAccountID else { return nil } return account(with: id) } static func account(with id: Data) -> Account? { return accounts.first(where: { $0.id == id }) } static func migrateIfNecessary() { if let accounts = UserDefaults.standard.object(forKey: "accounts") { UserDefaults.standard.removeObject(forKey: "accounts") defaults.set(accounts, forKey: "accounts") } if let mostRecentAccountID = UserDefaults.standard.object(forKey: "mostRecentAccountID") { UserDefaults.standard.removeObject(forKey: "mostRecentAccountID") defaults.set(mostRecentAccountID, forKey: "mostRecentAccountID") } } struct Account: Codable { let id: Data let instanceURL: URL let clientID: String let clientSecret: String let token: Token init(instanceURL: URL, clientID: String, clientSecret: String, token: Token) { // we use a hash of instance host and account id rather than random ids so that // user activites can uniquely identify accounts across devices var hasher = SHA256() hasher.update(data: instanceURL.host!.data(using: .utf8)!) hasher.update(data: token.owner!.data(using: .utf8)!) self.id = Data(hasher.finalize()) self.instanceURL = instanceURL self.clientID = clientID self.clientSecret = clientSecret self.token = token } } }