diff --git a/client/Cargo.toml b/client/Cargo.toml index af2a07b..223f580 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -26,3 +26,7 @@ tracing-subscriber = "0.3.19" tui-textarea = { version = "0.7.0", features = ["crossterm", "ratatui", "search"] } unicode-segmentation = "1.12.0" unicode-width = "0.2.0" + +[features] +default = [] +ui-debug = [] diff --git a/client/src/components/common/status_line.rs b/client/src/components/common/status_line.rs index 91ee799..8bc67ce 100644 --- a/client/src/components/common/status_line.rs +++ b/client/src/components/common/status_line.rs @@ -1,14 +1,15 @@ // src/components/common/status_line.rs +use crate::config::colors::themes::Theme; +use crate::state::app::state::AppState; use ratatui::{ - style::Style, layout::Rect, - Frame, + style::Style, text::{Line, Span}, widgets::Paragraph, + Frame, }; -use unicode_width::UnicodeWidthStr; -use crate::config::colors::themes::Theme; use std::path::Path; +use unicode_width::UnicodeWidthStr; pub fn render_status_line( f: &mut Frame, @@ -17,11 +18,24 @@ pub fn render_status_line( theme: &Theme, is_edit_mode: bool, current_fps: f64, + app_state: &AppState, ) { + // --- START FIX --- + // Ensure debug_text is always a &str, which implements UnicodeWidthStr. + #[cfg(feature = "ui-debug")] + let debug_text = app_state.debug_info.as_str(); + #[cfg(not(feature = "ui-debug"))] + let debug_text = ""; + // --- END FIX --- + + let debug_width = UnicodeWidthStr::width(debug_text); + let debug_separator_width = if !debug_text.is_empty() { UnicodeWidthStr::width(" | ") } else { 0 }; + let program_info = format!("multieko2 v{}", env!("CARGO_PKG_VERSION")); let mode_text = if is_edit_mode { "[EDIT]" } else { "[READ-ONLY]" }; - let home_dir = dirs::home_dir().map(|p| p.to_string_lossy().into_owned()).unwrap_or_default(); + let home_dir = + dirs::home_dir().map(|p| p.to_string_lossy().into_owned()).unwrap_or_default(); let display_dir = if current_dir.starts_with(&home_dir) { current_dir.replacen(&home_dir, "~", 1) } else { @@ -37,23 +51,24 @@ pub fn render_status_line( let separator_width = UnicodeWidthStr::width(separator); let fixed_width_with_fps = mode_width + separator_width + separator_width + - program_info_width + separator_width + fps_width; - let show_fps = fixed_width_with_fps <= available_width; // Use <= to show if it fits exactly + program_info_width + separator_width + fps_width + + debug_separator_width + debug_width; + let show_fps = fixed_width_with_fps <= available_width; let remaining_width_for_dir = available_width.saturating_sub( - mode_width + separator_width + // after mode - separator_width + program_info_width + // after program_info - if show_fps { separator_width + fps_width } else { 0 } // after fps + mode_width + separator_width + + separator_width + program_info_width + + (if show_fps { separator_width + fps_width } else { 0 }) + + debug_separator_width + debug_width, ); - // Original directory display logic let dir_display_text_str = if UnicodeWidthStr::width(display_dir.as_str()) <= remaining_width_for_dir { - display_dir // display_dir is already a String here + display_dir } else { - let dir_name = Path::new(current_dir) // Use original current_dir for path logic + let dir_name = Path::new(current_dir) .file_name() .and_then(|n| n.to_str()) - .unwrap_or(current_dir); // Fallback to current_dir if no filename + .unwrap_or(current_dir); if UnicodeWidthStr::width(dir_name) <= remaining_width_for_dir { dir_name.to_string() } else { @@ -61,10 +76,10 @@ pub fn render_status_line( } }; - // Calculate current content width based on what will be displayed let mut current_content_width = mode_width + separator_width + UnicodeWidthStr::width(dir_display_text_str.as_str()) + - separator_width + program_info_width; + separator_width + program_info_width + + debug_separator_width + debug_width; if show_fps { current_content_width += separator_width + fps_width; } @@ -82,12 +97,17 @@ pub fn render_status_line( line_spans.push(Span::styled(fps_text.as_str(), Style::default().fg(theme.secondary))); } - // Calculate padding + #[cfg(feature = "ui-debug")] + { + line_spans.push(Span::styled(separator, Style::default().fg(theme.border))); + line_spans.push(Span::styled(debug_text, Style::default().fg(theme.accent))); + } + let padding_needed = available_width.saturating_sub(current_content_width); if padding_needed > 0 { line_spans.push(Span::styled( " ".repeat(padding_needed), - Style::default().bg(theme.bg), // Ensure padding uses background color + Style::default().bg(theme.bg), )); } diff --git a/client/src/state/app/state.rs b/client/src/state/app/state.rs index 936ebaa..d727626 100644 --- a/client/src/state/app/state.rs +++ b/client/src/state/app/state.rs @@ -44,6 +44,9 @@ pub struct AppState { // UI preferences pub ui: UiState, + + #[cfg(feature = "ui-debug")] + pub debug_info: String, } impl AppState { @@ -61,6 +64,9 @@ impl AppState { focused_button_index: 0, pending_table_structure_fetch: None, ui: UiState::default(), + + #[cfg(feature = "ui-debug")] + debug_info: String::new(), }) } diff --git a/client/src/ui/handlers/render.rs b/client/src/ui/handlers/render.rs index 0a67ed3..7f84db9 100644 --- a/client/src/ui/handlers/render.rs +++ b/client/src/ui/handlers/render.rs @@ -183,7 +183,15 @@ pub fn render_ui( render_buffer_list(f, area, theme, buffer_state, app_state); } - render_status_line(f, status_line_area, current_dir, theme, is_event_handler_edit_mode, current_fps); + render_status_line( + f, + status_line_area, + current_dir, + theme, + is_event_handler_edit_mode, + current_fps, + app_state, + ); if let Some(palette_or_command_area) = command_render_area { // Use the calculated area if navigation_state.active { diff --git a/client/src/ui/handlers/ui.rs b/client/src/ui/handlers/ui.rs index f3993af..827ded4 100644 --- a/client/src/ui/handlers/ui.rs +++ b/client/src/ui/handlers/ui.rs @@ -497,6 +497,14 @@ pub async fn run_ui() -> Result<()> { needs_redraw = true; } + #[cfg(feature = "ui-debug")] + { + app_state.debug_info = format!( + "Redraw -> event: {}, needs_redraw: {}, pos_changed: {}", + event_processed, needs_redraw, position_changed + ); + } + if event_processed || needs_redraw || position_changed { let current_mode = ModeManager::derive_mode(&app_state, &event_handler, &admin_state); match current_mode {