113 lines
3.5 KiB
Swift
113 lines
3.5 KiB
Swift
//
|
|
// AccountManager.swift
|
|
// meterios
|
|
//
|
|
// (c) 2025 Martin "maride" Dessauer
|
|
//
|
|
|
|
import Foundation
|
|
import SwiftUI
|
|
import OSLog
|
|
|
|
/// **AccountManager** holds multiple accounts and takes care of storing them on the device.
|
|
@Observable class AccountManager {
|
|
// default contains a ready-to-use instance of AccountManager, read from AppStorage
|
|
static public var `default` = AccountManager()
|
|
|
|
// accounts holds all saved accounts
|
|
private(set) var Accounts: Array<Account> = [] { didSet { writeToRaw() } }
|
|
private var selectedAccount: Int? { didSet { writeToRaw() } }
|
|
|
|
// init creates a new AccountManager, reading saved account data from AppStorage
|
|
init() {
|
|
self.Accounts = AccountManager.readFromRaw()
|
|
|
|
// Read account selection
|
|
@AppStorage("selectedAccount") var selectedAccount: Int?
|
|
self.selectedAccount = selectedAccount
|
|
}
|
|
|
|
// readFromRaw reads the current accounts from the stored data and transforms it to a handy Account Array
|
|
static private func readFromRaw() -> Array<Account> {
|
|
@AppStorage("accounts") var rawAccs = Data()
|
|
do {
|
|
return try JSONDecoder().decode([Account].self, from: rawAccs)
|
|
} catch {
|
|
let _ = Logger().error("Error parsing stored accounts from JSON: \(error)")
|
|
rawAccs = Data()
|
|
return []
|
|
}
|
|
}
|
|
|
|
// writeToRaw writes the current account data to the AppStorage
|
|
private func writeToRaw() {
|
|
@AppStorage("accounts") var rawAccs = Data()
|
|
do {
|
|
rawAccs = try JSONEncoder().encode(Accounts)
|
|
} catch {
|
|
let _ = Logger().error("Error writing current accounts to JSON: \(error)")
|
|
}
|
|
}
|
|
|
|
// CurrentAccount returns the currently selected account if there is one
|
|
func CurrentAccount() -> Account? {
|
|
if selectedAccount == nil {
|
|
return nil
|
|
}
|
|
|
|
if Accounts.count > selectedAccount! {
|
|
return Accounts[selectedAccount!]
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// SelectAccount sets the current main account as returned by CurrentAccount
|
|
func SelectAccount(_ account: Account) {
|
|
SelectAccount(IndexOfAccount(account))
|
|
}
|
|
|
|
// SelectAccount sets the current main account as returned by CurrentAccount
|
|
func SelectAccount(_ accountID: Int?) {
|
|
self.selectedAccount = accountID
|
|
|
|
// Store account selection
|
|
@AppStorage("selectedAccount") var selectedAccount: Int?
|
|
selectedAccount = self.selectedAccount
|
|
}
|
|
|
|
// AddAccount adds the given account if it doesn't exist yet
|
|
func AddAccount(_ account: Account) {
|
|
if IndexOfAccount(account) == nil {
|
|
Accounts.append(account)
|
|
}
|
|
}
|
|
|
|
// IndexOfAccount returns the index of the specified account identified by address and user ID
|
|
func IndexOfAccount(_ account: Account) -> Int? {
|
|
return Accounts.firstIndex(where: {
|
|
$0.address == account.address &&
|
|
$0.userID == account.userID
|
|
})
|
|
}
|
|
|
|
// RemoveAccount removes the specified account
|
|
func RemoveAccount(_ account: Account) {
|
|
if IndexOfAccount(account) != nil {
|
|
RemoveAccount(IndexOfAccount(account)!)
|
|
}
|
|
}
|
|
|
|
// RemoveAccount removes the account at the specified index
|
|
func RemoveAccount(_ index: Int) {
|
|
Accounts.remove(at: index)
|
|
}
|
|
|
|
// RefreshAll refreshes all accounts held by this manager instance
|
|
func RefreshAll() async {
|
|
for acc in Accounts {
|
|
await acc.Refresh()
|
|
}
|
|
}
|
|
}
|