// src/modes/general/navigation.rs use crossterm::event::KeyEvent; use crate::config::binds::config::Config; use crate::state::app::state::AppState; use crate::state::pages::form::FormState; use crate::state::pages::auth::LoginState; use crate::state::pages::auth::RegisterState; use crate::state::pages::intro::IntroState; use crate::state::pages::admin::AdminState; use crate::state::pages::canvas_state::CanvasState; use crate::ui::handlers::context::UiContext; use crate::modes::handlers::event::EventOutcome; use crate::modes::general::command_navigation::{handle_command_navigation_event, NavigationState}; use anyhow::Result; pub async fn handle_navigation_event( key: KeyEvent, config: &Config, form_state: &mut FormState, app_state: &mut AppState, login_state: &mut LoginState, register_state: &mut RegisterState, intro_state: &mut IntroState, admin_state: &mut AdminState, command_mode: &mut bool, command_input: &mut String, command_message: &mut String, navigation_state: &mut NavigationState, ) -> Result { // Handle command navigation first if active if navigation_state.active { return handle_command_navigation_event(navigation_state, key, config).await; } if let Some(action) = config.get_general_action(key.code, key.modifiers) { match action { "move_up" => { move_up(app_state, login_state, register_state, intro_state, admin_state); return Ok(EventOutcome::Ok(String::new())); } "move_down" => { move_down(app_state, intro_state, admin_state); return Ok(EventOutcome::Ok(String::new())); } "next_option" => { next_option(app_state, intro_state); return Ok(EventOutcome::Ok(String::new())); } "previous_option" => { previous_option(app_state, intro_state); return Ok(EventOutcome::Ok(String::new())); } "next_field" => { next_field(form_state); return Ok(EventOutcome::Ok(String::new())); } "prev_field" => { prev_field(form_state); return Ok(EventOutcome::Ok(String::new())); } "enter_command_mode" => { handle_enter_command_mode(command_mode, command_input, command_message); return Ok(EventOutcome::Ok(String::new())); } "select" => { let (context, index) = if app_state.ui.show_intro { (UiContext::Intro, intro_state.selected_option) } else if app_state.ui.show_login && app_state.ui.focus_outside_canvas { (UiContext::Login, app_state.focused_button_index) } else if app_state.ui.show_register && app_state.ui.focus_outside_canvas { (UiContext::Register, app_state.focused_button_index) } else if app_state.ui.show_admin { (UiContext::Admin, admin_state.get_selected_index().unwrap_or(0)) } else if app_state.ui.dialog.dialog_show { (UiContext::Dialog, app_state.ui.dialog.dialog_active_button_index) } else { return Ok(EventOutcome::Ok("Select (No Action)".to_string())); }; return Ok(EventOutcome::ButtonSelected { context, index }); } _ => {} } } Ok(EventOutcome::Ok(String::new())) } pub fn move_up(app_state: &mut AppState, login_state: &mut LoginState, register_state: &mut RegisterState, intro_state: &mut IntroState, admin_state: &mut AdminState) { if app_state.ui.focus_outside_canvas && app_state.ui.show_login || app_state.ui.show_register{ if app_state.focused_button_index == 0 { app_state.ui.focus_outside_canvas = false; if app_state.ui.show_login { let last_field_index = login_state.fields().len().saturating_sub(1); login_state.set_current_field(last_field_index); } else { let last_field_index = register_state.fields().len().saturating_sub(1); register_state.set_current_field(last_field_index); } } else { app_state.focused_button_index = app_state.focused_button_index.saturating_sub(1); } } else if app_state.ui.show_intro { intro_state.previous_option(); } else if app_state.ui.show_admin { admin_state.previous(); } } pub fn move_down(app_state: &mut AppState, intro_state: &mut IntroState, admin_state: &mut AdminState) { if app_state.ui.focus_outside_canvas && app_state.ui.show_login || app_state.ui.show_register { let num_general_elements = 2; if app_state.focused_button_index < num_general_elements - 1 { app_state.focused_button_index += 1; } } else if app_state.ui.show_intro { intro_state.next_option(); } else if app_state.ui.show_admin { admin_state.next(); } } pub fn next_option(app_state: &mut AppState, intro_state: &mut IntroState) { if app_state.ui.show_intro { intro_state.next_option(); } else { // Get option count from state instead of parameter let option_count = app_state.profile_tree.profiles.len(); app_state.focused_button_index = (app_state.focused_button_index + 1) % option_count; } } pub fn previous_option(app_state: &mut AppState, intro_state: &mut IntroState) { if app_state.ui.show_intro { intro_state.previous_option(); } else { let option_count = app_state.profile_tree.profiles.len(); app_state.focused_button_index = if app_state.focused_button_index == 0 { option_count.saturating_sub(1) } else { app_state.focused_button_index - 1 }; } } pub fn next_field(form_state: &mut FormState) { if !form_state.fields.is_empty() { form_state.current_field = (form_state.current_field + 1) % form_state.fields.len(); } } pub fn prev_field(form_state: &mut FormState) { if !form_state.fields.is_empty() { if form_state.current_field == 0 { form_state.current_field = form_state.fields.len() - 1; } else { form_state.current_field -= 1; } } } pub fn handle_enter_command_mode( command_mode: &mut bool, command_input: &mut String, command_message: &mut String ) { *command_mode = true; command_input.clear(); command_message.clear(); }