Files
voicebox/tauri/src-tauri/src/key_codes.rs
T
James PineandClaude Opus 4.7 87c582ad54 feat(capture): dictation, personalities, 0.5.0
Ships the Capture release end to end. Global-hotkey dictation with
synthetic paste into the focused app on macOS and Windows, an on-screen
pill across recording / transcribing / refining, customizable push-to-
talk and toggle chords, and an accessibility-permission prompt scoped to
Settings → Captures with inline re-check feedback.

Voice profiles gain optional personalities that power compose / rewrite /
respond actions via a local Qwen3 LLM — shared with refinement, so there
is one local LLM in the app, not two.

Refinement hardened with deterministic Whisper-loop collapse before the
LLM sees the transcript, per-capture flag snapshots for re-runs, and a
ten-transcript evaluation harness across every bundled refinement size.

Version bump 0.4.5 → 0.5.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-04-22 18:49:16 -07:00

93 lines
3.9 KiB
Rust

//! Stable string ↔ `rdev::Key` mapping for chord persistence.
//!
//! The frontend captures keypresses through the browser keyboard API (which
//! exposes `event.code` like `"MetaRight"`, `"AltRight"`, `"Space"`, `"KeyA"`)
//! and stores chords in capture_settings as JSON arrays of canonical names.
//! On the way back the same names need to round-trip into `rdev::Key`
//! variants the chord engine actually matches against.
//!
//! Names follow the rdev variant identifiers exactly (`"MetaRight"`,
//! `"AltGr"`, `"KeyA"`, …) with one alias: the browser reports right-Option
//! as `"AltRight"` while rdev calls it `"AltGr"`. Both map to the same key.
use rdev::Key;
/// Resolve a canonical key name to its `rdev::Key`. Returns `None` for
/// names that don't have a corresponding variant — the command surface
/// rejects those so we never silently drop keys from a chord.
pub fn key_from_str(name: &str) -> Option<Key> {
Some(match name {
// Modifiers — left/right distinction matters for chord defaults.
"Alt" | "AltLeft" => Key::Alt,
"AltGr" | "AltRight" => Key::AltGr,
"ControlLeft" => Key::ControlLeft,
"ControlRight" => Key::ControlRight,
"MetaLeft" => Key::MetaLeft,
"MetaRight" => Key::MetaRight,
"ShiftLeft" => Key::ShiftLeft,
"ShiftRight" => Key::ShiftRight,
"CapsLock" => Key::CapsLock,
"Function" => Key::Function,
// Whitespace / navigation
"Space" => Key::Space,
"Tab" => Key::Tab,
"Return" | "Enter" => Key::Return,
"Backspace" => Key::Backspace,
"Delete" => Key::Delete,
"Escape" => Key::Escape,
"Insert" => Key::Insert,
"Home" => Key::Home,
"End" => Key::End,
"PageUp" => Key::PageUp,
"PageDown" => Key::PageDown,
"ArrowUp" | "UpArrow" => Key::UpArrow,
"ArrowDown" | "DownArrow" => Key::DownArrow,
"ArrowLeft" | "LeftArrow" => Key::LeftArrow,
"ArrowRight" | "RightArrow" => Key::RightArrow,
// Function row
"F1" => Key::F1, "F2" => Key::F2, "F3" => Key::F3, "F4" => Key::F4,
"F5" => Key::F5, "F6" => Key::F6, "F7" => Key::F7, "F8" => Key::F8,
"F9" => Key::F9, "F10" => Key::F10, "F11" => Key::F11, "F12" => Key::F12,
// Digits
"Digit0" | "Num0" => Key::Num0,
"Digit1" | "Num1" => Key::Num1,
"Digit2" | "Num2" => Key::Num2,
"Digit3" | "Num3" => Key::Num3,
"Digit4" | "Num4" => Key::Num4,
"Digit5" | "Num5" => Key::Num5,
"Digit6" | "Num6" => Key::Num6,
"Digit7" | "Num7" => Key::Num7,
"Digit8" | "Num8" => Key::Num8,
"Digit9" | "Num9" => Key::Num9,
// Letters — browser uses "KeyA" style which already matches rdev.
"KeyA" => Key::KeyA, "KeyB" => Key::KeyB, "KeyC" => Key::KeyC,
"KeyD" => Key::KeyD, "KeyE" => Key::KeyE, "KeyF" => Key::KeyF,
"KeyG" => Key::KeyG, "KeyH" => Key::KeyH, "KeyI" => Key::KeyI,
"KeyJ" => Key::KeyJ, "KeyK" => Key::KeyK, "KeyL" => Key::KeyL,
"KeyM" => Key::KeyM, "KeyN" => Key::KeyN, "KeyO" => Key::KeyO,
"KeyP" => Key::KeyP, "KeyQ" => Key::KeyQ, "KeyR" => Key::KeyR,
"KeyS" => Key::KeyS, "KeyT" => Key::KeyT, "KeyU" => Key::KeyU,
"KeyV" => Key::KeyV, "KeyW" => Key::KeyW, "KeyX" => Key::KeyX,
"KeyY" => Key::KeyY, "KeyZ" => Key::KeyZ,
// Punctuation / symbols
"Backquote" | "BackQuote" => Key::BackQuote,
"Minus" => Key::Minus,
"Equal" => Key::Equal,
"BracketLeft" | "LeftBracket" => Key::LeftBracket,
"BracketRight" | "RightBracket" => Key::RightBracket,
"Semicolon" | "SemiColon" => Key::SemiColon,
"Quote" => Key::Quote,
"Backslash" | "BackSlash" => Key::BackSlash,
"Comma" => Key::Comma,
"Period" | "Dot" => Key::Dot,
"Slash" => Key::Slash,
_ => return None,
})
}