// ModifierState.swift // Observable sticky-modifier state for the ModifierBar. // // Design: Ctrl is "sticky" — tap once to arm, the next key sent // includes the Ctrl modifier, then the state automatically disarms // via `reset()`. `isRepeating` reflects whether an arrow key is // currently being held down in repeat mode. import Foundation // MARK: - ModifierState /// Observable state for sticky keyboard modifiers used by `ModifierBar`. /// /// All mutations must happen on the main actor; consumers should observe /// via `@ObservedObject` or `@StateObject`. @MainActor final class ModifierState: ObservableObject { // MARK: Published /// Whether the Ctrl modifier is armed. /// /// When `true`, the next key dispatched by `ModifierBar` is sent as a /// Ctrl combo (e.g. `ctrl-c`). The modifier disarms automatically after /// the key is sent. @Published var ctrlActive: Bool = false /// Whether an arrow key is currently being held down in repeat mode. /// /// Set to `true` by `ModifierBar` when a long-press repeat cycle begins, /// and back to `false` when the touch is released. Consumers may observe /// this to suppress other UI interactions while repeating. @Published var isRepeating: Bool = false // MARK: Mutations /// Toggles the Ctrl sticky modifier on / off. func toggleCtrl() { ctrlActive.toggle() } /// Disarms all modifiers (Ctrl and repeat state). /// /// Call this after any key has been dispatched to return to a neutral /// modifier state. func reset() { ctrlActive = false isRepeating = false } }