Files
mobile-ios/Rosetta/Features/Settings/SettingsViewModel.swift

64 lines
2.3 KiB
Swift

import Combine
import Foundation
import UIKit
/// Settings view model with **cached** state.
///
/// Previously this was `@Observable` with computed properties that read
/// `ProtocolManager`, `SessionManager`, and `AccountManager` directly.
/// Because all tabs are pre-activated, those reads caused SettingsView
/// (inside a NavigationStack) to re-render 6+ times during handshake,
/// producing "Update NavigationRequestObserver tried to update multiple
/// times per frame" app freeze.
///
/// Now uses `ObservableObject` + `@Published` stored properties.
/// State is refreshed explicitly via `refresh()`.
@MainActor
final class SettingsViewModel: ObservableObject {
@Published private(set) var displayName: String = ""
@Published private(set) var username: String = ""
@Published private(set) var publicKey: String = ""
@Published private(set) var connectionStatus: String = "Disconnected"
@Published private(set) var isConnected: Bool = false
var initials: String {
RosettaColors.initials(name: displayName, publicKey: publicKey)
}
var avatarColorIndex: Int {
RosettaColors.avatarColorIndex(for: displayName, publicKey: publicKey)
}
/// Snapshot current state from singletons. Call from `.task {}` or `.onAppear`.
func refresh() {
let session = SessionManager.shared
let account = AccountManager.shared.currentAccount
displayName = session.displayName.isEmpty
? (account?.displayName ?? "")
: session.displayName
username = session.username.isEmpty
? (account?.username ?? "")
: session.username
publicKey = account?.publicKey ?? ""
let state = ProtocolManager.shared.connectionState
isConnected = state == .authenticated
switch state {
case .disconnected: connectionStatus = "Disconnected"
case .connecting: connectionStatus = "Connecting..."
case .connected: connectionStatus = "Connected"
case .handshaking: connectionStatus = "Authenticating..."
case .deviceVerificationRequired: connectionStatus = "Device Verification Required"
case .authenticated: connectionStatus = "Online"
}
}
func copyPublicKey() {
UIPasteboard.general.string = publicKey
}
}