From d837acde6356108097825421cde92129be833579 Mon Sep 17 00:00:00 2001 From: Priec Date: Tue, 29 Jul 2025 16:05:45 +0200 Subject: [PATCH] bugs fixed, canvas library now replaced internal canvas, only form is using it now --- client/Cargo.toml | 2 +- client/src/modes/handlers/event.rs | 119 +++++++++++++++++++++++------ 2 files changed, 97 insertions(+), 24 deletions(-) diff --git a/client/Cargo.toml b/client/Cargo.toml index 2668585..5d0ae51 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -31,7 +31,7 @@ unicode-width = "0.2.0" [features] default = [] - +ui-debug = [] [dev-dependencies] rstest = "0.25.0" diff --git a/client/src/modes/handlers/event.rs b/client/src/modes/handlers/event.rs index f3078b0..f24c659 100644 --- a/client/src/modes/handlers/event.rs +++ b/client/src/modes/handlers/event.rs @@ -1037,7 +1037,7 @@ impl EventHandler { form_state, &mut self.ideal_cursor_column, ).await { - return Ok(result.message().map(|s| s.to_string())); + return Ok(Some(result.message().unwrap_or("").to_string())); } } KeyCode::Down => { @@ -1046,7 +1046,7 @@ impl EventHandler { form_state, &mut self.ideal_cursor_column, ).await { - return Ok(result.message().map(|s| s.to_string())); + return Ok(Some(result.message().unwrap_or("").to_string())); } } KeyCode::Enter => { @@ -1055,7 +1055,7 @@ impl EventHandler { form_state, &mut self.ideal_cursor_column, ).await { - return Ok(result.message().map(|s| s.to_string())); + return Ok(Some(result.message().unwrap_or("").to_string())); } } KeyCode::Esc => { @@ -1064,30 +1064,14 @@ impl EventHandler { form_state, &mut self.ideal_cursor_column, ).await { - return Ok(result.message().map(|s| s.to_string())); + return Ok(Some(result.message().unwrap_or("").to_string())); } } _ => {} } } - // Try to create canvas action from key - if let Some(canvas_action) = CanvasAction::from_key(key_event.code) { - match ActionDispatcher::dispatch( - canvas_action, - form_state, - &mut self.ideal_cursor_column, - ).await { - Ok(result) => { - return Ok(result.message().map(|s| s.to_string())); - } - Err(_) => { - // Fall through to try config mapping - } - } - } - - // Try mapped actions from config + // Check config mappings FIRST, before CanvasAction::from_key let action_str = if is_edit_mode { config.get_edit_action_for_key(key_event.code, key_event.modifiers) } else { @@ -1095,6 +1079,11 @@ impl EventHandler { }; if let Some(action_str) = action_str { + // FIXED: Filter out mode transition actions - let legacy handlers deal with these + if Self::is_mode_transition_action(action_str) { + return Ok(None); // Let legacy handler handle mode transitions + } + let canvas_action = CanvasAction::from_string(&action_str); match ActionDispatcher::dispatch( canvas_action, @@ -1102,14 +1091,98 @@ impl EventHandler { &mut self.ideal_cursor_column, ).await { Ok(result) => { - return Ok(result.message().map(|s| s.to_string())); + return Ok(Some(result.message().unwrap_or("").to_string())); } Err(_) => { - // Ignore error, let existing code handle it + return Ok(Some("Action failed".to_string())); + } + } + } + + // Only try CanvasAction::from_key as a fallback, and be more selective + if is_edit_mode { + // In edit mode, allow character insertion for unmapped keys + if let Some(canvas_action) = CanvasAction::from_key(key_event.code) { + match ActionDispatcher::dispatch( + canvas_action, + form_state, + &mut self.ideal_cursor_column, + ).await { + Ok(result) => { + return Ok(Some(result.message().unwrap_or("").to_string())); + } + Err(_) => { + return Ok(Some("Action failed".to_string())); + } + } + } + } else { + // In read-only mode, only handle non-character keys + let canvas_action = match key_event.code { + // Only handle special keys that don't conflict with vim bindings + KeyCode::Left => Some(CanvasAction::MoveLeft), + KeyCode::Right => Some(CanvasAction::MoveRight), + KeyCode::Up => Some(CanvasAction::MoveUp), + KeyCode::Down => Some(CanvasAction::MoveDown), + KeyCode::Home => Some(CanvasAction::MoveLineStart), + KeyCode::End => Some(CanvasAction::MoveLineEnd), + KeyCode::Tab => Some(CanvasAction::NextField), + KeyCode::BackTab => Some(CanvasAction::PrevField), + KeyCode::Delete => Some(CanvasAction::DeleteForward), + KeyCode::Backspace => Some(CanvasAction::DeleteBackward), + // DON'T handle Char(c) in read-only mode - let config handle it + _ => None, + }; + + if let Some(canvas_action) = canvas_action { + match ActionDispatcher::dispatch( + canvas_action, + form_state, + &mut self.ideal_cursor_column, + ).await { + Ok(result) => { + return Ok(Some(result.message().unwrap_or("").to_string())); + } + Err(_) => { + return Ok(Some("Action failed".to_string())); + } } } } Ok(None) } + + // ADDED: Helper function to identify mode transition actions + fn is_mode_transition_action(action: &str) -> bool { + matches!(action, + "exit" | + "exit_edit_mode" | + "enter_edit_mode_before" | + "enter_edit_mode_after" | + "enter_command_mode" | + "exit_command_mode" | + "enter_highlight_mode" | + "enter_highlight_mode_linewise" | + "exit_highlight_mode" | + "save" | + "quit" | + "force_quit" | + "save_and_quit" | + "revert" | + "enter_decider" | // This is also handled specially by legacy system + "trigger_autocomplete" | // This is handled specially by legacy system + "suggestion_up" | // These are handled above in suggestion logic + "suggestion_down" | + "previous_entry" | // Navigation between records + "next_entry" | + "toggle_sidebar" | + "toggle_buffer_list" | + "next_buffer" | + "previous_buffer" | + "close_buffer" | + "open_search" | + "find_file_palette_toggle" + ) + } }