Skip to main content

a2ui_base/
interaction.rs

1//! Framework-agnostic interaction helpers — applying component interaction
2//! results to the runtime state.
3//!
4//! This module holds the parts of the keyboard/interaction pipeline that touch
5//! only core types, so every backend (ratatui, Slint, …) shares them. The
6//! key-mapping and component-dispatch halves stay backend-side: each backend
7//! maps its own key enum to [`crate::event::InputKey`] and dispatches via its
8//! own component registry (or, after the shared-behavior extraction, via
9//! [`crate::components::dispatch_event`]).
10//!
11//! See the tui crate's `interaction` module for the original implementation
12//! this was lifted from.
13
14use crate::event::EventResult;
15use crate::message_processor::MessageProcessor;
16
17/// Apply an [`EventResult`] produced by a component to the processor's state.
18///
19/// Returns `Some(path)` only for an [`EventResult::Action`] that expects a
20/// response — the path is where the eventual server response value should be
21/// written — so the caller can drive the action-response cycle. Every other
22/// variant returns `None`.
23pub fn apply_event_result(processor: &mut MessageProcessor, result: EventResult) -> Option<String> {
24    match result {
25        EventResult::Action {
26            want_response,
27            response_path,
28            // event_name / context are intentionally ignored, matching the gallery.
29            ..
30        } => {
31            if want_response {
32                let surface_id = processor
33                    .model
34                    .surfaces()
35                    .next()
36                    .map(|s| s.id.clone());
37                if let Some(sid) = surface_id {
38                    let action_id = uuid::Uuid::new_v4().to_string();
39                    let _ = processor.register_action(&sid, &action_id, response_path.clone());
40                }
41                response_path
42            } else {
43                None
44            }
45        }
46        EventResult::DataUpdate { path, value } => {
47            if let Some(surface) = processor.model.surfaces_mut().next() {
48                surface.data_model.borrow_mut().set(&path, value);
49            }
50            None
51        }
52        EventResult::Toggle { path } => {
53            if let Some(surface) = processor.model.surfaces_mut().next() {
54                let current = surface
55                    .data_model
56                    .borrow()
57                    .get(&path)
58                    .and_then(|v| v.as_bool())
59                    .unwrap_or(false);
60                surface
61                    .data_model
62                    .borrow_mut()
63                    .set(&path, serde_json::json!(!current));
64            }
65            None
66        }
67        EventResult::Consumed => None,
68    }
69}