Tusker/Tusker/LocalData.swift

158 lines
5.2 KiB
Swift
Raw Normal View History

2018-08-19 20:14:04 +00:00
//
// LocalData.swift
// Tusker
//
// Created by Shadowfacts on 8/18/18.
// Copyright © 2018 Shadowfacts. All rights reserved.
//
import Foundation
import Combine
2018-08-19 20:14:04 +00:00
class LocalData: ObservableObject {
2018-08-19 20:14:04 +00:00
static let shared = LocalData()
2019-12-30 20:59:49 +00:00
let defaults: UserDefaults
private init() {
if ProcessInfo.processInfo.environment.keys.contains("UI_TESTING") {
defaults = UserDefaults(suiteName: "\(Bundle.main.bundleIdentifier!).uitesting")!
2019-12-31 16:40:56 +00:00
if ProcessInfo.processInfo.environment.keys.contains("UI_TESTING_LOGIN") {
accounts = [
UserAccountInfo(
2020-01-19 16:52:06 +00:00
id: UUID().uuidString,
instanceURL: URL(string: "http://localhost:8080")!,
clientID: "client_id",
clientSecret: "client_secret",
username: "admin",
accessToken: "access_token")
]
2019-12-31 16:40:56 +00:00
}
2019-12-30 20:59:49 +00:00
} else {
defaults = UserDefaults()
}
}
2018-08-19 20:14:04 +00:00
private let accountsKey = "accounts"
var accounts: [UserAccountInfo] {
2018-08-19 20:14:04 +00:00
get {
if let array = defaults.array(forKey: accountsKey) as? [[String: String]] {
return array.compactMap { (info) in
2020-01-19 16:52:06 +00:00
guard let id = info["id"],
let instanceURL = info["instanceURL"],
let url = URL(string: instanceURL),
2020-01-19 16:52:06 +00:00
let clientId = info["clientID"],
let secret = info["clientSecret"],
let accessToken = info["accessToken"] else {
return nil
}
return UserAccountInfo(id: id, instanceURL: url, clientID: clientId, clientSecret: secret, username: info["username"], accessToken: accessToken)
}
} else {
return []
}
2018-08-19 20:14:04 +00:00
}
set {
objectWillChange.send()
let array = newValue.map { (info) -> [String: String] in
var res = [
2020-01-19 16:52:06 +00:00
"id": info.id,
"instanceURL": info.instanceURL.absoluteString,
"clientID": info.clientID,
"clientSecret": info.clientSecret,
"accessToken": info.accessToken
]
if let username = info.username {
res["username"] = username
}
return res
}
defaults.set(array, forKey: accountsKey)
2018-08-19 20:14:04 +00:00
}
}
private let mostRecentAccountKey = "mostRecentAccount"
2020-01-19 16:52:06 +00:00
private var mostRecentAccount: String? {
2018-08-19 20:14:04 +00:00
get {
return defaults.string(forKey: mostRecentAccountKey)
2018-08-19 20:14:04 +00:00
}
set {
objectWillChange.send()
defaults.set(newValue, forKey: mostRecentAccountKey)
2018-08-19 20:14:04 +00:00
}
}
var onboardingComplete: Bool {
return !accounts.isEmpty
2018-08-19 20:14:04 +00:00
}
func addAccount(instanceURL url: URL, clientID: String, clientSecret secret: String, username: String?, accessToken: String) -> UserAccountInfo {
var accounts = self.accounts
if let index = accounts.firstIndex(where: { $0.instanceURL == url && $0.username == username }) {
accounts.remove(at: index)
2018-08-19 20:14:04 +00:00
}
2020-01-19 16:52:06 +00:00
let id = UUID().uuidString
let info = UserAccountInfo(id: id, instanceURL: url, clientID: clientID, clientSecret: secret, username: username, accessToken: accessToken)
accounts.append(info)
self.accounts = accounts
return info
2018-08-19 20:14:04 +00:00
}
func setUsername(for info: UserAccountInfo, username: String) {
var info = info
info.username = username
removeAccount(info)
accounts.append(info)
}
func removeAccount(_ info: UserAccountInfo) {
2020-01-19 16:52:06 +00:00
accounts.removeAll(where: { $0.id == info.id })
}
func getAccount(id: String) -> UserAccountInfo? {
return accounts.first(where: { $0.id == id })
}
func getMostRecentAccount() -> UserAccountInfo? {
2020-01-19 16:52:06 +00:00
guard onboardingComplete else { return nil }
let mostRecent: UserAccountInfo?
if let id = mostRecentAccount {
mostRecent = accounts.first { $0.id == id }
} else {
2020-01-19 16:52:06 +00:00
mostRecent = nil
2018-08-19 20:14:04 +00:00
}
2020-01-19 16:52:06 +00:00
return mostRecent ?? accounts.first!
}
func setMostRecentAccount(_ account: UserAccountInfo?) {
mostRecentAccount = account?.id
2018-08-19 20:14:04 +00:00
}
}
extension LocalData {
struct UserAccountInfo: Equatable, Hashable {
2020-01-19 16:52:06 +00:00
let id: String
let instanceURL: URL
let clientID: String
let clientSecret: String
fileprivate(set) var username: String!
let accessToken: String
2020-01-19 16:52:06 +00:00
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
static func ==(lhs: UserAccountInfo, rhs: UserAccountInfo) -> Bool {
return lhs.id == rhs.id
}
}
2018-08-19 20:14:04 +00:00
}
2019-09-16 17:12:23 +00:00
extension Notification.Name {
2020-01-19 16:52:06 +00:00
static let userLoggedOut = Notification.Name("Tusker.userLoggedOut")
static let addAccount = Notification.Name("Tusker.addAccount")
static let activateAccount = Notification.Name("Tusker.activateAccount")
2019-09-16 17:12:23 +00:00
}