Files
conjure/Sources/ConjureKit/CommandNumberShortcuts.swift
T

49 lines
1.5 KiB
Swift

import Foundation
/// Monotonic timestamps are supplied by the window; tests never wait on a real clock.
public struct CommandNumberShortcuts: Sendable {
private var heldSince: TimeInterval?
private var cancelledUntilRelease = false
public private(set) var isVisible = false
public var isHolding: Bool { heldSince != nil }
public init() {}
/// Samples an existing hold too, including when results first become eligible.
public mutating func update(commandOnly: Bool, eligible: Bool, at time: TimeInterval) -> Bool {
guard commandOnly else { reset(); return false }
guard eligible && !cancelledUntilRelease else {
heldSince = nil
isVisible = false
return false
}
guard heldSince == nil else { return false }
heldSince = time
return true
}
public mutating func reveal(at time: TimeInterval) -> Bool {
guard let heldSince, time - heldSince >= 1 else { return false }
isVisible = true
return true
}
public func index(for key: String) -> Int? {
guard isVisible, key.utf8.count == 1, let digit = key.utf8.first,
(49...57).contains(digit) else { return nil }
return Int(digit - 49)
}
/// An action cancels this hold; modifier sampling must not restart it.
public mutating func cancel() {
reset()
cancelledUntilRelease = true
}
public mutating func reset() {
heldSince = nil
isVisible = false
cancelledUntilRelease = false
}
}