You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
Music/Music/Remote/ConnectionState.swift

69 lines
2.3 KiB

import Foundation
/// Represents the connection lifecycle of the remote client.
/// Transitions are validated by `canTransition(to:)` to enforce a strict state machine.
nonisolated enum ConnectionState: Equatable, Sendable {
case disconnected
case discovering
case foundHost(String)
case downloadingDB
case connectingCommandChannel
case connected(String)
case connectionLost(String)
/// Human-readable status message for display in the UI.
var userMessage: String? {
switch self {
case .disconnected:
nil
case .discovering:
"Searching for hosts..."
case .foundHost(let host):
"Found \(host)"
case .downloadingDB:
"Downloading library..."
case .connectingCommandChannel:
"Connecting..."
case .connected(let host):
"Connected to \(host)"
case .connectionLost(let reason):
"Connection lost — \(reason)"
}
}
/// Whether the client is fully connected.
var isConnected: Bool {
if case .connected = self { return true }
return false
}
/// Validates whether transitioning from the current state to `next` is allowed.
///
/// Valid forward transitions follow the connection lifecycle:
/// disconnected discovering foundHost downloadingDB connectingCommandChannel connected connectionLost discovering
///
/// Any state may transition to `.disconnected` (the user can always disconnect).
func canTransition(to next: ConnectionState) -> Bool {
// Any state can go to disconnected
if case .disconnected = next { return true }
switch self {
case .disconnected:
if case .discovering = next { return true }
case .discovering:
if case .foundHost = next { return true }
case .foundHost:
if case .downloadingDB = next { return true }
case .downloadingDB:
if case .connectingCommandChannel = next { return true }
case .connectingCommandChannel:
if case .connected = next { return true }
case .connected:
if case .connectionLost = next { return true }
case .connectionLost:
if case .discovering = next { return true }
}
return false
}
}