toggle on and off mode
This commit is contained in:
@@ -15,6 +15,7 @@ pub fn render_form(
|
||||
current_field: &usize,
|
||||
inputs: &[&String],
|
||||
theme: &Theme,
|
||||
is_edit_mode: bool,
|
||||
) {
|
||||
// Create Adresar card
|
||||
let adresar_card = Block::default()
|
||||
@@ -40,7 +41,11 @@ pub fn render_form(
|
||||
// Create compact input container
|
||||
let input_container = Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.border_style(Style::default().fg(theme.accent))
|
||||
.border_style(if is_edit_mode {
|
||||
Style::default().fg(theme.accent)
|
||||
} else {
|
||||
Style::default().fg(theme.secondary)
|
||||
})
|
||||
.style(Style::default().bg(theme.bg));
|
||||
|
||||
// Place the input container at the top
|
||||
@@ -89,7 +94,7 @@ pub fn render_form(
|
||||
f.render_widget(input_display, input_rows[i]);
|
||||
|
||||
// Position cursor at the correct position in the active field
|
||||
if is_active {
|
||||
if is_active && is_edit_mode { // Move cursor logic inside the loop
|
||||
let cursor_x = input_rows[i].x + input.len() as u16;
|
||||
let cursor_y = input_rows[i].y;
|
||||
f.set_cursor(cursor_x, cursor_y);
|
||||
|
||||
@@ -8,23 +8,27 @@ use ratatui::{
|
||||
};
|
||||
use crate::client::colors::Theme;
|
||||
|
||||
pub fn render_status_line(f: &mut Frame, area: Rect, current_dir: &str, theme: &Theme) {
|
||||
pub fn render_status_line(
|
||||
f: &mut Frame,
|
||||
area: Rect,
|
||||
current_dir: &str,
|
||||
theme: &Theme,
|
||||
is_edit_mode: bool
|
||||
) {
|
||||
|
||||
// Program name and version
|
||||
let program_info = format!("multieko2 v{}", env!("CARGO_PKG_VERSION"));
|
||||
|
||||
// Create the status line text
|
||||
let status_line = Line::from(vec![
|
||||
Span::styled(current_dir, Style::default().fg(theme.fg)),
|
||||
Span::styled(
|
||||
program_info,
|
||||
Style::default().fg(theme.secondary).add_modifier(ratatui::style::Modifier::BOLD), // Use `secondary` color
|
||||
),
|
||||
]);
|
||||
let mode_text = if is_edit_mode {
|
||||
"[EDIT]"
|
||||
} else {
|
||||
"[READ-ONLY]"
|
||||
};
|
||||
|
||||
// Render the status line
|
||||
let paragraph = Paragraph::new(status_line)
|
||||
.block(Block::default().style(Style::default().bg(theme.bg)))
|
||||
.alignment(Alignment::Left);
|
||||
let text = format!(" {} | {}", mode_text, current_dir);
|
||||
let paragraph = Paragraph::new(text)
|
||||
.style(Style::default().fg(theme.fg).bg(theme.bg));
|
||||
|
||||
f.render_widget(paragraph, area);
|
||||
}
|
||||
|
||||
@@ -63,4 +63,12 @@ impl Config {
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn is_toggle_edit_mode(&self, key: KeyCode, modifiers: KeyModifiers) -> bool {
|
||||
if let Some(bindings) = self.keybindings.get("toggle_edit_mode") {
|
||||
bindings.iter().any(|b| Self::matches_keybinding(b, key, modifiers))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
279
src/client/ui.rs
279
src/client/ui.rs
@@ -48,6 +48,8 @@ pub async fn run_ui() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
// Track the current message to display in the command line
|
||||
let mut command_message = String::new();
|
||||
let mut is_edit_mode = false;
|
||||
let mut edit_mode_cooldown = false;
|
||||
|
||||
loop {
|
||||
app_terminal.draw(|f| {
|
||||
@@ -77,6 +79,7 @@ pub async fn run_ui() -> Result<(), Box<dyn std::error::Error>> {
|
||||
&ucet, &skladm, &ico, &kontakt, &telefon, &skladu, &fax,
|
||||
],
|
||||
&theme,
|
||||
is_edit_mode,
|
||||
);
|
||||
|
||||
// Right panel - Preview Card
|
||||
@@ -90,7 +93,7 @@ pub async fn run_ui() -> Result<(), Box<dyn std::error::Error>> {
|
||||
);
|
||||
|
||||
// Status line
|
||||
render_status_line(f, root[1], ¤t_dir, &theme);
|
||||
render_status_line(f, root[1], ¤t_dir, &theme, is_edit_mode);
|
||||
|
||||
// Command line
|
||||
render_command_line(f, root[2], &command_input, command_mode, &theme, &command_message);
|
||||
@@ -98,10 +101,105 @@ pub async fn run_ui() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
// Event handling
|
||||
if let Event::Key(key) = app_terminal.read_event()? {
|
||||
if command_mode {
|
||||
// First check for edit mode toggle (works in any mode)
|
||||
if config.is_toggle_edit_mode(key.code, key.modifiers) {
|
||||
is_edit_mode = !is_edit_mode;
|
||||
edit_mode_cooldown = true; // Prevent accidental double-toggles
|
||||
command_message = format!("{} mode", if is_edit_mode { "Edit" } else { "Read-only" });
|
||||
continue;
|
||||
}
|
||||
|
||||
if !is_edit_mode {
|
||||
// Read-only mode handling
|
||||
match key.code {
|
||||
KeyCode::Enter => {
|
||||
// Create PostAdresarRequest from form data
|
||||
KeyCode::Char(':') => {
|
||||
command_mode = true;
|
||||
command_input.clear();
|
||||
command_message.clear();
|
||||
}
|
||||
KeyCode::Esc => {
|
||||
command_mode = false;
|
||||
command_input.clear();
|
||||
command_message.clear();
|
||||
}
|
||||
// Allow navigation but prevent editing
|
||||
KeyCode::Tab | KeyCode::BackTab | KeyCode::Down | KeyCode::Up => {
|
||||
if key.modifiers.contains(KeyModifiers::SHIFT) {
|
||||
current_field = current_field.saturating_sub(1);
|
||||
} else {
|
||||
current_field = (current_field + 1) % fields.len();
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Block all other inputs
|
||||
if !edit_mode_cooldown {
|
||||
command_message = format!("Read-only mode - press {} to edit",
|
||||
config.keybindings.get("toggle_edit_mode").unwrap()[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Existing edit mode handling
|
||||
if command_mode {
|
||||
match key.code {
|
||||
KeyCode::Enter => {
|
||||
// Create PostAdresarRequest from form data
|
||||
let form_data = PostAdresarRequest {
|
||||
firma: firma.clone(),
|
||||
kz: kz.clone(),
|
||||
drc: drc.clone(),
|
||||
ulica: ulica.clone(),
|
||||
psc: psc.clone(),
|
||||
mesto: mesto.clone(),
|
||||
stat: stat.clone(),
|
||||
banka: banka.clone(),
|
||||
ucet: ucet.clone(),
|
||||
skladm: skladm.clone(),
|
||||
ico: ico.clone(),
|
||||
kontakt: kontakt.clone(),
|
||||
telefon: telefon.clone(),
|
||||
skladu: skladu.clone(),
|
||||
fax: fax.clone(),
|
||||
};
|
||||
|
||||
// Validate command format
|
||||
let command = command_input.trim();
|
||||
if command.is_empty() {
|
||||
command_message = "Empty command".to_string();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Look up the action for the command string (e.g., "w")
|
||||
let action = config.get_action_for_command(command)
|
||||
.unwrap_or("unknown");
|
||||
|
||||
// Pass the resolved action to handle_command
|
||||
let (should_exit, message) = app_terminal
|
||||
.handle_command(action, &mut is_saved, &form_data)
|
||||
.await?;
|
||||
|
||||
command_message = message;
|
||||
command_mode = false;
|
||||
command_input.clear();
|
||||
|
||||
if should_exit {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
KeyCode::Char(c) => command_input.push(c),
|
||||
KeyCode::Backspace => {
|
||||
command_input.pop(); // Ignore the return value
|
||||
}
|
||||
KeyCode::Esc => {
|
||||
command_mode = false;
|
||||
command_input.clear();
|
||||
command_message.clear();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
// Check for keybindings
|
||||
if let Some(action) = config.get_action_for_key(key.code, key.modifiers) {
|
||||
let form_data = PostAdresarRequest {
|
||||
firma: firma.clone(),
|
||||
kz: kz.clone(),
|
||||
@@ -120,132 +218,79 @@ pub async fn run_ui() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fax: fax.clone(),
|
||||
};
|
||||
|
||||
// Validate command format
|
||||
let command = command_input.trim();
|
||||
if command.is_empty() {
|
||||
command_message = "Empty command".to_string();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Look up the action for the command string (e.g., "w")
|
||||
let action = config.get_action_for_command(command)
|
||||
.unwrap_or("unknown");
|
||||
|
||||
// Pass the resolved action to handle_command
|
||||
// Pass form data to handle_command (remove &config)
|
||||
let (should_exit, message) = app_terminal
|
||||
.handle_command(action, &mut is_saved, &form_data)
|
||||
.await?;
|
||||
|
||||
command_message = message;
|
||||
command_mode = false;
|
||||
command_input.clear();
|
||||
|
||||
if should_exit {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
KeyCode::Char(c) => command_input.push(c),
|
||||
KeyCode::Backspace => {
|
||||
command_input.pop(); // Ignore the return value
|
||||
}
|
||||
KeyCode::Esc => {
|
||||
command_mode = false;
|
||||
command_input.clear();
|
||||
command_message.clear();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
// Check for keybindings
|
||||
if let Some(action) = config.get_action_for_key(key.code, key.modifiers) {
|
||||
let form_data = PostAdresarRequest {
|
||||
firma: firma.clone(),
|
||||
kz: kz.clone(),
|
||||
drc: drc.clone(),
|
||||
ulica: ulica.clone(),
|
||||
psc: psc.clone(),
|
||||
mesto: mesto.clone(),
|
||||
stat: stat.clone(),
|
||||
banka: banka.clone(),
|
||||
ucet: ucet.clone(),
|
||||
skladm: skladm.clone(),
|
||||
ico: ico.clone(),
|
||||
kontakt: kontakt.clone(),
|
||||
telefon: telefon.clone(),
|
||||
skladu: skladu.clone(),
|
||||
fax: fax.clone(),
|
||||
};
|
||||
|
||||
// Pass form data to handle_command (remove &config)
|
||||
let (should_exit, message) = app_terminal
|
||||
.handle_command(action, &mut is_saved, &form_data)
|
||||
.await?;
|
||||
command_message = message;
|
||||
if should_exit {
|
||||
return Ok(());
|
||||
}
|
||||
} else {
|
||||
match key.code {
|
||||
KeyCode::Char(':') => {
|
||||
command_mode = true;
|
||||
command_input.clear();
|
||||
command_message.clear();
|
||||
}
|
||||
KeyCode::Tab => {
|
||||
if key.modifiers.contains(KeyModifiers::SHIFT) {
|
||||
current_field = current_field.saturating_sub(1);
|
||||
} else {
|
||||
current_field = (current_field + 1) % fields.len();
|
||||
} else {
|
||||
match key.code {
|
||||
KeyCode::Char(':') => {
|
||||
command_mode = true;
|
||||
command_input.clear();
|
||||
command_message.clear();
|
||||
}
|
||||
}
|
||||
KeyCode::BackTab => current_field = current_field.saturating_sub(1),
|
||||
KeyCode::Down => current_field = (current_field + 1) % fields.len(),
|
||||
KeyCode::Up => current_field = current_field.saturating_sub(1),
|
||||
KeyCode::Enter => current_field = (current_field + 1) % fields.len(),
|
||||
KeyCode::Char(c) => {
|
||||
match current_field {
|
||||
0 => firma.push(c),
|
||||
1 => kz.push(c),
|
||||
2 => drc.push(c),
|
||||
3 => ulica.push(c),
|
||||
4 => psc.push(c),
|
||||
5 => mesto.push(c),
|
||||
6 => stat.push(c),
|
||||
7 => banka.push(c),
|
||||
8 => ucet.push(c),
|
||||
9 => skladm.push(c),
|
||||
10 => ico.push(c),
|
||||
11 => kontakt.push(c),
|
||||
12 => telefon.push(c),
|
||||
13 => skladu.push(c),
|
||||
14 => fax.push(c),
|
||||
_ => (),
|
||||
KeyCode::Tab => {
|
||||
if key.modifiers.contains(KeyModifiers::SHIFT) {
|
||||
current_field = current_field.saturating_sub(1);
|
||||
} else {
|
||||
current_field = (current_field + 1) % fields.len();
|
||||
}
|
||||
}
|
||||
KeyCode::BackTab => current_field = current_field.saturating_sub(1),
|
||||
KeyCode::Down => current_field = (current_field + 1) % fields.len(),
|
||||
KeyCode::Up => current_field = current_field.saturating_sub(1),
|
||||
KeyCode::Enter => current_field = (current_field + 1) % fields.len(),
|
||||
KeyCode::Char(c) => {
|
||||
match current_field {
|
||||
0 => firma.push(c),
|
||||
1 => kz.push(c),
|
||||
2 => drc.push(c),
|
||||
3 => ulica.push(c),
|
||||
4 => psc.push(c),
|
||||
5 => mesto.push(c),
|
||||
6 => stat.push(c),
|
||||
7 => banka.push(c),
|
||||
8 => ucet.push(c),
|
||||
9 => skladm.push(c),
|
||||
10 => ico.push(c),
|
||||
11 => kontakt.push(c),
|
||||
12 => telefon.push(c),
|
||||
13 => skladu.push(c),
|
||||
14 => fax.push(c),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
KeyCode::Backspace => {
|
||||
match current_field {
|
||||
0 => firma.pop(),
|
||||
1 => kz.pop(),
|
||||
2 => drc.pop(),
|
||||
3 => ulica.pop(),
|
||||
4 => psc.pop(),
|
||||
5 => mesto.pop(),
|
||||
6 => stat.pop(),
|
||||
7 => banka.pop(),
|
||||
8 => ucet.pop(),
|
||||
9 => skladm.pop(),
|
||||
10 => ico.pop(),
|
||||
11 => kontakt.pop(),
|
||||
12 => telefon.pop(),
|
||||
13 => skladu.pop(),
|
||||
14 => fax.pop(),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
KeyCode::Backspace => {
|
||||
match current_field {
|
||||
0 => firma.pop(),
|
||||
1 => kz.pop(),
|
||||
2 => drc.pop(),
|
||||
3 => ulica.pop(),
|
||||
4 => psc.pop(),
|
||||
5 => mesto.pop(),
|
||||
6 => stat.pop(),
|
||||
7 => banka.pop(),
|
||||
8 => ucet.pop(),
|
||||
9 => skladm.pop(),
|
||||
10 => ico.pop(),
|
||||
11 => kontakt.pop(),
|
||||
12 => telefon.pop(),
|
||||
13 => skladu.pop(),
|
||||
14 => fax.pop(),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
edit_mode_cooldown = false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user