import Foundation @MainActor final class SessionStore: ObservableObject { static let defaultApiBase = "https://master.vonas.nl" @Published var refreshToken: String? @Published var apiBase: String @Published var profileId: String? @Published var profileName: String? @Published var profileAvatarId: String? @Published var profileShowAvatar: Bool = true @Published var profileAvatarUrl: String? private let defaults = UserDefaults.standard private enum Key { static let token = "vmc.refresh_token" static let api = "vmc.api_base" static let profileId = "vmc.profile_id" static let profileName = "vmc.profile_name" static let profileAvatar = "vmc.profile_avatar" static let profileShowAvatar = "vmc.profile_show_avatar" static let profileAvatarUrl = "vmc.profile_avatar_url" } init() { refreshToken = defaults.string(forKey: Key.token) apiBase = defaults.string(forKey: Key.api) ?? Self.defaultApiBase profileId = defaults.string(forKey: Key.profileId) profileName = defaults.string(forKey: Key.profileName) profileAvatarId = defaults.string(forKey: Key.profileAvatar) let showRaw = defaults.string(forKey: Key.profileShowAvatar) profileShowAvatar = showRaw != "0" profileAvatarUrl = defaults.string(forKey: Key.profileAvatarUrl) } var isAuthed: Bool { !(refreshToken ?? "").isEmpty } var hasProfile: Bool { !(profileId ?? "").isEmpty } func setToken(_ token: String?) { refreshToken = token if let token, !token.isEmpty { defaults.set(token, forKey: Key.token) } else { defaults.removeObject(forKey: Key.token) setProfile(id: nil, name: nil, avatarId: nil) } } func setApiBase(_ url: String) { let clean = url.trimmingCharacters(in: .whitespacesAndNewlines) .trimmingCharacters(in: CharacterSet(charactersIn: "/")) apiBase = clean.isEmpty ? Self.defaultApiBase : clean defaults.set(apiBase, forKey: Key.api) } func setProfile( id: String?, name: String?, avatarId: String?, showAvatar: Bool? = nil, avatarUrl: String? = nil ) { profileId = id profileName = name profileAvatarId = avatarId if let id, !id.isEmpty { defaults.set(id, forKey: Key.profileId) if let name, !name.isEmpty { defaults.set(name, forKey: Key.profileName) } else { defaults.removeObject(forKey: Key.profileName) } if let avatarId, !avatarId.isEmpty { defaults.set(avatarId, forKey: Key.profileAvatar) } else { defaults.removeObject(forKey: Key.profileAvatar) } if let showAvatar { profileShowAvatar = showAvatar defaults.set(showAvatar ? "1" : "0", forKey: Key.profileShowAvatar) } if let avatarUrl { if avatarUrl.isEmpty { profileAvatarUrl = nil defaults.removeObject(forKey: Key.profileAvatarUrl) } else { profileAvatarUrl = avatarUrl defaults.set(avatarUrl, forKey: Key.profileAvatarUrl) } } } else { defaults.removeObject(forKey: Key.profileId) defaults.removeObject(forKey: Key.profileName) defaults.removeObject(forKey: Key.profileAvatar) defaults.removeObject(forKey: Key.profileShowAvatar) defaults.removeObject(forKey: Key.profileAvatarUrl) profileName = nil profileAvatarId = nil profileShowAvatar = true profileAvatarUrl = nil } } }