From bc9e62e8e24f5e218acd471404455ef57bc7d752 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Fri, 27 Mar 2026 10:45:04 -0700 Subject: chore(deps): Update to eye-declare v0.2.0 (#3355) eye-declare v0.2.0 includes two relevant changes: * "Capture-phase" event handling lets us remove the special-case event handling in `InputBox` that allowed global keyboard binds to work; the `AtuinAi` component now handles this directly. * `Tracked::read()` allows reading fields in tracked state without triggering the dirty-tracking from the `DerefMut` implementation, allowing us to send messages on the app event bus without marking the containing state as dirty. --- Cargo.lock | 8 ++++---- crates/atuin-ai/Cargo.toml | 2 +- crates/atuin-ai/src/tui/components/atuin_ai.rs | 6 ++++-- crates/atuin-ai/src/tui/components/input_box.rs | 24 ++++++------------------ 4 files changed, 15 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 03e78c09..1fa8ebca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1498,9 +1498,9 @@ dependencies = [ [[package]] name = "eye_declare" -version = "0.1.4" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29f7a306e9da6182b45de1c5e29ca9d469f6aa4cd0bdd6ff0da4bdaf67bec4ff" +checksum = "4d025f4c5954a5797f81cdde3871f301a3e5bca02e3110848de0f2c348a05573" dependencies = [ "crossterm", "eye_declare_macros", @@ -1513,9 +1513,9 @@ dependencies = [ [[package]] name = "eye_declare_macros" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c552b6cb631a6826de9c793d7f1b620e4007c6f8ee584f2bc428d193c14b3381" +checksum = "7ad7509865efe5f9cd4b05db4e50605e06c6425b7ef1a579526bebb3bd4bfa1a" dependencies = [ "proc-macro2", "quote", diff --git a/crates/atuin-ai/Cargo.toml b/crates/atuin-ai/Cargo.toml index a62e3274..f4d6e8f2 100644 --- a/crates/atuin-ai/Cargo.toml +++ b/crates/atuin-ai/Cargo.toml @@ -39,7 +39,7 @@ async-stream = "0.3" uuid = { workspace = true } tui-textarea-2 = "0.10.2" unicode-width = "0.2" -eye_declare = "0.1" +eye_declare = "0.2" ratatui-core = "0.1" ratatui-widgets = "0.3" diff --git a/crates/atuin-ai/src/tui/components/atuin_ai.rs b/crates/atuin-ai/src/tui/components/atuin_ai.rs index 680b93ed..b2239a70 100644 --- a/crates/atuin-ai/src/tui/components/atuin_ai.rs +++ b/crates/atuin-ai/src/tui/components/atuin_ai.rs @@ -7,7 +7,7 @@ use std::sync::mpsc; use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers}; -use eye_declare::{Component, EventResult, Hooks, impl_slot_children}; +use eye_declare::{Component, EventResult, Hooks, Tracked, impl_slot_children}; use crate::tui::events::AiTuiEvent; use crate::tui::state::AppMode; @@ -67,7 +67,9 @@ impl Component for AtuinAi { 0 } - fn handle_event(&self, event: &Event, state: &mut Self::State) -> EventResult { + fn handle_event_capture(&self, event: &Event, state: &mut Tracked) -> EventResult { + let state = state.read(); + let Event::Key(KeyEvent { code, kind: KeyEventKind::Press, diff --git a/crates/atuin-ai/src/tui/components/input_box.rs b/crates/atuin-ai/src/tui/components/input_box.rs index fd8132f4..3167ecc1 100644 --- a/crates/atuin-ai/src/tui/components/input_box.rs +++ b/crates/atuin-ai/src/tui/components/input_box.rs @@ -9,7 +9,7 @@ use std::sync::{Mutex, mpsc}; use crossterm::event::KeyModifiers; -use eye_declare::{Component, EventResult, Hooks}; +use eye_declare::{Component, EventResult, Hooks, Tracked}; use ratatui::widgets::{Block, Borders, Padding}; use ratatui_core::{ buffer::Buffer, @@ -153,8 +153,10 @@ impl Component for InputBox { fn handle_event( &self, event: &crossterm::event::Event, - state: &mut Self::State, + state: &mut Tracked, ) -> EventResult { + let state = state.read(); + if !self.active { return EventResult::Ignored; } @@ -170,13 +172,6 @@ impl Component for InputBox { return EventResult::Ignored; } - // Let Ctrl+C bubble up to AtuinAi for exit handling - if key.modifiers.contains(KeyModifiers::CONTROL) - && key.code == crossterm::event::KeyCode::Char('c') - { - return EventResult::Ignored; - } - let mut textarea = state.textarea.lock().unwrap(); match key.code { @@ -192,25 +187,18 @@ impl Component for InputBox { return EventResult::Consumed; } else { let text = textarea.lines().join("\n"); - textarea.clear(); - if text.trim().is_empty() { return EventResult::Ignored; } + textarea.clear(); + if let Some(ref tx) = state.tx { let _ = tx.send(AiTuiEvent::SubmitInput(text)); } return EventResult::Consumed; } } - crossterm::event::KeyCode::Tab => { - return EventResult::Ignored; - } - // Esc: bubble up to app - crossterm::event::KeyCode::Esc => { - return EventResult::Ignored; - } _ => {} } -- cgit v1.3.1