diff --git a/client/src/components/common/command_line.rs b/client/src/bottom_panel/command_line.rs similarity index 100% rename from client/src/components/common/command_line.rs rename to client/src/bottom_panel/command_line.rs diff --git a/client/src/bottom_panel/layout.rs b/client/src/bottom_panel/layout.rs new file mode 100644 index 0000000..d6137df --- /dev/null +++ b/client/src/bottom_panel/layout.rs @@ -0,0 +1,97 @@ +// src/bottom_panel/layout.rs + +use ratatui::{layout::Constraint, layout::Rect, Frame}; +use crate::bottom_panel::{status_line::render_status_line, command_line::render_command_line}; +use crate::components::common::find_file_palette; +use crate::config::colors::themes::Theme; +use crate::modes::general::command_navigation::NavigationState; +use crate::state::app::state::AppState; + +/// Calculate the layout constraints for the bottom panel (status line + command line/palette). +pub fn bottom_panel_constraints( + app_state: &AppState, + navigation_state: &NavigationState, + event_handler_command_mode_active: bool, +) -> Vec { + let mut status_line_height = 1; + #[cfg(feature = "ui-debug")] + { + if let Some(debug_state) = &app_state.debug_state { + if debug_state.is_error { + status_line_height = 4; + } + } + } + + const PALETTE_OPTIONS_HEIGHT_FOR_LAYOUT: u16 = 15; + let command_palette_area_height = if navigation_state.active { + 1 + PALETTE_OPTIONS_HEIGHT_FOR_LAYOUT + } else if event_handler_command_mode_active { + 1 + } else { + 0 + }; + + let mut constraints = vec![Constraint::Length(status_line_height)]; + if command_palette_area_height > 0 { + constraints.push(Constraint::Length(command_palette_area_height)); + } + constraints +} + +/// Render the bottom panel (status line + command line/palette). +pub fn render_bottom_panel( + f: &mut Frame, + root_chunks: &[Rect], + chunk_idx: &mut usize, + current_dir: &str, + theme: &Theme, + is_event_handler_edit_mode: bool, + current_fps: f64, + app_state: &AppState, + navigation_state: &NavigationState, + event_handler_command_input: &str, + event_handler_command_mode_active: bool, + event_handler_command_message: &str, +) { + // --- Status line area --- + let status_line_area = root_chunks[*chunk_idx]; + *chunk_idx += 1; + + // --- Command line / palette area --- + let command_render_area = if root_chunks.len() > *chunk_idx { + Some(root_chunks[*chunk_idx]) + } else { + None + }; + if command_render_area.is_some() { + *chunk_idx += 1; + } + + // --- Render status line --- + render_status_line( + f, + status_line_area, + current_dir, + theme, + is_event_handler_edit_mode, + current_fps, + app_state, + ); + + // --- Render command line or palette --- + if let Some(area) = command_render_area { + if navigation_state.active { + find_file_palette::render_find_file_palette(f, area, theme, navigation_state); + } else if event_handler_command_mode_active { + render_command_line( + f, + area, + event_handler_command_input, + true, + theme, + event_handler_command_message, + ); + } + } +} diff --git a/client/src/bottom_panel/mod.rs b/client/src/bottom_panel/mod.rs new file mode 100644 index 0000000..243c6e6 --- /dev/null +++ b/client/src/bottom_panel/mod.rs @@ -0,0 +1,5 @@ +// src/bottom_panel/mod.rs + +pub mod status_line; +pub mod command_line; +pub mod layout; diff --git a/client/src/components/common/status_line.rs b/client/src/bottom_panel/status_line.rs similarity index 98% rename from client/src/components/common/status_line.rs rename to client/src/bottom_panel/status_line.rs index 499f9cf..cfef77f 100644 --- a/client/src/components/common/status_line.rs +++ b/client/src/bottom_panel/status_line.rs @@ -4,8 +4,8 @@ use crate::state::app::state::AppState; use ratatui::{ layout::Rect, style::Style, - text::{Line, Span}, - widgets::Paragraph, + text::{Line, Span, Text}, + widgets::{Paragraph, Wrap}, Frame, }; use std::path::Path; diff --git a/client/src/components/common.rs b/client/src/components/common.rs index 57a242a..0f14849 100644 --- a/client/src/components/common.rs +++ b/client/src/components/common.rs @@ -1,14 +1,11 @@ // src/components/common.rs -pub mod command_line; -pub mod status_line; + pub mod text_editor; pub mod background; pub mod dialog; pub mod autocomplete; pub mod find_file_palette; -pub use command_line::*; -pub use status_line::*; pub use text_editor::*; pub use background::*; pub use dialog::*; diff --git a/client/src/lib.rs b/client/src/lib.rs index 684343d..729fcb6 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -11,6 +11,7 @@ pub mod utils; pub mod buffer; pub mod sidebar; pub mod search; +pub mod bottom_panel; pub use ui::run_ui; diff --git a/client/src/ui/handlers/render.rs b/client/src/ui/handlers/render.rs index 625a34e..5cd381a 100644 --- a/client/src/ui/handlers/render.rs +++ b/client/src/ui/handlers/render.rs @@ -8,9 +8,8 @@ use crate::components::{ common::find_file_palette, intro::intro::render_intro, render_background, - render_command_line, - render_status_line, }; +use crate::bottom_panel::{command_line::render_command_line, status_line::render_status_line}; use crate::sidebar::{calculate_sidebar_layout, render_sidebar}; use crate::buffer::render_buffer_list; use crate::search::render_search_palette; @@ -24,6 +23,7 @@ use crate::state::pages::auth::LoginState; use crate::state::pages::auth::RegisterState; use crate::state::pages::form::FormState; use crate::state::pages::intro::IntroState; +use crate::bottom_panel::layout::{bottom_panel_constraints, render_bottom_panel}; use crate::components::render_form; use ratatui::{ layout::{Constraint, Direction, Layout}, @@ -52,38 +52,15 @@ pub fn render_ui( ) { render_background(f, f.area(), theme); - // --- START DYNAMIC LAYOUT LOGIC --- - let status_line_height = 1; - #[cfg(feature = "ui-debug")] - { - if let Some(debug_state) = &app_state.debug_state { - if debug_state.is_error { - status_line_height = 4; - } - } - } - // --- END DYNAMIC LAYOUT LOGIC --- - - const PALETTE_OPTIONS_HEIGHT_FOR_LAYOUT: u16 = 15; - - let mut bottom_area_constraints: Vec = vec![Constraint::Length(status_line_height)]; - let command_palette_area_height = if navigation_state.active { - 1 + PALETTE_OPTIONS_HEIGHT_FOR_LAYOUT - } else if event_handler_command_mode_active { - 1 - } else { - 0 - }; - - if command_palette_area_height > 0 { - bottom_area_constraints.push(Constraint::Length(command_palette_area_height)); - } - let mut main_layout_constraints = vec![Constraint::Min(1)]; if app_state.ui.show_buffer_list { main_layout_constraints.insert(0, Constraint::Length(1)); } - main_layout_constraints.extend(bottom_area_constraints); + main_layout_constraints.extend(bottom_panel_constraints( + app_state, + navigation_state, + event_handler_command_mode_active, + )); let root_chunks = Layout::default() .direction(Direction::Vertical) @@ -102,19 +79,6 @@ pub fn render_ui( let main_content_area = root_chunks[chunk_idx]; chunk_idx += 1; - let status_line_area = root_chunks[chunk_idx]; - chunk_idx += 1; - - let command_render_area = if command_palette_area_height > 0 { - if root_chunks.len() > chunk_idx { - Some(root_chunks[chunk_idx]) - } else { - None - } - } else { - None - }; - if app_state.ui.show_intro { render_intro(f, intro_state, main_content_area, theme); } else if app_state.ui.show_register { @@ -209,36 +173,6 @@ 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, - app_state, - ); - - if let Some(palette_or_command_area) = command_render_area { - if navigation_state.active { - find_file_palette::render_find_file_palette( - f, - palette_or_command_area, - theme, - navigation_state, - ); - } else if event_handler_command_mode_active { - render_command_line( - f, - palette_or_command_area, - event_handler_command_input, - true, - theme, - event_handler_command_message, - ); - } - } - // This block now correctly handles drawing popups over any view. if app_state.ui.show_search_palette { if let Some(search_state) = &app_state.search_state { @@ -256,4 +190,19 @@ pub fn render_ui( app_state.ui.dialog.is_loading, ); } + + render_bottom_panel( + f, + &root_chunks, + &mut chunk_idx, + current_dir, + theme, + is_event_handler_edit_mode, + current_fps, + app_state, + navigation_state, + event_handler_command_input, + event_handler_command_mode_active, + event_handler_command_message, + ); } diff --git a/client/src/ui/handlers/ui.rs b/client/src/ui/handlers/ui.rs index 2f8e39a..8300cb5 100644 --- a/client/src/ui/handlers/ui.rs +++ b/client/src/ui/handlers/ui.rs @@ -33,6 +33,7 @@ use crossterm::event as crossterm_event; use tracing::{error, info, warn}; use tokio::sync::mpsc; use std::time::Instant; +use std::time::Duration; #[cfg(feature = "ui-debug")] use crate::state::app::state::DebugState; #[cfg(feature = "ui-debug")]