78 lines
2.4 KiB
Swift
78 lines
2.4 KiB
Swift
//
|
|
// AccountSwitchViewModel.swift
|
|
// suixinkan
|
|
//
|
|
|
|
import Foundation
|
|
|
|
/// 账号切换 ViewModel,管理可切换账号列表、选择状态和提交状态。
|
|
final class AccountSwitchViewModel {
|
|
private(set) var accounts: [AccountSwitchAccount] = []
|
|
private(set) var selectedAccountId: String?
|
|
private(set) var loading = false
|
|
private(set) var switching = false
|
|
private var didLoad = false
|
|
|
|
var onStateChange: (() -> Void)?
|
|
|
|
var selectedAccount: AccountSwitchAccount? {
|
|
accounts.first { $0.id == selectedAccountId }
|
|
}
|
|
|
|
func load(api: ProfileAPI, force: Bool = false, currentAccountId: String? = nil) async throws {
|
|
guard force || !didLoad else { return }
|
|
didLoad = true
|
|
loading = true
|
|
notifyStateChange()
|
|
defer {
|
|
loading = false
|
|
notifyStateChange()
|
|
}
|
|
|
|
let response = try await api.switchableAccounts()
|
|
accounts = response.accounts.filter { $0.businessUserId > 0 }
|
|
selectedAccountId = accounts.first(where: { $0.isCurrent || isCurrent($0, currentAccountId: currentAccountId) })?.id
|
|
?? accounts.first?.id
|
|
notifyStateChange()
|
|
}
|
|
|
|
func select(_ account: AccountSwitchAccount) {
|
|
selectedAccountId = account.id
|
|
notifyStateChange()
|
|
}
|
|
|
|
func switchAccount(_ account: AccountSwitchAccount, api: AuthAPI) async throws -> V9AuthResponse {
|
|
guard !switching else { throw AccountSwitchError.submitting }
|
|
guard account.businessUserId > 0 else { throw AccountSwitchError.invalidAccount }
|
|
|
|
switching = true
|
|
notifyStateChange()
|
|
defer {
|
|
switching = false
|
|
notifyStateChange()
|
|
}
|
|
return try await api.setUser(account.toSetUserRequest())
|
|
}
|
|
|
|
func isCurrent(_ account: AccountSwitchAccount, currentAccountId: String?) -> Bool {
|
|
guard let currentAccountId else { return false }
|
|
return account.id == currentAccountId || String(account.businessUserId) == currentAccountId
|
|
}
|
|
|
|
private func notifyStateChange() {
|
|
onStateChange?()
|
|
}
|
|
}
|
|
|
|
enum AccountSwitchError: LocalizedError, Equatable {
|
|
case submitting
|
|
case invalidAccount
|
|
|
|
var errorDescription: String? {
|
|
switch self {
|
|
case .submitting: "账号正在切换,请稍候"
|
|
case .invalidAccount: "账号信息异常,请重新选择账号"
|
|
}
|
|
}
|
|
}
|