Show end times on detail/player, tighten TV chrome, and let profiles toggle or upload a cropped photo via API and mobile/iOS.
98 lines
3.7 KiB
Swift
98 lines
3.7 KiB
Swift
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
|
|
}
|
|
}
|
|
}
|