OTP/OTP/KeyData.swift

122 lines
3.3 KiB
Swift

//
// KeyData.swift
// OTP
//
// Created by Shadowfacts on 8/23/21.
//
import Foundation
import OTPKit
struct KeyData: Codable {
private(set) var entries: [Entry] = []
private(set) var folders: [Folder] = []
init(entries: [Entry] = []) {
self.entries = entries
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.entries = try container.decode([Entry].self, forKey: .entries)
self.folders = try container.decode([Folder].self, forKey: .folders)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(entries, forKey: .entries)
try container.encode(folders, forKey: .folders)
}
mutating func addKey(_ key: TOTPKey) {
entries.append(Entry(key: key))
}
mutating func addOrUpdateEntries(_ entries: [Entry]) {
for e in entries {
if let index = self.entries.firstIndex(where: { $0.id == e.id }) {
self.entries[index] = e
} else {
self.entries.append(e)
}
}
}
mutating func updateKey(entryID id: UUID, newKey: TOTPKey) {
guard let index = entries.firstIndex(where: { $0.id == id }) else {
return
}
entries[index].key = newKey
}
mutating func removeKey(entryID id: UUID) {
entries.removeAll(where: { $0.id == id })
}
mutating func clearEntries() {
entries.removeAll()
}
mutating func addFolder() {
let count = folders.filter { $0.name.starts(with: "New Folder") }.count
if count > 0 {
folders.append(Folder(name: "New Folder \(count + 1)"))
} else {
folders.append(Folder(name: "New Folder"))
}
}
mutating func updateFolder(_ newFolder: KeyData.Folder) {
guard let index = folders.firstIndex(where: { $0.id == newFolder.id }) else {
return
}
folders[index] = newFolder
}
mutating func removeFolder(id: UUID) {
folders.removeAll(where: { $0.id == id })
for (index, e) in entries.enumerated() where e.folderID == id {
entries[index].folderID = nil
}
}
mutating func moveEntryToFolder(entryID: UUID, folderID: UUID?) {
guard let index = entries.firstIndex(where: { $0.id == entryID }),
folderID == nil || folders.contains(where: { $0.id == folderID }) else {
return
}
entries[index].folderID = folderID
}
struct Entry: Identifiable, Hashable, Codable {
let id: UUID
var key: TOTPKey
var folderID: UUID?
let image: Data?
init(id: UUID = UUID(), key: TOTPKey, folderID: UUID? = nil, image: Data? = nil) {
self.id = id
self.key = key
self.folderID = folderID
self.image = image
}
}
struct Folder: Identifiable, Codable {
let id: UUID
var name: String
init(id: UUID = UUID(), name: String) {
self.id = id
self.name = name
}
}
private enum CodingKeys: CodingKey {
case entries
case folders
}
}