diff --git a/client/src/functions/modes.rs b/client/src/functions/modes.rs index 5618a06..dda082b 100644 --- a/client/src/functions/modes.rs +++ b/client/src/functions/modes.rs @@ -2,7 +2,8 @@ pub mod read_only; pub mod edit; - +pub mod navigation; pub use read_only::*; pub use edit::*; +pub use navigation::*; diff --git a/client/src/functions/modes/navigation.rs b/client/src/functions/modes/navigation.rs new file mode 100644 index 0000000..7b6121e --- /dev/null +++ b/client/src/functions/modes/navigation.rs @@ -0,0 +1,3 @@ +// src/functions/modes/navigation.rs + +pub mod admin_nav; diff --git a/client/src/functions/modes/navigation/admin_nav.rs b/client/src/functions/modes/navigation/admin_nav.rs new file mode 100644 index 0000000..adaa29d --- /dev/null +++ b/client/src/functions/modes/navigation/admin_nav.rs @@ -0,0 +1,36 @@ +// src/functions/modes/navigation/admin_nav.rs + +use crate::state::app::state::AppState; +use crate::state::pages::admin::AdminState; + +/// Handles moving the selection up in the admin profile list. +pub fn move_admin_list_up(app_state: &AppState, admin_state: &mut AdminState) { + // Read profile count directly from app_state where the source data lives + let profile_count = app_state.profile_tree.profiles.len(); + if profile_count == 0 { + admin_state.list_state.select(None); // Ensure nothing selected if empty + return; + } + + let current_index = admin_state.get_selected_index().unwrap_or(0); + let new_index = if current_index == 0 { + profile_count - 1 // Wrap to end + } else { + current_index.saturating_sub(1) // Move up + }; + admin_state.list_state.select(Some(new_index)); +} + +/// Handles moving the selection down in the admin profile list. +pub fn move_admin_list_down(app_state: &AppState, admin_state: &mut AdminState) { + // Read profile count directly from app_state + let profile_count = app_state.profile_tree.profiles.len(); + if profile_count == 0 { + admin_state.list_state.select(None); // Ensure nothing selected if empty + return; + } + + let current_index = admin_state.get_selected_index().unwrap_or(0); + let new_index = (current_index + 1) % profile_count; // Wrap around + admin_state.list_state.select(Some(new_index)); +} diff --git a/client/src/modes/general/navigation.rs b/client/src/modes/general/navigation.rs index 3f1afbb..d134241 100644 --- a/client/src/modes/general/navigation.rs +++ b/client/src/modes/general/navigation.rs @@ -6,9 +6,11 @@ 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::admin::AdminState; use crate::state::pages::canvas_state::CanvasState; use crate::ui::handlers::context::UiContext; use crate::modes::handlers::event::EventOutcome; +use crate::functions::modes::navigation::admin_nav; pub async fn handle_navigation_event( key: KeyEvent, @@ -17,6 +19,7 @@ pub async fn handle_navigation_event( app_state: &mut AppState, login_state: &mut LoginState, register_state: &mut RegisterState, + admin_state: &mut AdminState, command_mode: &mut bool, command_input: &mut String, command_message: &mut String, @@ -24,11 +27,11 @@ pub async fn handle_navigation_event( if let Some(action) = config.get_general_action(key.code, key.modifiers) { match action { "move_up" => { - move_up(app_state, login_state, register_state); + move_up(app_state, login_state, register_state, admin_state); return Ok(EventOutcome::Ok(String::new())); } "move_down" => { - move_down(app_state); + move_down(app_state, admin_state); return Ok(EventOutcome::Ok(String::new())); } "next_option" => { @@ -80,7 +83,7 @@ pub async fn handle_navigation_event( Ok(EventOutcome::Ok(String::new())) } -pub fn move_up(app_state: &mut AppState, login_state: &mut LoginState, register_state: &mut RegisterState) { +pub fn move_up(app_state: &mut AppState, login_state: &mut LoginState, register_state: &mut RegisterState, admin_state: &mut AdminState) { if app_state.ui.focus_outside_canvas && app_state.ui.show_login || app_state.ui.show_register{ if app_state.general.selected_item == 0 { app_state.ui.focus_outside_canvas = false; @@ -97,22 +100,11 @@ pub fn move_up(app_state: &mut AppState, login_state: &mut LoginState, register_ } else if app_state.ui.show_intro { app_state.ui.intro_state.previous_option(); } else if app_state.ui.show_admin { - // Assuming profile_tree.profiles is the list we're navigating - let profile_count = app_state.profile_tree.profiles.len(); - if profile_count == 0 { - return; - } - - // Use general state for tracking selection in admin panel - if app_state.general.selected_item == 0 { - app_state.general.selected_item = profile_count - 1; - } else { - app_state.general.selected_item = app_state.general.selected_item.saturating_sub(1); - } + admin_nav::move_admin_list_up(app_state, admin_state); } } -pub fn move_down(app_state: &mut AppState) { +pub fn move_down(app_state: &mut AppState, 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.general.selected_item < num_general_elements - 1 { @@ -127,7 +119,7 @@ pub fn move_down(app_state: &mut AppState) { return; } - app_state.general.selected_item = (app_state.general.selected_item + 1) % profile_count; + admin_nav::move_admin_list_down(app_state, admin_state); } } diff --git a/client/src/modes/handlers/event.rs b/client/src/modes/handlers/event.rs index 5f092de..81be572 100644 --- a/client/src/modes/handlers/event.rs +++ b/client/src/modes/handlers/event.rs @@ -10,6 +10,7 @@ use crate::state::pages::form::FormState; use crate::state::pages::auth::AuthState; use crate::state::pages::auth::LoginState; use crate::state::pages::auth::RegisterState; +use crate::state::pages::admin::AdminState; use crate::state::app::state::AppState; use crate::state::pages::canvas_state::CanvasState; use crate::ui::handlers::rat_state::UiStateHandler; @@ -69,6 +70,7 @@ impl EventHandler { auth_state: &mut AuthState, login_state: &mut LoginState, register_state: &mut RegisterState, + admin_state: &mut AdminState, app_state: &mut AppState, total_count: u64, current_position: &mut u64, @@ -107,6 +109,7 @@ impl EventHandler { app_state, login_state, register_state, + admin_state, &mut self.command_mode, &mut self.command_input, &mut self.command_message, @@ -134,8 +137,8 @@ impl EventHandler { }; } UiContext::Admin => { - // Assuming handle_admin_selection uses app_state.general.selected_item admin::handle_admin_selection(app_state); + message = format!("Admin Option {} selected", index); } UiContext::Dialog => { diff --git a/client/src/state/app/state.rs b/client/src/state/app/state.rs index a5af415..af66ae1 100644 --- a/client/src/state/app/state.rs +++ b/client/src/state/app/state.rs @@ -27,11 +27,6 @@ pub struct UiState { pub dialog: DialogState, } -pub struct GeneralState { - pub selected_item: usize, - pub current_option: usize, -} - pub struct AppState { // Core editor state pub current_dir: String, @@ -43,7 +38,6 @@ pub struct AppState { // UI preferences pub ui: UiState, - pub general: GeneralState, } impl AppState { @@ -59,10 +53,6 @@ impl AppState { selected_profile: None, current_mode: AppMode::General, ui: UiState::default(), - general: GeneralState { - selected_item: 0, - current_option: 0, - }, }) } diff --git a/client/src/state/pages.rs b/client/src/state/pages.rs index 2138407..9ac984b 100644 --- a/client/src/state/pages.rs +++ b/client/src/state/pages.rs @@ -2,4 +2,5 @@ pub mod form; pub mod auth; +pub mod admin; pub mod canvas_state; diff --git a/client/src/state/pages/admin.rs b/client/src/state/pages/admin.rs new file mode 100644 index 0000000..dc9e6c0 --- /dev/null +++ b/client/src/state/pages/admin.rs @@ -0,0 +1,38 @@ +// src/state/pages/admin.rs + +use ratatui::widgets::ListState; + +#[derive(Default, Clone, Debug)] +pub struct AdminState { + pub profiles: Vec, + pub list_state: ListState, +} + +impl AdminState { + /// Gets the index of the currently selected item. + pub fn get_selected_index(&self) -> Option { + self.list_state.selected() + } + + /// Gets the name of the currently selected profile. + pub fn get_selected_profile_name(&self) -> Option<&String> { + self.list_state.selected().and_then(|i| self.profiles.get(i)) + } + + /// Populates the profile list and updates/resets the selection. + pub fn set_profiles(&mut self, new_profiles: Vec) { + let current_selection_index = self.list_state.selected(); + self.profiles = new_profiles; + + if self.profiles.is_empty() { + self.list_state.select(None); + } else { + let new_selection = match current_selection_index { + Some(index) => Some(index.min(self.profiles.len() - 1)), + None => Some(0), + }; + self.list_state.select(new_selection); + } + } +} + diff --git a/client/src/ui/handlers/render.rs b/client/src/ui/handlers/render.rs index de31958..9ed99c5 100644 --- a/client/src/ui/handlers/render.rs +++ b/client/src/ui/handlers/render.rs @@ -17,6 +17,7 @@ use crate::state::pages::auth::AuthState; use crate::state::pages::auth::LoginState; use crate::state::pages::auth::RegisterState; use crate::state::app::state::AppState; +use crate::state::pages::admin::AdminState; pub fn render_ui( f: &mut Frame, @@ -77,10 +78,9 @@ pub fn render_ui( // Set the selected item - FIXED if !admin_state.profiles.is_empty() { - let selected_index = std::cmp::min( - app_state.general.selected_item, - admin_state.profiles.len() - 1 - ); + let selected_index = admin_state.get_selected_index() + .unwrap_or(0) + .min(admin_state.profiles.len() - 1); admin_state.list_state.select(Some(selected_index)); } diff --git a/client/src/ui/handlers/ui.rs b/client/src/ui/handlers/ui.rs index 3a50497..57faeb9 100644 --- a/client/src/ui/handlers/ui.rs +++ b/client/src/ui/handlers/ui.rs @@ -12,6 +12,7 @@ use crate::state::pages::form::FormState; use crate::state::pages::auth::AuthState; use crate::state::pages::auth::LoginState; use crate::state::pages::auth::RegisterState; +use crate::state::pages::admin::AdminState; use crate::state::app::state::AppState; // Import SaveOutcome use crate::tui::terminal::{EventReader, TerminalCore}; @@ -27,6 +28,7 @@ pub async fn run_ui() -> Result<(), Box> { let mut auth_state = AuthState::default(); let mut register_state = RegisterState::default(); let mut login_state = LoginState::default(); + let mut admin_state = AdminState::default(); // Initialize app_state first let mut app_state = AppState::new()?; @@ -118,6 +120,7 @@ pub async fn run_ui() -> Result<(), Box> { &mut auth_state, &mut login_state, &mut register_state, + &mut admin_state, &mut app_state, total_count, &mut current_position,