agent_air_tui/widgets/
mod.rs1use crossterm::event::KeyEvent;
21use ratatui::{Frame, layout::Rect};
22use std::any::Any;
23
24use crate::controller::{AskUserQuestionsResponse, PermissionPanelResponse};
25use crate::keys::NavigationHelper;
26use crate::permissions::BatchPermissionResponse;
27use crate::themes::Theme;
28
29pub mod batch_permission_panel;
30pub mod chat;
31pub mod chat_helpers;
32pub mod conversation;
33pub mod input;
34pub mod permission_panel;
35pub mod question_panel;
36pub mod session_picker;
37pub mod slash_popup;
38pub mod status_bar;
39
40pub use batch_permission_panel::{
41 BatchKeyAction, BatchPermissionOption, BatchPermissionPanel, BatchPermissionPanelConfig,
42};
43pub use chat::{ChatView, ChatViewConfig, MessageRole, ToolMessageData, ToolStatus};
44pub use chat_helpers::RenderFn;
45pub use conversation::{ConversationView, ConversationViewFactory};
46pub use input::TextInput;
47pub use permission_panel::{
48 KeyAction as PermissionKeyAction, PermissionOption, PermissionPanel, PermissionPanelConfig,
49};
50pub use question_panel::{
51 AnswerState, EnterAction, FocusItem, KeyAction as QuestionKeyAction, QuestionPanel,
52 QuestionPanelConfig,
53};
54pub use session_picker::{
55 SessionInfo, SessionPickerConfig, SessionPickerState, render_session_picker,
56};
57pub use slash_popup::{
58 SimpleCommand, SlashCommandDisplay, SlashPopupConfig, SlashPopupState, render_slash_popup,
59};
60pub use status_bar::{StatusBar, StatusBarConfig, StatusBarData};
61
62pub mod widget_ids {
64 pub const CHAT_VIEW: &str = "chat_view";
66 pub const TEXT_INPUT: &str = "text_input";
67
68 pub const BATCH_PERMISSION_PANEL: &str = "batch_permission_panel";
70 pub const PERMISSION_PANEL: &str = "permission_panel";
71 pub const QUESTION_PANEL: &str = "question_panel";
72 pub const SESSION_PICKER: &str = "session_picker";
73 pub const SLASH_POPUP: &str = "slash_popup";
74 pub const THEME_PICKER: &str = "theme_picker";
75 pub const STATUS_BAR: &str = "status_bar";
76}
77
78pub struct WidgetKeyContext<'a> {
83 pub theme: &'a Theme,
85 pub nav: NavigationHelper<'a>,
87}
88
89#[derive(Debug, Clone)]
91pub enum WidgetKeyResult {
92 NotHandled,
94 Handled,
96 Action(WidgetAction),
98}
99
100#[derive(Debug, Clone)]
102pub enum WidgetAction {
103 SubmitQuestion {
105 tool_use_id: String,
106 response: AskUserQuestionsResponse,
107 },
108 CancelQuestion { tool_use_id: String },
110 SubmitPermission {
112 tool_use_id: String,
113 response: PermissionPanelResponse,
114 },
115 CancelPermission { tool_use_id: String },
117 SubmitBatchPermission {
119 batch_id: String,
120 response: BatchPermissionResponse,
121 },
122 CancelBatchPermission { batch_id: String },
124 SwitchSession { session_id: i64 },
126 ExecuteCommand { command: String },
128 Close,
130}
131
132pub trait Widget: Send + 'static {
137 fn id(&self) -> &'static str;
139
140 fn priority(&self) -> u8 {
145 100
146 }
147
148 fn is_active(&self) -> bool;
150
151 fn handle_key(&mut self, key: KeyEvent, ctx: &WidgetKeyContext) -> WidgetKeyResult;
156
157 fn render(&mut self, frame: &mut Frame, area: Rect, theme: &Theme);
159
160 fn required_height(&self, available: u16) -> u16 {
164 let _ = available;
165 0
166 }
167
168 fn blocks_input(&self) -> bool {
170 false
171 }
172
173 fn is_overlay(&self) -> bool {
177 false
178 }
179
180 fn as_any(&self) -> &dyn Any;
182
183 fn as_any_mut(&mut self) -> &mut dyn Any;
185
186 fn into_any(self: Box<Self>) -> Box<dyn Any>;
188}