// src/client/ui/handlers/ui.rs use crate::tui::terminal::TerminalCore; use crate::tui::terminal::GrpcClient; use crate::tui::terminal::CommandHandler; use crate::tui::terminal::EventReader; use crate::config::colors::Theme; use crate::config::config::Config; use crate::ui::handlers::{form::FormState, render::render_ui}; use crate::modes::handlers::event::EventHandler; use crate::state::state::AppState; pub async fn run_ui() -> Result<(), Box> { let config = Config::load()?; let mut terminal = TerminalCore::new()?; // Remove .await let mut grpc_client = GrpcClient::new().await?; let mut command_handler = CommandHandler::new(grpc_client); let theme = Theme::from_str(&config.colors.theme); // Fetch table structure at startup (one-time) // TODO: Later, consider implementing a live update for table structure changes. let table_structure = grpc_client.get_table_structure().await?; // Changed // Extract the column names from the response let column_names: Vec = table_structure .columns .iter() .map(|col| col.name.clone()) .collect(); // Initialize FormState with dynamic fields let mut form_state = FormState::new(column_names); // The rest of your UI initialization remains the same let mut event_handler = EventHandler::new(); let event_reader = EventReader::new(); let mut app_state = AppState::new()?; // Fetch the total count of Adresar entries let total_count = grpc_client.get_adresar_count().await?; app_state.update_total_count(total_count); app_state.update_current_position(total_count.saturating_add(1)); // Start in new entry mode form_state.reset_to_empty(); loop { let total_count = grpc_client.get_adresar_count().await?; app_state.update_total_count(total_count); terminal.draw(|f| { render_ui( f, &mut form_state, &theme, event_handler.is_edit_mode, app_state.total_count, app_state.current_position, &app_state.current_dir, &event_handler.command_input, event_handler.command_mode, &event_handler.command_message, ); })?; let event = event_reader.read_event()?; let (should_exit, message) = event_handler.handle_event( event, &config, &mut terminal, &mut grpc_client, &mut command_handler, &mut form_state, &mut app_state.is_saved, app_state.total_count, &mut app_state.current_position, ).await?; // Handle position changes and update form state if !event_handler.is_edit_mode { let current_input = form_state.get_current_input(); let max_cursor_pos = if !current_input.is_empty() { current_input.len() - 1 // Limit to last character in readonly mode } else { 0 }; form_state.current_cursor_pos = event_handler.ideal_cursor_column.min(max_cursor_pos); // Ensure position never exceeds total_count + 1 if app_state.current_position > total_count + 1 { app_state.current_position = total_count + 1; } if app_state.current_position > total_count { // New entry - reset form form_state.reset_to_empty(); form_state.current_field = 0; } else if app_state.current_position >= 1 && app_state.current_position <= total_count { // Existing entry - load data match grpc_client.get_adresar_by_position(app_state.current_position).await { Ok(response) => { // Set the ID properly form_state.id = response.id; // Update form values dynamically form_state.values = vec![ response.firma, response.kz, response.drc, response.ulica, response.psc, response.mesto, response.stat, response.banka, response.ucet, response.skladm, response.ico, response.kontakt, response.telefon, response.skladu, response.fax, ]; let current_input = form_state.get_current_input(); let max_cursor_pos = if !event_handler.is_edit_mode && !current_input.is_empty() { current_input.len() - 1 // In readonly mode, limit to last character } else { current_input.len() }; form_state.current_cursor_pos = event_handler.ideal_cursor_column.min(max_cursor_pos); form_state.has_unsaved_changes = false; event_handler.command_message = format!("Loaded entry {}", app_state.current_position); } Err(e) => { event_handler.command_message = format!("Error loading entry: {}", e); } } } else { // Invalid position - reset to first entry app_state.current_position = 1; } } event_handler.command_message = message; if should_exit { return Ok(()); } } }