compiled and working sidebar in ratatui
This commit is contained in:
@@ -11,6 +11,7 @@ force_quit = ["ctrl+shift+q"]
|
|||||||
save_and_quit = ["ctrl+shift+s"]
|
save_and_quit = ["ctrl+shift+s"]
|
||||||
move_up = ["Up"]
|
move_up = ["Up"]
|
||||||
move_down = ["Down"]
|
move_down = ["Down"]
|
||||||
|
toggle_sidebar = ["ctrl+t"]
|
||||||
|
|
||||||
# MODE SPECIFIC
|
# MODE SPECIFIC
|
||||||
# READ ONLY MODE
|
# READ ONLY MODE
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ pub mod preview_card;
|
|||||||
pub mod command_line;
|
pub mod command_line;
|
||||||
pub mod status_line;
|
pub mod status_line;
|
||||||
pub mod canvas;
|
pub mod canvas;
|
||||||
|
pub mod sidebar;
|
||||||
|
|
||||||
pub use command_line::render_command_line;
|
pub use command_line::render_command_line;
|
||||||
pub use form::*;
|
pub use form::*;
|
||||||
pub use preview_card::render_preview_card;
|
pub use preview_card::render_preview_card;
|
||||||
pub use status_line::render_status_line;
|
pub use status_line::render_status_line;
|
||||||
pub use canvas::*;
|
pub use canvas::*;
|
||||||
|
pub use sidebar::*;
|
||||||
|
|||||||
29
client/src/components/handlers/sidebar.rs
Normal file
29
client/src/components/handlers/sidebar.rs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// src/components/handlers/sidebar.rs
|
||||||
|
use ratatui::{
|
||||||
|
widgets::{Block, Borders, List, ListItem},
|
||||||
|
layout::Rect,
|
||||||
|
style::Style,
|
||||||
|
text::Text,
|
||||||
|
Frame,
|
||||||
|
};
|
||||||
|
use crate::config::colors::Theme;
|
||||||
|
|
||||||
|
pub fn render_sidebar(f: &mut Frame, area: Rect, theme: &Theme) {
|
||||||
|
let sidebar_block = Block::default()
|
||||||
|
.borders(Borders::RIGHT)
|
||||||
|
.border_style(Style::default().fg(theme.border))
|
||||||
|
.style(Style::default().bg(theme.bg));
|
||||||
|
|
||||||
|
let items = vec![
|
||||||
|
ListItem::new(Text::from(" Navigation ")),
|
||||||
|
ListItem::new(Text::from(" Search ")),
|
||||||
|
ListItem::new(Text::from(" Settings ")),
|
||||||
|
];
|
||||||
|
|
||||||
|
let list = List::new(items)
|
||||||
|
.block(sidebar_block)
|
||||||
|
.highlight_style(Style::default().fg(theme.highlight))
|
||||||
|
.highlight_symbol(">>");
|
||||||
|
|
||||||
|
f.render_widget(list, area);
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
// src/modes/handlers/event.rs
|
// src/modes/handlers/event.rs
|
||||||
|
|
||||||
use crossterm::event::Event;
|
use crossterm::event::{Event, KeyCode, KeyModifiers};
|
||||||
use crossterm::cursor::SetCursorStyle;
|
use crossterm::cursor::SetCursorStyle;
|
||||||
use crate::tui::terminal::{
|
use crate::tui::terminal::{
|
||||||
core::TerminalCore,
|
core::TerminalCore,
|
||||||
@@ -9,6 +9,8 @@ use crate::tui::terminal::{
|
|||||||
};
|
};
|
||||||
use crate::config::config::Config;
|
use crate::config::config::Config;
|
||||||
use crate::ui::handlers::form::FormState;
|
use crate::ui::handlers::form::FormState;
|
||||||
|
use crate::ui::handlers::rat_state::UiStateHandler;
|
||||||
|
use crate::state::state::AppState;
|
||||||
use crate::modes::handlers::{edit, command_mode, read_only};
|
use crate::modes::handlers::{edit, command_mode, read_only};
|
||||||
use crate::config::key_sequences::KeySequenceTracker;
|
use crate::config::key_sequences::KeySequenceTracker;
|
||||||
use super::common;
|
use super::common;
|
||||||
@@ -44,22 +46,36 @@ impl EventHandler {
|
|||||||
grpc_client: &mut GrpcClient,
|
grpc_client: &mut GrpcClient,
|
||||||
command_handler: &mut CommandHandler,
|
command_handler: &mut CommandHandler,
|
||||||
form_state: &mut FormState,
|
form_state: &mut FormState,
|
||||||
is_saved: &mut bool,
|
app_state: &mut crate::state::state::AppState,
|
||||||
total_count: u64,
|
total_count: u64,
|
||||||
current_position: &mut u64,
|
current_position: &mut u64,
|
||||||
) -> Result<(bool, String), Box<dyn std::error::Error>> {
|
) -> Result<(bool, String), Box<dyn std::error::Error>> {
|
||||||
if let Event::Key(key) = event {
|
if let Event::Key(key) = event {
|
||||||
|
let key_code = key.code;
|
||||||
|
let modifiers = key.modifiers;
|
||||||
|
|
||||||
|
if UiStateHandler::toggle_sidebar(
|
||||||
|
&mut app_state.ui,
|
||||||
|
config,
|
||||||
|
key_code,
|
||||||
|
modifiers,
|
||||||
|
) {
|
||||||
|
return Ok((false, format!("Sidebar {}",
|
||||||
|
if app_state.ui.show_sidebar { "shown" } else { "hidden" }
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(action) = config.get_action_for_key_in_mode(
|
if let Some(action) = config.get_action_for_key_in_mode(
|
||||||
&config.keybindings.common,
|
&config.keybindings.common,
|
||||||
key.code,
|
key_code,
|
||||||
key.modifiers
|
modifiers
|
||||||
) {
|
) {
|
||||||
match action {
|
match action {
|
||||||
"save" => {
|
"save" => {
|
||||||
let message = common::save(
|
let message = common::save(
|
||||||
form_state,
|
form_state,
|
||||||
grpc_client,
|
grpc_client,
|
||||||
is_saved,
|
&mut app_state.is_saved,
|
||||||
current_position,
|
current_position,
|
||||||
total_count,
|
total_count,
|
||||||
).await?;
|
).await?;
|
||||||
@@ -94,7 +110,7 @@ impl EventHandler {
|
|||||||
&mut self.command_input,
|
&mut self.command_input,
|
||||||
&mut self.command_message,
|
&mut self.command_message,
|
||||||
grpc_client,
|
grpc_client,
|
||||||
is_saved,
|
&mut app_state.is_saved,
|
||||||
current_position,
|
current_position,
|
||||||
total_count,
|
total_count,
|
||||||
).await?;
|
).await?;
|
||||||
@@ -107,7 +123,7 @@ impl EventHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.is_edit_mode {
|
if self.is_edit_mode {
|
||||||
if config.is_exit_edit_mode(key.code, key.modifiers) {
|
if config.is_exit_edit_mode(key_code, modifiers) {
|
||||||
if form_state.has_unsaved_changes {
|
if form_state.has_unsaved_changes {
|
||||||
self.command_message = "Unsaved changes! Use :w to save or :q! to discard".to_string();
|
self.command_message = "Unsaved changes! Use :w to save or :q! to discard".to_string();
|
||||||
return Ok((false, self.command_message.clone()));
|
return Ok((false, self.command_message.clone()));
|
||||||
@@ -131,7 +147,7 @@ impl EventHandler {
|
|||||||
form_state,
|
form_state,
|
||||||
&mut self.ideal_cursor_column,
|
&mut self.ideal_cursor_column,
|
||||||
&mut self.command_message,
|
&mut self.command_message,
|
||||||
is_saved,
|
&mut app_state.is_saved,
|
||||||
current_position,
|
current_position,
|
||||||
total_count,
|
total_count,
|
||||||
grpc_client,
|
grpc_client,
|
||||||
@@ -140,7 +156,7 @@ impl EventHandler {
|
|||||||
self.key_sequence_tracker.reset();
|
self.key_sequence_tracker.reset();
|
||||||
return Ok((false, result));
|
return Ok((false, result));
|
||||||
} else {
|
} else {
|
||||||
if let Some(action) = config.get_read_only_action_for_key(key.code, key.modifiers) {
|
if let Some(action) = config.get_read_only_action_for_key(key_code, modifiers) {
|
||||||
if action == "enter_command_mode" {
|
if action == "enter_command_mode" {
|
||||||
self.command_mode = true;
|
self.command_mode = true;
|
||||||
self.command_input.clear();
|
self.command_input.clear();
|
||||||
@@ -149,7 +165,7 @@ impl EventHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.is_enter_edit_mode_before(key.code, key.modifiers) {
|
if config.is_enter_edit_mode_before(key_code, modifiers) {
|
||||||
self.is_edit_mode = true;
|
self.is_edit_mode = true;
|
||||||
self.edit_mode_cooldown = true;
|
self.edit_mode_cooldown = true;
|
||||||
self.command_message = "Edit mode".to_string();
|
self.command_message = "Edit mode".to_string();
|
||||||
@@ -157,7 +173,7 @@ impl EventHandler {
|
|||||||
return Ok((false, self.command_message.clone()));
|
return Ok((false, self.command_message.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.is_enter_edit_mode_after(key.code, key.modifiers) {
|
if config.is_enter_edit_mode_after(key_code, modifiers) {
|
||||||
let current_input = form_state.get_current_input();
|
let current_input = form_state.get_current_input();
|
||||||
if !current_input.is_empty() && form_state.current_cursor_pos < current_input.len() {
|
if !current_input.is_empty() && form_state.current_cursor_pos < current_input.len() {
|
||||||
form_state.current_cursor_pos += 1;
|
form_state.current_cursor_pos += 1;
|
||||||
|
|||||||
@@ -2,11 +2,21 @@
|
|||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct UiState {
|
||||||
|
pub show_sidebar: bool,
|
||||||
|
// Add other UI-related states here
|
||||||
|
}
|
||||||
|
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
|
// Core editor state
|
||||||
pub is_saved: bool,
|
pub is_saved: bool,
|
||||||
pub current_dir: String,
|
pub current_dir: String,
|
||||||
pub total_count: u64,
|
pub total_count: u64,
|
||||||
pub current_position: u64,
|
pub current_position: u64,
|
||||||
|
|
||||||
|
// UI preferences
|
||||||
|
pub ui: UiState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppState {
|
impl AppState {
|
||||||
@@ -19,9 +29,11 @@ impl AppState {
|
|||||||
current_dir,
|
current_dir,
|
||||||
total_count: 0,
|
total_count: 0,
|
||||||
current_position: 0,
|
current_position: 0,
|
||||||
|
ui: UiState::default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Existing methods remain unchanged
|
||||||
pub fn update_total_count(&mut self, total_count: u64) {
|
pub fn update_total_count(&mut self, total_count: u64) {
|
||||||
self.total_count = total_count;
|
self.total_count = total_count;
|
||||||
}
|
}
|
||||||
|
|||||||
1
client/src/text.txt
Normal file
1
client/src/text.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
cat src/modes/handlers/event.rs src/state/state.rs src/ui/handlers.rs src/ui/handlers/render.rs src/ui/handlers/ui.rs src/components/handlers.rs
|
||||||
@@ -3,5 +3,7 @@
|
|||||||
pub mod ui;
|
pub mod ui;
|
||||||
pub mod form;
|
pub mod form;
|
||||||
pub mod render;
|
pub mod render;
|
||||||
|
pub mod rat_state;
|
||||||
|
|
||||||
pub use ui::run_ui;
|
pub use ui::run_ui;
|
||||||
|
pub use rat_state::*;
|
||||||
|
|||||||
45
client/src/ui/handlers/rat_state.rs
Normal file
45
client/src/ui/handlers/rat_state.rs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// src/ui/handlers/rat_state.rs
|
||||||
|
use crossterm::event::{KeyCode, KeyModifiers};
|
||||||
|
use crate::config::config::Config;
|
||||||
|
use crate::state::state::UiState;
|
||||||
|
|
||||||
|
pub struct UiStateHandler;
|
||||||
|
|
||||||
|
impl UiStateHandler {
|
||||||
|
pub fn toggle_sidebar(
|
||||||
|
ui_state: &mut UiState,
|
||||||
|
config: &Config,
|
||||||
|
key: KeyCode,
|
||||||
|
modifiers: KeyModifiers,
|
||||||
|
) -> bool {
|
||||||
|
if let Some(action) = config.get_action_for_key_in_mode(&config.keybindings.common, key, modifiers) {
|
||||||
|
if action == "toggle_sidebar" {
|
||||||
|
ui_state.show_sidebar = !ui_state.show_sidebar;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep your existing handle_ui_action method if you need it for other UI actions
|
||||||
|
pub fn handle_ui_action(
|
||||||
|
ui_state: &mut UiState,
|
||||||
|
config: &Config,
|
||||||
|
key: KeyCode,
|
||||||
|
modifiers: KeyModifiers,
|
||||||
|
) -> bool {
|
||||||
|
let mut action_performed = false;
|
||||||
|
|
||||||
|
// Check for sidebar toggle
|
||||||
|
if let Some(action) = config.get_action_for_key_in_mode(&config.keybindings.common, key, modifiers) {
|
||||||
|
if action == "toggle_sidebar" {
|
||||||
|
ui_state.show_sidebar = !ui_state.show_sidebar;
|
||||||
|
action_performed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add other UI actions here following the same pattern
|
||||||
|
|
||||||
|
action_performed
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ use crate::config::colors::Theme;
|
|||||||
use ratatui::layout::{Constraint, Direction, Layout};
|
use ratatui::layout::{Constraint, Direction, Layout};
|
||||||
use ratatui::Frame;
|
use ratatui::Frame;
|
||||||
use super::form::FormState;
|
use super::form::FormState;
|
||||||
|
use crate::state::state::UiState;
|
||||||
|
|
||||||
pub fn render_ui(
|
pub fn render_ui(
|
||||||
f: &mut Frame,
|
f: &mut Frame,
|
||||||
@@ -17,6 +18,7 @@ pub fn render_ui(
|
|||||||
command_input: &str,
|
command_input: &str,
|
||||||
command_mode: bool,
|
command_mode: bool,
|
||||||
command_message: &str,
|
command_message: &str,
|
||||||
|
ui_state: &UiState,
|
||||||
) {
|
) {
|
||||||
let root = Layout::default()
|
let root = Layout::default()
|
||||||
.direction(Direction::Vertical)
|
.direction(Direction::Vertical)
|
||||||
@@ -45,6 +47,10 @@ pub fn render_ui(
|
|||||||
&theme,
|
&theme,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ui_state.show_sidebar {
|
||||||
|
crate::components::handlers::sidebar::render_sidebar(f, main_chunks[0], theme);
|
||||||
|
}
|
||||||
|
|
||||||
// Status line
|
// Status line
|
||||||
render_status_line(f, root[1], current_dir, theme, is_edit_mode);
|
render_status_line(f, root[1], current_dir, theme, is_edit_mode);
|
||||||
|
|
||||||
|
|||||||
@@ -59,9 +59,13 @@ pub async fn run_ui() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
&event_handler.command_input,
|
&event_handler.command_input,
|
||||||
event_handler.command_mode,
|
event_handler.command_mode,
|
||||||
&event_handler.command_message,
|
&event_handler.command_message,
|
||||||
|
&app_state.ui,
|
||||||
);
|
);
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
let total_count = app_state.total_count;
|
||||||
|
let mut current_position = app_state.current_position;
|
||||||
|
|
||||||
let event = event_reader.read_event()?;
|
let event = event_reader.read_event()?;
|
||||||
let (should_exit, message) = event_handler.handle_event(
|
let (should_exit, message) = event_handler.handle_event(
|
||||||
event,
|
event,
|
||||||
@@ -70,11 +74,13 @@ pub async fn run_ui() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
&mut grpc_client,
|
&mut grpc_client,
|
||||||
&mut command_handler,
|
&mut command_handler,
|
||||||
&mut form_state,
|
&mut form_state,
|
||||||
&mut app_state.is_saved,
|
&mut app_state,
|
||||||
app_state.total_count,
|
total_count,
|
||||||
&mut app_state.current_position,
|
&mut current_position,
|
||||||
).await?;
|
).await?;
|
||||||
|
|
||||||
|
app_state.current_position = current_position;
|
||||||
|
|
||||||
// Handle position changes and update form state
|
// Handle position changes and update form state
|
||||||
if !event_handler.is_edit_mode {
|
if !event_handler.is_edit_mode {
|
||||||
let current_input = form_state.get_current_input();
|
let current_input = form_state.get_current_input();
|
||||||
|
|||||||
Reference in New Issue
Block a user