Transform to multi-account support

This commit is contained in:
2025-08-01 19:31:53 +02:00
parent 351f08e43e
commit 68239727fa
24 changed files with 635 additions and 503 deletions
+53 -25
View File
@@ -7,29 +7,34 @@
import Foundation
import SwiftUI
import OSLog
/// **AccountManager** stores connection details and the corresponding client
class AccountManager: ObservableObject {
/// **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
@Published private(set) var Accounts: Array<AccountManagerEntry> = []
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<AccountManagerEntry> {
static private func readFromRaw() -> Array<Account> {
@AppStorage("accounts") var rawAccs = Data()
do {
let simpleAccs = try JSONDecoder().decode([Account].self, from: rawAccs)
let richAccs = simpleAccs.map({ AccountManagerEntry($0) })
return richAccs
return try JSONDecoder().decode([Account].self, from: rawAccs)
} catch {
print("Error parsing stored accounts from JSON: \(error)")
let _ = Logger().error("Error parsing stored accounts from JSON: \(error)")
rawAccs = Data()
return []
}
}
@@ -38,47 +43,70 @@ class AccountManager: ObservableObject {
private func writeToRaw() {
@AppStorage("accounts") var rawAccs = Data()
do {
let simpleAccs = Accounts.map({ $0.GetAccount() })
rawAccs = try JSONEncoder().encode(simpleAccs)
rawAccs = try JSONEncoder().encode(Accounts)
} catch {
print("Error writing current accounts to JSON: \(error)")
let _ = Logger().error("Error writing current accounts to JSON: \(error)")
}
}
// CurrentAccount returns the currently selected account if there is one
func CurrentAccount() -> AccountManagerEntry? {
if self.Accounts.count > 0 {
return self.Accounts.first
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(AccountManagerEntry(account))
writeToRaw()
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.GetAccount().GetAddress() == account.GetAddress() &&
$0.GetAccount().GetUserID() == account.GetUserID()
$0.address == account.address &&
$0.userID == account.userID
})
}
// RemoveAccount removes the account specified by address and user ID of the given Account, if present
// RemoveAccount removes the specified account
func RemoveAccount(_ account: Account) {
if IndexOfAccount(account) != nil {
Accounts.remove(at: IndexOfAccount(account)!)
writeToRaw()
RemoveAccount(IndexOfAccount(account)!)
}
}
// RemoveAccount removes the account specified by address and user ID of the given AccountManagerEntry, if present
func RemoveAccount(_ account: AccountManagerEntry) {
RemoveAccount(account.GetAccount())
// 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()
}
}
}