// src/state/state.rs use std::env; use common::proto::multieko2::table_definition::ProfileTreeResponse; use crate::modes::handlers::mode_manager::AppMode; use crate::ui::handlers::context::DialogPurpose; use anyhow::{Context, Result}; pub struct DialogState { pub dialog_show: bool, pub dialog_title: String, pub dialog_message: String, pub dialog_buttons: Vec, pub dialog_active_button_index: usize, pub purpose: Option, pub is_loading: bool, } pub struct UiState { pub show_sidebar: bool, pub show_buffer_list: bool, pub show_intro: bool, pub show_admin: bool, pub show_add_table: bool, pub show_form: bool, pub show_login: bool, pub show_register: bool, pub focus_outside_canvas: bool, pub dialog: DialogState, } pub struct AppState { // Core editor state pub current_dir: String, pub total_count: u64, pub current_position: u64, pub profile_tree: ProfileTreeResponse, pub selected_profile: Option, pub current_mode: AppMode, pub focused_button_index: usize, // UI preferences pub ui: UiState, } impl AppState { pub fn new() -> Result { let current_dir = env::current_dir()? .to_string_lossy() .to_string(); Ok(AppState { current_dir, total_count: 0, current_position: 0, profile_tree: ProfileTreeResponse::default(), selected_profile: None, current_mode: AppMode::General, focused_button_index: 0, ui: UiState::default(), }) } // Existing methods remain unchanged pub fn update_total_count(&mut self, total_count: u64) { self.total_count = total_count; } pub fn update_current_position(&mut self, current_position: u64) { self.current_position = current_position; } pub fn update_mode(&mut self, mode: AppMode) { self.current_mode = mode; } // Add dialog helper methods /// Shows a dialog with the given title, message, and buttons. /// The first button (index 0) is active by default. pub fn show_dialog( &mut self, title: &str, message: &str, buttons: Vec, purpose: DialogPurpose, ) { self.ui.dialog.dialog_title = title.to_string(); self.ui.dialog.dialog_message = message.to_string(); self.ui.dialog.dialog_buttons = buttons; self.ui.dialog.dialog_active_button_index = 0; self.ui.dialog.purpose = Some(purpose); self.ui.dialog.is_loading = false; self.ui.dialog.dialog_show = true; self.ui.focus_outside_canvas = true; } /// Shows a dialog specifically for loading states. pub fn show_loading_dialog(&mut self, title: &str, message: &str) { self.ui.dialog.dialog_title = title.to_string(); self.ui.dialog.dialog_message = message.to_string(); self.ui.dialog.dialog_buttons.clear(); // No buttons during loading self.ui.dialog.dialog_active_button_index = 0; self.ui.dialog.purpose = None; // Purpose is set when loading finishes self.ui.dialog.is_loading = true; self.ui.dialog.dialog_show = true; self.ui.focus_outside_canvas = true; // Keep focus management consistent } /// Updates the content of an existing dialog, typically after loading. pub fn update_dialog_content( &mut self, message: &str, buttons: Vec, purpose: DialogPurpose, ) { if self.ui.dialog.dialog_show { self.ui.dialog.dialog_message = message.to_string(); self.ui.dialog.dialog_buttons = buttons; self.ui.dialog.dialog_active_button_index = 0; // Reset focus self.ui.dialog.purpose = Some(purpose); self.ui.dialog.is_loading = false; // Loading finished // Keep dialog_show = true // Keep focus_outside_canvas = true } } /// Hides the dialog and clears its content. pub fn hide_dialog(&mut self) { self.ui.dialog.dialog_show = false; self.ui.dialog.dialog_title.clear(); self.ui.dialog.dialog_message.clear(); self.ui.dialog.dialog_buttons.clear(); self.ui.dialog.dialog_active_button_index = 0; self.ui.dialog.purpose = None; self.ui.focus_outside_canvas = false; } /// Sets the active button index, wrapping around if necessary. pub fn next_dialog_button(&mut self) { if !self.ui.dialog.dialog_buttons.is_empty() { let next_index = (self.ui.dialog.dialog_active_button_index + 1) % self.ui.dialog.dialog_buttons.len(); self.ui.dialog.dialog_active_button_index = next_index; // Use new name } } /// Sets the active button index, wrapping around if necessary. pub fn previous_dialog_button(&mut self) { if !self.ui.dialog.dialog_buttons.is_empty() { let len = self.ui.dialog.dialog_buttons.len(); let prev_index = (self.ui.dialog.dialog_active_button_index + len - 1) % len; self.ui.dialog.dialog_active_button_index = prev_index; // Use new name } } /// Gets the label of the currently active button, if any. pub fn get_active_dialog_button_label(&self) -> Option<&str> { self.ui.dialog .dialog_buttons // Use new name .get(self.ui.dialog.dialog_active_button_index) // Use new name .map(|s| s.as_str()) } } impl Default for UiState { fn default() -> Self { Self { show_sidebar: false, show_intro: true, show_admin: false, show_add_table: false, show_form: false, show_login: false, show_register: false, show_buffer_list: true, focus_outside_canvas: false, dialog: DialogState::default(), } } } // Update the Default implementation for DialogState itself impl Default for DialogState { fn default() -> Self { Self { dialog_show: false, dialog_title: String::new(), dialog_message: String::new(), dialog_buttons: Vec::new(), dialog_active_button_index: 0, purpose: None, is_loading: false, } } }