Sesame-iOS/Sesame/ClientState.swift

176 lines
4.5 KiB
Swift
Raw Normal View History

2022-01-29 18:59:42 +01:00
import Foundation
import SwiftUI
2022-04-09 17:43:33 +02:00
enum ConnectionError {
case serverNotReached
case deviceDisconnected
}
extension ConnectionError: CustomStringConvertible {
var description: String {
switch self {
case .serverNotReached:
return "Server unavailable"
case .deviceDisconnected:
return "Device disconnected"
}
}
}
enum RejectionCause {
case invalidCounter
case invalidTime
case invalidAuthentication
case timeout
}
extension RejectionCause: CustomStringConvertible {
var description: String {
switch self {
case .invalidCounter:
return "Invalid counter"
case .invalidTime:
return "Invalid time"
case .invalidAuthentication:
return "Invalid authentication"
case .timeout:
return "Device not responding"
}
}
}
2022-01-29 18:59:42 +01:00
enum ClientState {
2022-04-09 17:43:33 +02:00
/// There is no key stored locally on the client. A new key must be generated before use.
case noKeyAvailable
/// The device status is being requested
case requestingStatus
2022-01-29 18:59:42 +01:00
/// The remote device is not connected (no socket opened)
2022-04-09 17:43:33 +02:00
case deviceNotAvailable(ConnectionError)
/// The device is connected and ready to receive a message
case ready
2022-01-29 18:59:42 +01:00
2022-04-09 17:43:33 +02:00
/// The message is being transmitted and a response is awaited
2022-01-29 18:59:42 +01:00
case waitingForResponse
2022-04-09 17:43:33 +02:00
/// The transmitted message was rejected (multiple possible reasons)
case messageRejected(RejectionCause)
2022-01-29 18:59:42 +01:00
/// The device responded that the opening action was started
case openSesame
2022-04-09 17:43:33 +02:00
case internalError(String)
2022-01-29 18:59:42 +01:00
var canSendKey: Bool {
switch self {
2022-04-09 17:43:33 +02:00
case .ready, .openSesame, .messageRejected:
2022-01-29 18:59:42 +01:00
return true
default:
return false
}
}
2022-04-09 17:43:33 +02:00
init(keyResult: MessageResult) {
2022-01-29 18:59:42 +01:00
switch keyResult {
2022-04-09 17:43:33 +02:00
case .messageAuthenticationFailed:
self = .messageRejected(.invalidAuthentication)
case .messageTimeMismatch:
self = .messageRejected(.invalidTime)
case .messageCounterInvalid:
self = .messageRejected(.invalidCounter)
case .deviceTimedOut:
self = .messageRejected(.timeout)
case .messageAccepted:
2022-01-29 18:59:42 +01:00
self = .openSesame
2022-04-09 17:43:33 +02:00
case .noBodyData, .invalidMessageData, .textReceived, .unexpectedSocketEvent:
self = .internalError(keyResult.description)
case .deviceNotConnected:
self = .deviceNotAvailable(.deviceDisconnected)
case .operationInProgress:
self = .waitingForResponse
2022-01-29 18:59:42 +01:00
}
}
2022-04-09 17:43:33 +02:00
2022-04-13 14:55:47 +02:00
var actionText: String {
2022-01-29 18:59:42 +01:00
switch self {
2022-04-09 17:43:33 +02:00
case .noKeyAvailable:
return "Create key"
default:
2022-01-29 18:59:42 +01:00
return "Unlock"
}
}
2022-04-13 14:55:47 +02:00
var requiresDescription: Bool {
switch self {
case .deviceNotAvailable, .messageRejected, .internalError:
return true
default:
return false
}
}
2022-01-29 18:59:42 +01:00
2022-04-13 14:55:47 +02:00
var color: Color {
2022-01-29 18:59:42 +01:00
switch self {
2022-04-13 14:55:47 +02:00
case .noKeyAvailable:
return .gray
case .requestingStatus:
2022-01-29 18:59:42 +01:00
return .yellow
2022-04-13 14:55:47 +02:00
case .deviceNotAvailable:
return Color(red: 1.0, green: 0.6, blue: 0.6)
case .messageRejected:
2022-01-29 18:59:42 +01:00
return .red
2022-04-13 14:55:47 +02:00
case .internalError:
return Color(red: 0.7, green: 0, blue: 0)
case .ready:
return Color(red: 0.7, green: 1.0, blue: 0.5)
case .waitingForResponse:
return Color(red: 0.9, green: 1.0, blue: 0.5)
case .openSesame:
2022-01-29 18:59:42 +01:00
return .green
}
}
2022-04-13 14:55:47 +02:00
var allowsAction: Bool {
2022-01-29 18:59:42 +01:00
switch self {
2022-04-09 17:43:33 +02:00
case .requestingStatus, .deviceNotAvailable, .waitingForResponse:
2022-01-29 18:59:42 +01:00
return false
default:
return true
}
}
2022-04-09 17:43:33 +02:00
}
extension ClientState: Equatable {
2022-01-29 18:59:42 +01:00
2022-04-09 17:43:33 +02:00
}
extension ClientState: CustomStringConvertible {
var description: String {
switch self {
case .noKeyAvailable:
return "No key set."
case .requestingStatus:
return "Checking device status"
case .deviceNotAvailable(let status):
return status.description
case .ready:
return "Ready"
case .waitingForResponse:
return "Unlocking..."
case .messageRejected(let cause):
return cause.description
case .openSesame:
return "Unlocked"
case .internalError(let e):
return "Error: \(e)"
}
}
2022-01-29 18:59:42 +01:00
}