114 lines
3.5 KiB
Swift
114 lines
3.5 KiB
Swift
import Foundation
|
|
import Combine
|
|
import CoreData
|
|
|
|
@MainActor
|
|
class AccountStore: ObservableObject {
|
|
@Published private(set) var accounts: [Account] = []
|
|
@Published var selectedAccount: Account?
|
|
@Published var showAllAccounts = true
|
|
|
|
private let accountRepository: AccountRepository
|
|
private let iapService: IAPService
|
|
private var cancellables = Set<AnyCancellable>()
|
|
|
|
init(
|
|
accountRepository: AccountRepository? = nil,
|
|
iapService: IAPService
|
|
) {
|
|
self.accountRepository = accountRepository ?? AccountRepository()
|
|
self.iapService = iapService
|
|
|
|
// Clean up any duplicate Default accounts from previous bug
|
|
self.accountRepository.cleanupDuplicateDefaultAccounts()
|
|
|
|
// Create default account if needed (now fetches directly from DB)
|
|
let defaultAccount = self.accountRepository.createDefaultAccountIfNeeded()
|
|
|
|
// Trigger async fetch to populate the published accounts array
|
|
self.accountRepository.fetchAccounts()
|
|
accounts = self.accountRepository.accounts
|
|
selectedAccount = defaultAccount
|
|
|
|
loadSelection()
|
|
setupObservers()
|
|
}
|
|
|
|
private func setupObservers() {
|
|
accountRepository.$accounts
|
|
.receive(on: DispatchQueue.main)
|
|
.sink { [weak self] accounts in
|
|
self?.accounts = accounts
|
|
if let selected = self?.selectedAccount, selected.isDeleted {
|
|
self?.selectedAccount = nil
|
|
}
|
|
self?.syncSelectedAccount()
|
|
}
|
|
.store(in: &cancellables)
|
|
|
|
NotificationCenter.default.publisher(for: .didResetData)
|
|
.receive(on: DispatchQueue.main)
|
|
.sink { [weak self] _ in
|
|
guard let self else { return }
|
|
self.accountRepository.fetchAccounts()
|
|
self.selectedAccount = nil
|
|
self.showAllAccounts = true
|
|
self.persistSelection()
|
|
}
|
|
.store(in: &cancellables)
|
|
}
|
|
|
|
private func loadSelection() {
|
|
let context = CoreDataStack.shared.viewContext
|
|
let settings = AppSettings.getOrCreate(in: context)
|
|
showAllAccounts = settings.showAllAccounts
|
|
|
|
if let selectedId = settings.selectedAccountId,
|
|
let account = accountRepository.fetchAccount(by: selectedId) {
|
|
selectedAccount = account
|
|
} else {
|
|
selectedAccount = accounts.first
|
|
}
|
|
}
|
|
|
|
private func syncSelectedAccount() {
|
|
if showAllAccounts { return }
|
|
if let selectedId = selectedAccount?.safeId,
|
|
accounts.contains(where: { $0.safeId == selectedId }) {
|
|
return
|
|
}
|
|
selectedAccount = accounts.first
|
|
}
|
|
|
|
func selectAllAccounts() {
|
|
showAllAccounts = true
|
|
selectedAccount = nil
|
|
persistSelection()
|
|
}
|
|
|
|
func selectAccount(_ account: Account) {
|
|
showAllAccounts = false
|
|
selectedAccount = account
|
|
persistSelection()
|
|
}
|
|
|
|
func persistSelection() {
|
|
let context = CoreDataStack.shared.viewContext
|
|
let settings = AppSettings.getOrCreate(in: context)
|
|
settings.showAllAccounts = showAllAccounts
|
|
settings.selectedAccountId = showAllAccounts ? nil : selectedAccount?.safeId
|
|
CoreDataStack.shared.save()
|
|
}
|
|
|
|
func canAddAccount() -> Bool {
|
|
iapService.isPremium || accounts.count < 1
|
|
}
|
|
}
|
|
|
|
extension Account {
|
|
var safeId: UUID? {
|
|
guard !isDeleted else { return nil }
|
|
return value(forKey: "id") as? UUID
|
|
}
|
|
}
|