64 lines
2.3 KiB
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
|
|
}
|
|
}
|