forked from shadowfacts/Tusker
172 lines
5.9 KiB
Swift
172 lines
5.9 KiB
Swift
//
|
|
// LocalData.swift
|
|
// Tusker
|
|
//
|
|
// Created by Shadowfacts on 8/18/18.
|
|
// Copyright © 2018 Shadowfacts. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import Combine
|
|
|
|
class LocalData: ObservableObject {
|
|
|
|
static let shared = LocalData()
|
|
|
|
let defaults: UserDefaults
|
|
|
|
private init() {
|
|
if ProcessInfo.processInfo.environment.keys.contains("UI_TESTING") {
|
|
defaults = UserDefaults(suiteName: "\(Bundle.main.bundleIdentifier!).uitesting")!
|
|
defaults.removePersistentDomain(forName: "\(Bundle.main.bundleIdentifier!).uitesting")
|
|
if ProcessInfo.processInfo.environment.keys.contains("UI_TESTING_LOGIN") {
|
|
accounts = [
|
|
UserAccountInfo(
|
|
id: UUID().uuidString,
|
|
instanceURL: URL(string: "http://localhost:8080")!,
|
|
clientID: "client_id",
|
|
clientSecret: "client_secret",
|
|
username: "admin",
|
|
accessToken: "access_token")
|
|
]
|
|
}
|
|
} else {
|
|
defaults = UserDefaults(suiteName: "group.space.vaccor.Tusker")!
|
|
tryMigrateOldDefaults()
|
|
}
|
|
}
|
|
|
|
// TODO: remove me before public beta
|
|
private func tryMigrateOldDefaults() {
|
|
let old = UserDefaults()
|
|
if let accounts = old.array(forKey: accountsKey) as? [[String: String]],
|
|
let mostRecentAccount = old.string(forKey: mostRecentAccountKey) {
|
|
defaults.setValue(accounts, forKey: accountsKey)
|
|
defaults.setValue(mostRecentAccount, forKey: mostRecentAccountKey)
|
|
old.removeObject(forKey: accountsKey)
|
|
old.removeObject(forKey: mostRecentAccountKey)
|
|
}
|
|
}
|
|
|
|
private let accountsKey = "accounts"
|
|
var accounts: [UserAccountInfo] {
|
|
get {
|
|
if let array = defaults.array(forKey: accountsKey) as? [[String: String]] {
|
|
return array.compactMap { (info) in
|
|
guard let id = info["id"],
|
|
let instanceURL = info["instanceURL"],
|
|
let url = URL(string: instanceURL),
|
|
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 []
|
|
}
|
|
}
|
|
set {
|
|
objectWillChange.send()
|
|
let array = newValue.map { (info) -> [String: String] in
|
|
var res = [
|
|
"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)
|
|
}
|
|
}
|
|
|
|
private let mostRecentAccountKey = "mostRecentAccount"
|
|
private(set) var mostRecentAccountID: String? {
|
|
get {
|
|
return defaults.string(forKey: mostRecentAccountKey)
|
|
}
|
|
set {
|
|
objectWillChange.send()
|
|
defaults.set(newValue, forKey: mostRecentAccountKey)
|
|
}
|
|
}
|
|
|
|
var onboardingComplete: Bool {
|
|
return !accounts.isEmpty
|
|
}
|
|
|
|
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)
|
|
}
|
|
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
|
|
}
|
|
|
|
func setUsername(for info: UserAccountInfo, username: String) {
|
|
var info = info
|
|
info.username = username
|
|
removeAccount(info)
|
|
accounts.append(info)
|
|
}
|
|
|
|
func removeAccount(_ info: UserAccountInfo) {
|
|
accounts.removeAll(where: { $0.id == info.id })
|
|
}
|
|
|
|
func getAccount(id: String) -> UserAccountInfo? {
|
|
return accounts.first(where: { $0.id == id })
|
|
}
|
|
|
|
func getMostRecentAccount() -> UserAccountInfo? {
|
|
guard onboardingComplete else { return nil }
|
|
let mostRecent: UserAccountInfo?
|
|
if let id = mostRecentAccountID {
|
|
mostRecent = accounts.first { $0.id == id }
|
|
} else {
|
|
mostRecent = nil
|
|
}
|
|
return mostRecent ?? accounts.first!
|
|
}
|
|
|
|
func setMostRecentAccount(_ account: UserAccountInfo?) {
|
|
mostRecentAccountID = account?.id
|
|
}
|
|
|
|
}
|
|
|
|
extension LocalData {
|
|
struct UserAccountInfo: Equatable, Hashable {
|
|
let id: String
|
|
let instanceURL: URL
|
|
let clientID: String
|
|
let clientSecret: String
|
|
fileprivate(set) var username: String!
|
|
let accessToken: String
|
|
|
|
func hash(into hasher: inout Hasher) {
|
|
hasher.combine(id)
|
|
}
|
|
|
|
static func ==(lhs: UserAccountInfo, rhs: UserAccountInfo) -> Bool {
|
|
return lhs.id == rhs.id
|
|
}
|
|
}
|
|
}
|
|
|
|
extension Notification.Name {
|
|
static let userLoggedOut = Notification.Name("Tusker.userLoggedOut")
|
|
static let addAccount = Notification.Name("Tusker.addAccount")
|
|
static let activateAccount = Notification.Name("Tusker.activateAccount")
|
|
}
|