diff --git a/client/config.toml b/client/config.toml index a0230a7..6900154 100644 --- a/client/config.toml +++ b/client/config.toml @@ -10,6 +10,7 @@ next_option = ["l", "Right"] previous_option = ["h", "Left"] select = ["Enter"] toggle_sidebar = ["ctrl+t"] +toggle_buffer_list = ["ctrl+b"] next_field = ["Tab"] prev_field = ["Shift+Tab"] @@ -24,6 +25,7 @@ save_and_quit = ["ctrl+shift+s"] move_up = ["Up"] move_down = ["Down"] toggle_sidebar = ["ctrl+t"] +toggle_buffer_list = ["ctrl+b"] # MODE SPECIFIC # READ ONLY MODE diff --git a/client/src/components/common.rs b/client/src/components/common.rs index ea30d5f..7ea69dd 100644 --- a/client/src/components/common.rs +++ b/client/src/components/common.rs @@ -1,12 +1,14 @@ // src/components/common.rs pub mod command_line; pub mod status_line; +pub mod buffer_list; pub mod background; pub mod dialog; pub mod autocomplete; pub use command_line::*; pub use status_line::*; +pub use buffer_list::*; pub use background::*; pub use dialog::*; pub use autocomplete::*; diff --git a/client/src/components/common/buffer_list.rs b/client/src/components/common/buffer_list.rs new file mode 100644 index 0000000..716f4ce --- /dev/null +++ b/client/src/components/common/buffer_list.rs @@ -0,0 +1,53 @@ +// src/components/common/buffer_list.rs + +use crate::config::colors::themes::Theme; +use crate::state::app::state::AppState; +use ratatui::{ + layout::Rect, + style::{Style, Stylize}, + text::Line, + widgets::{Block, Borders, List, ListItem, ListState}, + Frame, +}; + +pub fn render_buffer_list( + f: &mut Frame, + area: Rect, + theme: &Theme, + app_state: &AppState, +) { + let mut items = Vec::new(); + let mut current_buffer_name = "*scratch*"; // Default if nothing else is shown + + // Determine the active buffer name based on UI state + if app_state.ui.show_intro { + current_buffer_name = "Intro"; + } else if app_state.ui.show_register { + current_buffer_name = "Register"; + } else if app_state.ui.show_login { + current_buffer_name = "Login"; + } else if app_state.ui.show_admin { + current_buffer_name = "Admin Panel"; + } else if app_state.ui.show_form { + current_buffer_name = "Data Form"; // Or derive from selected profile/table if needed + } + + items.push(ListItem::new(Line::from(vec![ + " ".into(), // Padding + current_buffer_name.fg(theme.highlight), + " ".into(), // Padding + ]))); + + let list = List::new(items) + .block( + Block::default() + .borders(Borders::TOP) // Simple top border + .border_style(Style::default().fg(theme.secondary)), + ) + .style(Style::default().bg(theme.bg).fg(theme.fg)); + + let mut state = ListState::default(); + + f.render_stateful_widget(list, area, &mut state); +} + diff --git a/client/src/modes/general/navigation.rs b/client/src/modes/general/navigation.rs index e956e4e..a04979a 100644 --- a/client/src/modes/general/navigation.rs +++ b/client/src/modes/general/navigation.rs @@ -43,12 +43,6 @@ pub async fn handle_navigation_event( previous_option(app_state, intro_state); return Ok(EventOutcome::Ok(String::new())); } - "toggle_sidebar" => { - toggle_sidebar(app_state); - return Ok(EventOutcome::Ok(format!("Sidebar {}", - if app_state.ui.show_sidebar { "shown" } else { "hidden" } - ))); - } "next_field" => { next_field(form_state); return Ok(EventOutcome::Ok(String::new())); @@ -140,10 +134,6 @@ pub fn previous_option(app_state: &mut AppState, intro_state: &mut IntroState) { } } -pub fn toggle_sidebar(app_state: &mut AppState) { - app_state.ui.show_sidebar = !app_state.ui.show_sidebar; -} - 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(); diff --git a/client/src/modes/handlers/event.rs b/client/src/modes/handlers/event.rs index 3779e58..1623008 100644 --- a/client/src/modes/handlers/event.rs +++ b/client/src/modes/handlers/event.rs @@ -101,6 +101,13 @@ impl EventHandler { ); return Ok(EventOutcome::Ok(message)); } + if UiStateHandler::toggle_buffer_list(&mut app_state.ui, config, key_code, modifiers) { + let message = format!("Buffer {}", + if app_state.ui.show_buffer_list { "shown" } else { "hidden" } + ); + return Ok(EventOutcome::Ok(message)); + } + // --- End Global UI Toggles --- match current_mode { AppMode::General => { diff --git a/client/src/state/app/state.rs b/client/src/state/app/state.rs index c83e045..38b7e7c 100644 --- a/client/src/state/app/state.rs +++ b/client/src/state/app/state.rs @@ -16,6 +16,7 @@ pub struct DialogState { pub struct UiState { pub show_sidebar: bool, + pub show_buffer_list: bool, pub show_intro: bool, pub show_admin: bool, pub show_form: bool, @@ -136,6 +137,7 @@ impl Default for UiState { show_form: false, show_login: false, show_register: false, + show_buffer_list: false, focus_outside_canvas: false, dialog: DialogState::default(), } diff --git a/client/src/ui/handlers/rat_state.rs b/client/src/ui/handlers/rat_state.rs index e969f73..4b35408 100644 --- a/client/src/ui/handlers/rat_state.rs +++ b/client/src/ui/handlers/rat_state.rs @@ -21,4 +21,18 @@ impl UiStateHandler { false } + pub fn toggle_buffer_list( + ui_state: &mut UiState, + config: &Config, + key: KeyCode, + modifiers: KeyModifiers, + ) -> bool { + if let Some(action) = config.get_common_action(key, modifiers) { + if action == "toggle_buffer_list" { + ui_state.show_buffer_list = !ui_state.show_buffer_list; + return true; + } + } + false + } } diff --git a/client/src/ui/handlers/render.rs b/client/src/ui/handlers/render.rs index cc1f8ca..20c81ea 100644 --- a/client/src/ui/handlers/render.rs +++ b/client/src/ui/handlers/render.rs @@ -2,6 +2,7 @@ use crate::components::{ render_background, + render_buffer_list, render_command_line, render_status_line, intro::intro::render_intro, @@ -40,16 +41,42 @@ pub fn render_ui( ) { render_background(f, f.area(), theme); + // Adjust layout based on whether buffer list is shown + let constraints = if app_state.ui.show_buffer_list { + vec![ + Constraint::Min(1), // Main content + Constraint::Length(1), // Buffer list + Constraint::Length(1), // Status line + Constraint::Length(1), // Command line + ] + } else { + vec![ + Constraint::Min(1), // Main content + Constraint::Length(1), // Status line (no buffer list) + Constraint::Length(1), // Command line + ] + }; + let root = Layout::default() .direction(Direction::Vertical) - .constraints([ - Constraint::Min(1), - Constraint::Length(1), - Constraint::Length(1), - ]) + .constraints(constraints) .split(f.area()); let main_content_area = root[0]; + let mut buffer_list_area = None; + let status_line_area; + let command_line_area; + + // Assign areas based on layout + if app_state.ui.show_buffer_list { + buffer_list_area = Some(root[1]); + status_line_area = root[2]; + command_line_area = root[3]; + } else { + status_line_area = root[1]; + command_line_area = root[2]; + } + if app_state.ui.show_intro { render_intro(f, intro_state, main_content_area, theme); } else if app_state.ui.show_register { @@ -61,17 +88,17 @@ pub fn render_ui( app_state, register_state.current_field < 4 ); - }else if app_state.ui.show_login { + } else if app_state.ui.show_login { render_login( - f, - main_content_area, - theme, + f, + main_content_area, + theme, login_state, app_state, login_state.current_field < 2 ); } else if app_state.ui.show_admin { - crate::components::admin::admin_panel::render_admin_panel( + crate::components::admin::admin_panel::render_admin_panel( f, auth_state, admin_state, @@ -136,10 +163,14 @@ pub fn render_ui( total_count, current_position, ); - } else{ - } - render_status_line(f, root[1], current_dir, theme, is_edit_mode); - render_command_line(f, root[2], command_input, command_mode, theme, command_message); + // Render buffer list if enabled and area is available + if let Some(area) = buffer_list_area { + if app_state.ui.show_buffer_list { + render_buffer_list(f, area, theme, app_state); + } + } + render_status_line(f, status_line_area, current_dir, theme, is_edit_mode); + render_command_line(f, command_line_area, command_input, command_mode, theme, command_message); }