banyaro-ios/BanYaroGo/Support/ActiveDogStore.swift
rene 546386dcbd Hunde-Cache leeren bei Logout/401 — kein Durchschimmern auf neuen User
Bug: ActiveDogStore cached dogs + activeDogId (UserDefaults). Beim
Login mit einem neuen Account waren die Hunde des vorigen Users
weiter zu sehen, weil HeimView nur loadDogs() ruft wenn dogs.isEmpty.

Fix:
- ActiveDogStore hat jetzt reset() (dogs=[], activeDogId=0,
  UserDefaults gelöscht).
- ActiveDogStore hört auf .userDidLogout und auf .apiUnauthorized,
  beides löst reset() aus.
- AuthSession.logout() postet jetzt .userDidLogout.
- Nach Login holt HeimView's .task automatisch die neuen Hunde
  (dogs.isEmpty → loadDogs).
2026-05-30 18:25:23 +02:00

68 lines
2.2 KiB
Swift

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")
}