Native macOS app for posting to Mastodon, WordPress (self-hosted), and Micro.blog. Features: global hotkey (Ctrl+Option+Cmd+T), multiple accounts with selection, image attachments (up to 4, drag-and-drop), floating panel UI, Keychain storage.
49 lines
1.3 KiB
Swift
49 lines
1.3 KiB
Swift
import Foundation
|
|
|
|
@Observable
|
|
@MainActor
|
|
final class AccountStore {
|
|
private(set) var accounts: [Account] = []
|
|
|
|
private static let storageKey = "qstatus.accounts"
|
|
|
|
init() {
|
|
loadAccounts()
|
|
}
|
|
|
|
func addAccount(_ account: Account, token: String) throws {
|
|
try KeychainManager.saveToken(token, forAccount: account.keychainKey)
|
|
accounts.append(account)
|
|
saveAccounts()
|
|
}
|
|
|
|
func removeAccount(_ account: Account) {
|
|
try? KeychainManager.delete(account: account.keychainKey)
|
|
accounts.removeAll { $0.id == account.id }
|
|
saveAccounts()
|
|
}
|
|
|
|
func token(for account: Account) -> String? {
|
|
try? KeychainManager.loadToken(forAccount: account.keychainKey)
|
|
}
|
|
|
|
func updateAccount(_ account: Account) {
|
|
if let index = accounts.firstIndex(where: { $0.id == account.id }) {
|
|
accounts[index] = account
|
|
saveAccounts()
|
|
}
|
|
}
|
|
|
|
private func saveAccounts() {
|
|
if let data = try? JSONEncoder().encode(accounts) {
|
|
UserDefaults.standard.set(data, forKey: Self.storageKey)
|
|
}
|
|
}
|
|
|
|
private func loadAccounts() {
|
|
guard let data = UserDefaults.standard.data(forKey: Self.storageKey),
|
|
let decoded = try? JSONDecoder().decode([Account].self, from: data)
|
|
else { return }
|
|
accounts = decoded
|
|
}
|
|
}
|