import Foundation import Observation /// Tracks the user's currently selected dog across the app. Picked once, /// reused everywhere (Heim, Tagebuch, Statistik, …). Persisted in UserDefaults. @Observable @MainActor final class ActiveDogStore { var activeDogId: Int var dogs: [Dog] = [] var activeDog: Dog? { dogs.first(where: { $0.id == activeDogId }) ?? dogs.first } init() { self.activeDogId = UserDefaults.standard.integer(forKey: "activeDogId") // Auf User-Wechsel hören (Logout oder 401 = Token abgelaufen), // damit nie die Hunde des vorigen Users durchschimmern. NotificationCenter.default.addObserver( forName: .userDidLogout, object: nil, queue: .main ) { [weak self] _ in Task { @MainActor in self?.reset() } } NotificationCenter.default.addObserver( forName: .apiUnauthorized, object: nil, queue: .main ) { [weak self] _ in Task { @MainActor in self?.reset() } } } func loadDogs() async { do { let fetched: [Dog] = try await APIClient.shared.get("/api/dogs") self.dogs = fetched if !fetched.contains(where: { $0.id == activeDogId }), let first = fetched.first { setActive(first.id) } } catch { print("ActiveDogStore loadDogs failed: \(error)") } } func setActive(_ dogId: Int) { activeDogId = dogId UserDefaults.standard.set(dogId, forKey: "activeDogId") } /// Komplett zurücksetzen — wird bei Logout / 401 aufgerufen, damit kein /// Cache vom vorigen User durchschlägt. `loadDogs()` wird beim nächsten /// Erscheinen einer Seite (`dogs.isEmpty`) automatisch wieder gefeuert. func reset() { dogs = [] activeDogId = 0 UserDefaults.standard.removeObject(forKey: "activeDogId") } } extension Notification.Name { /// Wird von `AuthSession.logout()` gepostet, damit abhängige Stores /// (z.B. ActiveDogStore) ihren User-bezogenen Cache leeren. static let userDidLogout = Notification.Name("BanYaroGo.userDidLogout") }