Skip to main content

smix_input/
lib.rs

1#![doc = include_str!("../README.md")]
2#![deny(missing_docs)]
3#![deny(rustdoc::broken_intra_doc_links)]
4#![doc(html_root_url = "https://docs.smix.dev/smix-input")]
5
6//! Small wire-only types shared by smix-driver / smix-authoring-ir /
7//! smix-runner-client. Kept as a separate crate so cement (CLI / MCP /
8//! SDK / recorder) can depend on them without dragging in heavier
9//! driver / runner deps.
10
11use serde::{Deserialize, Serialize};
12
13/// Maestro yaml `direction:` semantic: the direction names what
14/// content the caller wants to **see** (navigation through content),
15/// NOT the finger gesture direction. `Down` = "navigate down through
16/// content" = reveal what's BELOW the current viewport (visually content
17/// moves up, finger gestures up). Mirrors maestro CLI `direction: DOWN`
18/// semantics.
19///
20/// The name "SwipeDirection" predates this convention and now
21/// reads as a slight misnomer (the value is the *navigation* direction,
22/// not the *swipe gesture* direction). Renaming the enum would ripple
23/// across every adapter/driver/runner crate without semantic gain;
24/// instead the docstring carries the contract. Both runners (swift
25/// XCUITest + Kotlin UiAutomator) map this enum's wire string to the
26/// inverse finger gesture (e.g. `Down` → finger up via swipeUp / coord
27/// y 70→30) so the same yaml flow yields the same visual behavior on
28/// both platforms.
29#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
30#[serde(rename_all = "camelCase")]
31pub enum SwipeDirection {
32    /// Navigate up = see what's above (content moves down; finger gestures down).
33    Up,
34    /// Navigate down = see what's below (content moves up; finger gestures up).
35    Down,
36    /// Navigate left = see what's to the left (content moves right; finger gestures right).
37    Left,
38    /// Navigate right = see what's to the right (content moves left; finger gestures left).
39    Right,
40}
41
42impl SwipeDirection {
43    /// camelCase wire string (mirrors `roleSchema` style).
44    #[must_use]
45    pub fn as_str(self) -> &'static str {
46        match self {
47            SwipeDirection::Up => "up",
48            SwipeDirection::Down => "down",
49            SwipeDirection::Left => "left",
50            SwipeDirection::Right => "right",
51        }
52    }
53}
54
55impl std::fmt::Display for SwipeDirection {
56    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57        f.write_str(self.as_str())
58    }
59}
60
61/// Keyboard key name for `press_key` / `record` (camelCase on the wire).
62///
63/// The subset is intentional — these are the keys SDK users reliably
64/// exercise in iOS-sim contexts. Arrow keys are included because
65/// focus-traversal flows need them.
66#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
67#[serde(rename_all = "camelCase")]
68pub enum KeyName {
69    /// Return / Enter key — submits a form or confirms an action.
70    Return,
71    /// Delete / Backspace key — deletes the character before the cursor.
72    Delete,
73    /// Tab key — moves focus to the next focusable element.
74    Tab,
75    /// Space key — inserts a space character.
76    Space,
77    /// Escape key — dismisses a modal or cancels an action.
78    Escape,
79    /// Up-arrow key — moves selection / focus / caret upward.
80    ArrowUp,
81    /// Down-arrow key — moves selection / focus / caret downward.
82    ArrowDown,
83    /// Left-arrow key — moves selection / focus / caret leftward.
84    ArrowLeft,
85    /// Right-arrow key — moves selection / focus / caret rightward.
86    ArrowRight,
87    /// iOS hardware Home button — XCUIDevice.shared.perform(.homeButton).
88    /// Maps 1:1 to maestro `pressKey: home`.
89    Home,
90    /// iOS hardware Lock button — XCUIDevice.shared.perform(.lockButton).
91    /// Maps 1:1 to maestro `pressKey: lock`.
92    Lock,
93    /// iOS hardware Volume Up button — XCUIDevice.Button.volumeUp.
94    /// Maps 1:1 to maestro `pressKey: volume up`.
95    VolumeUp,
96    /// iOS hardware Volume Down button — XCUIDevice.Button.volumeDown.
97    /// Maps 1:1 to maestro `pressKey: volume down`.
98    VolumeDown,
99}
100
101impl KeyName {
102    /// camelCase wire string.
103    #[must_use]
104    pub fn as_str(self) -> &'static str {
105        match self {
106            KeyName::Return => "return",
107            KeyName::Delete => "delete",
108            KeyName::Tab => "tab",
109            KeyName::Space => "space",
110            KeyName::Escape => "escape",
111            KeyName::ArrowUp => "arrowUp",
112            KeyName::ArrowDown => "arrowDown",
113            KeyName::ArrowLeft => "arrowLeft",
114            KeyName::ArrowRight => "arrowRight",
115            KeyName::Home => "home",
116            KeyName::Lock => "lock",
117            KeyName::VolumeUp => "volumeUp",
118            KeyName::VolumeDown => "volumeDown",
119        }
120    }
121}
122
123impl std::fmt::Display for KeyName {
124    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
125        f.write_str(self.as_str())
126    }
127}