From 57285a1cfaa895b2adfd65d0bd0619a90895a5d6 Mon Sep 17 00:00:00 2001 From: leafx54 Date: Mon, 25 Aug 2025 19:13:06 -0400 Subject: [PATCH] refactor: Improve code formatting and readability across UI components --- crates/agentic-tui/src/ui/app.rs | 57 +++++++++++++------ crates/agentic-tui/src/ui/chat.rs | 54 ++++++++++++++---- crates/agentic-tui/src/ui/footer.rs | 16 ++++-- .../src/ui/model_selection_modal.rs | 22 ++++--- crates/agentic-tui/src/ui/settings_modal.rs | 16 ++---- 5 files changed, 111 insertions(+), 54 deletions(-) diff --git a/crates/agentic-tui/src/ui/app.rs b/crates/agentic-tui/src/ui/app.rs index e945413..31e5939 100644 --- a/crates/agentic-tui/src/ui/app.rs +++ b/crates/agentic-tui/src/ui/app.rs @@ -1,6 +1,9 @@ use super::{ - chat::render_chat, footer::render_footer, header::render_header, - model_selection_modal::{render_model_selection_modal, ModelSelectionParams}, settings_modal::render_settings_modal, + chat::render_chat, + footer::render_footer, + header::render_header, + model_selection_modal::{render_model_selection_modal, ModelSelectionParams}, + settings_modal::render_settings_modal, }; use agentic_core::{ models::{ModelValidator, OllamaModel, OpenRouterModel}, @@ -169,7 +172,13 @@ impl App { self.agent_status, &self.settings, ); - render_footer(frame, app_chunks[2], &self.theme, self.mode, &self.edit_buffer); + render_footer( + frame, + app_chunks[2], + &self.theme, + self.mode, + &self.edit_buffer, + ); if matches!( self.mode, @@ -200,7 +209,11 @@ impl App { frame.render_widget(Clear, modal_area); // clears the background if self.mode == AppMode::SelectingLocalModel { - let local_models = self.available_local_models.iter().map(|m| (m.name.clone(), m.size.to_string())).collect::>(); + let local_models = self + .available_local_models + .iter() + .map(|m| (m.name.clone(), m.size.to_string())) + .collect::>(); render_model_selection_modal( frame, modal_area, @@ -239,7 +252,14 @@ impl App { ); } } else { - render_chat(frame, app_chunks[1], &self.theme, self.mode, &self.edit_buffer, self.agent_status); + render_chat( + frame, + app_chunks[1], + &self.theme, + self.mode, + &self.edit_buffer, + self.agent_status, + ); } })?; Ok(()) @@ -443,7 +463,8 @@ impl App { } } KeyCode::Down => { - if self.selected_model_index + 1 < self.available_local_models.len() { + if self.selected_model_index + 1 < self.available_local_models.len() + { self.selected_model_index += 1; self.adjust_page_for_selection(); } @@ -476,7 +497,8 @@ impl App { } } KeyCode::Down => { - if self.selected_model_index + 1 < self.available_cloud_models.len() { + if self.selected_model_index + 1 < self.available_cloud_models.len() + { self.selected_model_index += 1; self.adjust_page_for_selection(); } @@ -574,7 +596,7 @@ impl App { fn handle_chat_message(&mut self) { let message = self.edit_buffer.trim().to_string(); - + if message.starts_with('/') { // Handle slash commands self.handle_slash_command(&message); @@ -584,7 +606,7 @@ impl App { // For now, just clear the input println!("Chat message: {}", message); } - + // Clear input after processing self.edit_buffer.clear(); } @@ -688,7 +710,7 @@ impl App { // Always create a new channel and spawn the task let (tx, rx) = mpsc::unbounded_channel(); self.validation_rx = Some(rx); - + // Spawn async task to fetch cloud models let api_key = self.settings.api_key.clone(); tokio::spawn(async move { @@ -705,12 +727,15 @@ impl App { } fn format_cloud_models_with_emojis(&self) -> Vec<(String, String)> { - self.available_cloud_models.iter().map(|m| { - let is_free = m.pricing.prompt == "0" && m.pricing.completion == "0"; - let emoji = if is_free { "๐Ÿ†“" } else { "๐Ÿ’ฐ" }; - let name = format!("{} {}", emoji, m.name); - (name, String::new()) // No secondary info column - }).collect() + self.available_cloud_models + .iter() + .map(|m| { + let is_free = m.pricing.prompt == "0" && m.pricing.completion == "0"; + let emoji = if is_free { "๐Ÿ†“" } else { "๐Ÿ’ฐ" }; + let name = format!("{} {}", emoji, m.name); + (name, String::new()) // No secondary info column + }) + .collect() } fn previous_page(&mut self) { diff --git a/crates/agentic-tui/src/ui/chat.rs b/crates/agentic-tui/src/ui/chat.rs index 2d14d5b..13eeef7 100644 --- a/crates/agentic-tui/src/ui/chat.rs +++ b/crates/agentic-tui/src/ui/chat.rs @@ -56,7 +56,14 @@ const GAP_HEIGHT: u16 = 1; const MAIN_TOTAL_HEIGHT: u16 = MAIN_LOGO_HEIGHT + GAP_HEIGHT + TEXT_HEIGHT; const SPIRAL_TOTAL_HEIGHT: u16 = SPIRAL_GALAXY_HEIGHT; -pub fn render_chat(frame: &mut Frame, area: Rect, theme: &Theme, mode: AppMode, chat_input: &str, agent_status: AgentStatus) { +pub fn render_chat( + frame: &mut Frame, + area: Rect, + theme: &Theme, + mode: AppMode, + chat_input: &str, + agent_status: AgentStatus, +) { let chat_block = Block::new() .borders(Borders::ALL) .title(" ๐Ÿคจ ๐Ÿ” ๐Ÿ’ก ") @@ -112,15 +119,42 @@ pub fn render_chat(frame: &mut Frame, area: Rect, theme: &Theme, mode: AppMode, // Status-based message let (status_text, status_style) = match agent_status { - AgentStatus::Ready => ("Press [ENTER] to Start Ruixen", theme.ratatui_style(Element::Accent)), - AgentStatus::LocalEndpointError => ("โš ๏ธ Local endpoint error - Check settings [S]", theme.ratatui_style(Element::Warning)), - AgentStatus::CloudEndpointError => ("โš ๏ธ Cloud endpoint error - Check settings [S]", theme.ratatui_style(Element::Warning)), - AgentStatus::CheckLocalModel => ("โš ๏ธ Local model not configured - Check settings [S]", theme.ratatui_style(Element::Warning)), - AgentStatus::CheckCloudModel => ("โš ๏ธ Cloud model not configured - Check settings [S]", theme.ratatui_style(Element::Warning)), - AgentStatus::CheckApiKey => ("โš ๏ธ API key not configured - Check settings [S]", theme.ratatui_style(Element::Warning)), - AgentStatus::ValidatingLocal => ("๐Ÿ”„ Validating local endpoint...", theme.ratatui_style(Element::Info)), - AgentStatus::ValidatingCloud => ("๐Ÿ”„ Validating cloud endpoint...", theme.ratatui_style(Element::Info)), - _ => ("Press [ENTER] when local and cloud models are ready", theme.ratatui_style(Element::Inactive)), + AgentStatus::Ready => ( + "Press [ENTER] to Start Ruixen", + theme.ratatui_style(Element::Accent), + ), + AgentStatus::LocalEndpointError => ( + "โš ๏ธ Local endpoint error - Check settings [S]", + theme.ratatui_style(Element::Warning), + ), + AgentStatus::CloudEndpointError => ( + "โš ๏ธ Cloud endpoint error - Check settings [S]", + theme.ratatui_style(Element::Warning), + ), + AgentStatus::CheckLocalModel => ( + "โš ๏ธ Local model not configured - Check settings [S]", + theme.ratatui_style(Element::Warning), + ), + AgentStatus::CheckCloudModel => ( + "โš ๏ธ Cloud model not configured - Check settings [S]", + theme.ratatui_style(Element::Warning), + ), + AgentStatus::CheckApiKey => ( + "โš ๏ธ API key not configured - Check settings [S]", + theme.ratatui_style(Element::Warning), + ), + AgentStatus::ValidatingLocal => ( + "๐Ÿ”„ Validating local endpoint...", + theme.ratatui_style(Element::Info), + ), + AgentStatus::ValidatingCloud => ( + "๐Ÿ”„ Validating cloud endpoint...", + theme.ratatui_style(Element::Info), + ), + _ => ( + "Press [ENTER] when local and cloud models are ready", + theme.ratatui_style(Element::Inactive), + ), }; let status_paragraph = Paragraph::new(status_text) diff --git a/crates/agentic-tui/src/ui/footer.rs b/crates/agentic-tui/src/ui/footer.rs index 009985e..13fbe35 100644 --- a/crates/agentic-tui/src/ui/footer.rs +++ b/crates/agentic-tui/src/ui/footer.rs @@ -6,13 +6,19 @@ use ratatui::{ widgets::{Block, Borders, Paragraph}, }; -pub fn render_footer(frame: &mut Frame, area: Rect, theme: &Theme, mode: AppMode, chat_input: &str) { +pub fn render_footer( + frame: &mut Frame, + area: Rect, + theme: &Theme, + mode: AppMode, + chat_input: &str, +) { let footer_block = Block::default() .borders(Borders::ALL) .style(theme.ratatui_style(Element::Active)); let inner_area = footer_block.inner(area); - + let content = match mode { AppMode::Chat => { // Chat input field with cursor @@ -21,17 +27,17 @@ pub fn render_footer(frame: &mut Frame, area: Rect, theme: &Theme, mode: AppMode } else { chat_input }; - + let mut spans = vec![ Span::styled("๐Ÿ’ฌ ", theme.ratatui_style(Element::Accent)), Span::styled(display_text, theme.text_style()), ]; - + // Add cursor when in chat mode if !chat_input.is_empty() || area.width > 50 { spans.push(Span::styled("_", theme.highlight_style())); } - + Line::from(spans) } _ => { diff --git a/crates/agentic-tui/src/ui/model_selection_modal.rs b/crates/agentic-tui/src/ui/model_selection_modal.rs index 9618160..81a38a6 100644 --- a/crates/agentic-tui/src/ui/model_selection_modal.rs +++ b/crates/agentic-tui/src/ui/model_selection_modal.rs @@ -15,11 +15,7 @@ pub struct ModelSelectionParams<'a> { pub models_per_page: usize, } -pub fn render_model_selection_modal( - frame: &mut Frame, - area: Rect, - params: ModelSelectionParams, -) { +pub fn render_model_selection_modal(frame: &mut Frame, area: Rect, params: ModelSelectionParams) { let block = Block::new() .title(params.title) .borders(Borders::ALL) @@ -52,10 +48,15 @@ pub fn render_model_selection_modal( let total_pages = params.models.len().div_ceil(params.models_per_page); let start_index = params.current_page * params.models_per_page; let end_index = std::cmp::min(start_index + params.models_per_page, params.models.len()); - + // Page indicator let page_info = if total_pages > 1 { - format!("Page {} of {} ({} models)", params.current_page + 1, total_pages, params.models.len()) + format!( + "Page {} of {} ({} models)", + params.current_page + 1, + total_pages, + params.models.len() + ) } else { format!("{} models", params.models.len()) }; @@ -66,7 +67,7 @@ pub fn render_model_selection_modal( // Get models for current page let page_models = ¶ms.models[start_index..end_index]; - + // Create list items for current page let items: Vec = page_models .iter() @@ -88,10 +89,7 @@ pub fn render_model_selection_modal( } else { // Show name and info in columns when both are present Line::from(vec![ - Span::styled( - format!("{:<40}", name), - style.add_modifier(Modifier::BOLD), - ), + Span::styled(format!("{:<40}", name), style.add_modifier(Modifier::BOLD)), Span::styled(format!("{:>15}", info), style), ]) }; diff --git a/crates/agentic-tui/src/ui/settings_modal.rs b/crates/agentic-tui/src/ui/settings_modal.rs index 711dd09..8d2697d 100644 --- a/crates/agentic-tui/src/ui/settings_modal.rs +++ b/crates/agentic-tui/src/ui/settings_modal.rs @@ -139,15 +139,9 @@ pub fn render_settings_modal( // Action Text let action_text = match mode { - AppMode::EditingApiKey => { - "[ENTER] Save | [CTRL+V] Paste | [ESC] Cancel" - }, - AppMode::EditingEndpoint => { - "[ENTER] Save | [ESC] Cancel" - }, - _ => { - "[ENTER] Edit | [โ†‘โ†“] Navigate | [S]ave | [R]eturn" - } + AppMode::EditingApiKey => "[ENTER] Save | [CTRL+V] Paste | [ESC] Cancel", + AppMode::EditingEndpoint => "[ENTER] Save | [ESC] Cancel", + _ => "[ENTER] Edit | [โ†‘โ†“] Navigate | [S]ave | [R]eturn", }; let action_style = if selection == SettingsSelection::Save { theme.highlight_style() @@ -164,13 +158,13 @@ fn format_api_key_display(api_key: &str) -> String { if api_key.is_empty() { return String::new(); } - + // For most API keys, show first 15 characters + "..." + last 3 characters // This gives us the pattern: "sk-or-v1-7d9200...3ac" (21 chars total) if api_key.len() <= 21 { // If it's already short enough, just return it api_key.to_string() } else { - format!("{}...{}", &api_key[..15], &api_key[api_key.len()-3..]) + format!("{}...{}", &api_key[..15], &api_key[api_key.len() - 3..]) } }