logic is being implemented properly well
This commit is contained in:
@@ -14,7 +14,6 @@ use ratatui::{
|
|||||||
use crate::components::handlers::canvas::render_canvas;
|
use crate::components::handlers::canvas::render_canvas;
|
||||||
use crate::components::common::dialog;
|
use crate::components::common::dialog;
|
||||||
use crate::config::binds::config::EditorKeybindingMode;
|
use crate::config::binds::config::EditorKeybindingMode;
|
||||||
use crate::components::common::text_editor::TextEditor;
|
|
||||||
|
|
||||||
pub fn render_add_logic(
|
pub fn render_add_logic(
|
||||||
f: &mut Frame,
|
f: &mut Frame,
|
||||||
@@ -35,7 +34,8 @@ pub fn render_add_logic(
|
|||||||
let inner_area = main_block.inner(area);
|
let inner_area = main_block.inner(area);
|
||||||
f.render_widget(main_block, area);
|
f.render_widget(main_block, area);
|
||||||
|
|
||||||
if add_logic_state.current_focus == AddLogicFocus::InputScriptContent {
|
// Handle full-screen script editing
|
||||||
|
if add_logic_state.current_focus == AddLogicFocus::InsideScriptContent {
|
||||||
let mut editor_ref = add_logic_state.script_content_editor.borrow_mut();
|
let mut editor_ref = add_logic_state.script_content_editor.borrow_mut();
|
||||||
let border_style_color = if is_edit_mode { theme.highlight } else { theme.secondary };
|
let border_style_color = if is_edit_mode { theme.highlight } else { theme.secondary };
|
||||||
let border_style = Style::default().fg(border_style_color);
|
let border_style = Style::default().fg(border_style_color);
|
||||||
@@ -44,18 +44,18 @@ pub fn render_add_logic(
|
|||||||
|
|
||||||
let script_title_hint = match add_logic_state.editor_keybinding_mode {
|
let script_title_hint = match add_logic_state.editor_keybinding_mode {
|
||||||
EditorKeybindingMode::Vim => {
|
EditorKeybindingMode::Vim => {
|
||||||
let vim_mode_status = TextEditor::get_vim_mode_status(&add_logic_state.vim_state);
|
let vim_mode_status = crate::components::common::text_editor::TextEditor::get_vim_mode_status(&add_logic_state.vim_state);
|
||||||
if is_edit_mode {
|
if is_edit_mode {
|
||||||
format!("Script (VIM {}) - Esc for Normal. Tab navigates from Normal.", vim_mode_status)
|
format!("Script (VIM {}) - Esc for Normal. Esc again to exit.", vim_mode_status)
|
||||||
} else {
|
} else {
|
||||||
format!("Script (VIM {}) - 'i'/'a'/'o' for Insert. Tab to navigate.", vim_mode_status)
|
format!("Script (VIM {}) - 'i'/'a'/'o' for Insert. Esc to exit.", vim_mode_status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EditorKeybindingMode::Emacs | EditorKeybindingMode::Default => {
|
EditorKeybindingMode::Emacs | EditorKeybindingMode::Default => {
|
||||||
if is_edit_mode {
|
if is_edit_mode {
|
||||||
"Script (Editing - Esc to exit edit. Tab navigates after exit.)".to_string()
|
"Script (Editing - Esc to exit edit. Esc again to exit script.)".to_string()
|
||||||
} else {
|
} else {
|
||||||
"Script (Press Enter or Ctrl+E to edit. Tab to navigate.)".to_string()
|
"Script (Press Enter or Ctrl+E to edit. Esc to exit.)".to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -68,19 +68,18 @@ pub fn render_add_logic(
|
|||||||
.border_type(BorderType::Rounded)
|
.border_type(BorderType::Rounded)
|
||||||
.border_style(border_style),
|
.border_style(border_style),
|
||||||
);
|
);
|
||||||
// Remove .widget() call - just pass the reference directly
|
|
||||||
f.render_widget(&*editor_ref, inner_area);
|
f.render_widget(&*editor_ref, inner_area);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ... rest of the layout code ...
|
// Regular layout with preview
|
||||||
let main_chunks = Layout::default()
|
let main_chunks = Layout::default()
|
||||||
.direction(Direction::Vertical)
|
.direction(Direction::Vertical)
|
||||||
.constraints([
|
.constraints([
|
||||||
Constraint::Length(3),
|
Constraint::Length(3), // Top info
|
||||||
Constraint::Length(9),
|
Constraint::Length(9), // Canvas
|
||||||
Constraint::Min(5),
|
Constraint::Min(5), // Script preview
|
||||||
Constraint::Length(3),
|
Constraint::Length(3), // Buttons
|
||||||
])
|
])
|
||||||
.split(inner_area);
|
.split(inner_area);
|
||||||
|
|
||||||
@@ -89,6 +88,7 @@ pub fn render_add_logic(
|
|||||||
let script_content_area = main_chunks[2];
|
let script_content_area = main_chunks[2];
|
||||||
let buttons_area = main_chunks[3];
|
let buttons_area = main_chunks[3];
|
||||||
|
|
||||||
|
// Top info
|
||||||
let profile_text = Paragraph::new(vec![
|
let profile_text = Paragraph::new(vec![
|
||||||
Line::from(Span::styled(
|
Line::from(Span::styled(
|
||||||
format!("Profile: {}", add_logic_state.profile_name),
|
format!("Profile: {}", add_logic_state.profile_name),
|
||||||
@@ -114,6 +114,7 @@ pub fn render_add_logic(
|
|||||||
);
|
);
|
||||||
f.render_widget(profile_text, top_info_area);
|
f.render_widget(profile_text, top_info_area);
|
||||||
|
|
||||||
|
// Canvas
|
||||||
let focus_on_canvas_inputs = matches!(
|
let focus_on_canvas_inputs = matches!(
|
||||||
add_logic_state.current_focus,
|
add_logic_state.current_focus,
|
||||||
AddLogicFocus::InputLogicName
|
AddLogicFocus::InputLogicName
|
||||||
@@ -132,32 +133,41 @@ pub fn render_add_logic(
|
|||||||
highlight_state,
|
highlight_state,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Script content preview (like table preview in add_table)
|
||||||
{
|
{
|
||||||
let mut editor_ref = add_logic_state.script_content_editor.borrow_mut();
|
let mut editor_ref = add_logic_state.script_content_editor.borrow_mut();
|
||||||
editor_ref.set_cursor_line_style(Style::default());
|
editor_ref.set_cursor_line_style(Style::default());
|
||||||
|
|
||||||
let border_style_color = if add_logic_state.current_focus == AddLogicFocus::InputScriptContent {
|
let is_script_focused = add_logic_state.current_focus == AddLogicFocus::ScriptContentPreview;
|
||||||
theme.highlight
|
let border_style_color = if is_script_focused {
|
||||||
|
theme.highlight // Green highlight when focused and ready to select
|
||||||
} else {
|
} else {
|
||||||
theme.secondary
|
theme.secondary
|
||||||
};
|
};
|
||||||
|
|
||||||
let title_hint = match add_logic_state.editor_keybinding_mode {
|
let title_text = if is_script_focused {
|
||||||
EditorKeybindingMode::Vim => "Script Preview (VIM - Focus with Tab, then 'i'/'a'/'o' to edit)",
|
"Script Preview (Press Enter to edit) [FOCUSED]"
|
||||||
_ => "Script Preview (Focus with Tab, then Enter/Ctrl+E to edit)",
|
} else {
|
||||||
|
"Script Preview"
|
||||||
|
};
|
||||||
|
|
||||||
|
let title_style = if is_script_focused {
|
||||||
|
Style::default().fg(theme.highlight).add_modifier(Modifier::BOLD)
|
||||||
|
} else {
|
||||||
|
Style::default().fg(theme.fg)
|
||||||
};
|
};
|
||||||
|
|
||||||
editor_ref.set_block(
|
editor_ref.set_block(
|
||||||
Block::default()
|
Block::default()
|
||||||
.title(title_hint)
|
.title(Span::styled(title_text, title_style))
|
||||||
.borders(Borders::ALL)
|
.borders(Borders::ALL)
|
||||||
.border_type(BorderType::Rounded)
|
.border_type(BorderType::Rounded)
|
||||||
.border_style(Style::default().fg(border_style_color)),
|
.border_style(Style::default().fg(border_style_color)),
|
||||||
);
|
);
|
||||||
// Remove .widget() call here too
|
|
||||||
f.render_widget(&*editor_ref, script_content_area);
|
f.render_widget(&*editor_ref, script_content_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Buttons
|
||||||
let get_button_style = |button_focus: AddLogicFocus, current_focus| {
|
let get_button_style = |button_focus: AddLogicFocus, current_focus| {
|
||||||
let is_focused = current_focus == button_focus;
|
let is_focused = current_focus == button_focus;
|
||||||
let base_style = Style::default().fg(if is_focused {
|
let base_style = Style::default().fg(if is_focused {
|
||||||
@@ -222,6 +232,7 @@ pub fn render_add_logic(
|
|||||||
);
|
);
|
||||||
f.render_widget(cancel_button, button_chunks[1]);
|
f.render_widget(cancel_button, button_chunks[1]);
|
||||||
|
|
||||||
|
// Dialog
|
||||||
if app_state.ui.dialog.dialog_show {
|
if app_state.ui.dialog.dialog_show {
|
||||||
dialog::render_dialog(
|
dialog::render_dialog(
|
||||||
f,
|
f,
|
||||||
|
|||||||
@@ -10,9 +10,7 @@ use crossterm::event::{KeyEvent, KeyCode, KeyModifiers};
|
|||||||
use crate::services::GrpcClient;
|
use crate::services::GrpcClient;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use common::proto::multieko2::table_script::PostTableScriptRequest;
|
|
||||||
use crate::components::common::text_editor::TextEditor;
|
use crate::components::common::text_editor::TextEditor;
|
||||||
use tui_textarea::Input as TextAreaInput;
|
|
||||||
|
|
||||||
pub type SaveLogicResultSender = mpsc::Sender<Result<String>>;
|
pub type SaveLogicResultSender = mpsc::Sender<Result<String>>;
|
||||||
|
|
||||||
@@ -27,236 +25,214 @@ pub fn handle_add_logic_navigation(
|
|||||||
save_logic_sender: SaveLogicResultSender,
|
save_logic_sender: SaveLogicResultSender,
|
||||||
command_message: &mut String,
|
command_message: &mut String,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut handled = false;
|
// === FULLSCREEN SCRIPT EDITING - COMPLETE ISOLATION ===
|
||||||
let general_action = config.get_general_action(key_event.code, key_event.modifiers);
|
if add_logic_state.current_focus == AddLogicFocus::InsideScriptContent {
|
||||||
|
|
||||||
if add_logic_state.current_focus == AddLogicFocus::InputScriptContent {
|
|
||||||
let mut editor_borrow = add_logic_state.script_content_editor.borrow_mut();
|
let mut editor_borrow = add_logic_state.script_content_editor.borrow_mut();
|
||||||
|
|
||||||
match add_logic_state.editor_keybinding_mode {
|
// Handle ONLY Escape to exit fullscreen mode
|
||||||
EditorKeybindingMode::Vim => {
|
|
||||||
if *is_edit_mode { // App considers textarea to be in "typing" (Insert) mode
|
|
||||||
let changed = TextEditor::handle_input(
|
|
||||||
&mut editor_borrow,
|
|
||||||
key_event,
|
|
||||||
&add_logic_state.editor_keybinding_mode,
|
|
||||||
&mut add_logic_state.vim_state,
|
|
||||||
);
|
|
||||||
if changed { add_logic_state.has_unsaved_changes = true; }
|
|
||||||
|
|
||||||
// Check if we've transitioned to Normal mode
|
|
||||||
if key_event.code == KeyCode::Esc && TextEditor::is_vim_normal_mode(&add_logic_state.vim_state) {
|
|
||||||
*is_edit_mode = false;
|
|
||||||
*command_message = "VIM: Normal Mode. Tab to navigate.".to_string();
|
|
||||||
}
|
|
||||||
handled = true;
|
|
||||||
} else { // App considers textarea to be in "navigation" (Normal) mode
|
|
||||||
match key_event.code {
|
|
||||||
// Keys to enter Vim Insert mode
|
|
||||||
KeyCode::Char('i') | KeyCode::Char('a') | KeyCode::Char('o') |
|
|
||||||
KeyCode::Char('I') | KeyCode::Char('A') | KeyCode::Char('O') => {
|
|
||||||
*is_edit_mode = true;
|
|
||||||
TextEditor::handle_input(
|
|
||||||
&mut editor_borrow,
|
|
||||||
key_event,
|
|
||||||
&add_logic_state.editor_keybinding_mode,
|
|
||||||
&mut add_logic_state.vim_state
|
|
||||||
);
|
|
||||||
*command_message = "VIM: Insert Mode.".to_string();
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
if general_action.is_none() {
|
|
||||||
let changed = TextEditor::handle_input(
|
|
||||||
&mut editor_borrow,
|
|
||||||
key_event,
|
|
||||||
&add_logic_state.editor_keybinding_mode,
|
|
||||||
&mut add_logic_state.vim_state,
|
|
||||||
);
|
|
||||||
if changed { add_logic_state.has_unsaved_changes = true; }
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EditorKeybindingMode::Emacs | EditorKeybindingMode::Default => {
|
|
||||||
if *is_edit_mode {
|
|
||||||
if key_event.code == KeyCode::Esc && key_event.modifiers == KeyModifiers::NONE {
|
if key_event.code == KeyCode::Esc && key_event.modifiers == KeyModifiers::NONE {
|
||||||
*is_edit_mode = false;
|
|
||||||
*command_message = "Exited script edit. Tab to navigate.".to_string();
|
|
||||||
handled = true;
|
|
||||||
} else if general_action.is_some() && (general_action.unwrap() == "next_field" || general_action.unwrap() == "prev_field") {
|
|
||||||
let changed = TextEditor::handle_input(
|
|
||||||
&mut editor_borrow,
|
|
||||||
key_event,
|
|
||||||
&add_logic_state.editor_keybinding_mode,
|
|
||||||
&mut add_logic_state.vim_state
|
|
||||||
);
|
|
||||||
if changed { add_logic_state.has_unsaved_changes = true; }
|
|
||||||
handled = true;
|
|
||||||
} else {
|
|
||||||
let changed = TextEditor::handle_input(
|
|
||||||
&mut editor_borrow,
|
|
||||||
key_event,
|
|
||||||
&add_logic_state.editor_keybinding_mode,
|
|
||||||
&mut add_logic_state.vim_state
|
|
||||||
);
|
|
||||||
if changed { add_logic_state.has_unsaved_changes = true; }
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if handled { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// If not handled above (e.g., Tab/Shift+Tab, or Enter when script content not in edit mode),
|
|
||||||
// process general application-level actions.
|
|
||||||
let action_str = general_action.map(String::from);
|
|
||||||
match action_str.as_deref() {
|
|
||||||
Some("exit_view") | Some("cancel_action") => {
|
|
||||||
buffer_state.update_history(AppView::Admin);
|
|
||||||
app_state.ui.show_add_logic = false;
|
|
||||||
*command_message = "Exited Add Logic".to_string();
|
|
||||||
*is_edit_mode = false;
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
Some("next_field") | Some("prev_field") => {
|
|
||||||
let is_next = action_str.as_deref() == Some("next_field");
|
|
||||||
let previous_focus = add_logic_state.current_focus;
|
|
||||||
|
|
||||||
add_logic_state.current_focus = if is_next {
|
|
||||||
match add_logic_state.current_focus {
|
|
||||||
AddLogicFocus::InputLogicName => AddLogicFocus::InputTargetColumn,
|
|
||||||
AddLogicFocus::InputTargetColumn => AddLogicFocus::InputDescription,
|
|
||||||
AddLogicFocus::InputDescription => AddLogicFocus::InputScriptContent,
|
|
||||||
AddLogicFocus::InputScriptContent => AddLogicFocus::SaveButton,
|
|
||||||
AddLogicFocus::SaveButton => AddLogicFocus::CancelButton,
|
|
||||||
AddLogicFocus::CancelButton => AddLogicFocus::InputLogicName,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
match add_logic_state.current_focus {
|
|
||||||
AddLogicFocus::InputLogicName => AddLogicFocus::CancelButton,
|
|
||||||
AddLogicFocus::InputTargetColumn => AddLogicFocus::InputLogicName,
|
|
||||||
AddLogicFocus::InputDescription => AddLogicFocus::InputTargetColumn,
|
|
||||||
AddLogicFocus::InputScriptContent => AddLogicFocus::InputDescription,
|
|
||||||
AddLogicFocus::SaveButton => AddLogicFocus::InputScriptContent,
|
|
||||||
AddLogicFocus::CancelButton => AddLogicFocus::SaveButton,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if add_logic_state.current_focus == AddLogicFocus::InputScriptContent {
|
|
||||||
*is_edit_mode = false;
|
|
||||||
let mode_hint = match add_logic_state.editor_keybinding_mode {
|
|
||||||
EditorKeybindingMode::Vim => "'i'/'a'/'o' to insert",
|
|
||||||
_ => "Enter/Ctrl+E to edit",
|
|
||||||
};
|
|
||||||
*command_message = format!("Focus: Script Content. Press {} or Tab.", mode_hint);
|
|
||||||
} else if matches!(add_logic_state.current_focus, AddLogicFocus::InputLogicName | AddLogicFocus::InputTargetColumn | AddLogicFocus::InputDescription) {
|
|
||||||
*is_edit_mode = true;
|
|
||||||
*command_message = format!("Focus: {:?}. Edit mode ON.", add_logic_state.current_focus);
|
|
||||||
} else {
|
|
||||||
*is_edit_mode = false;
|
|
||||||
*command_message = format!("Focus: {:?}", add_logic_state.current_focus);
|
|
||||||
}
|
|
||||||
|
|
||||||
app_state.ui.focus_outside_canvas = !matches!(
|
|
||||||
add_logic_state.current_focus,
|
|
||||||
AddLogicFocus::InputLogicName | AddLogicFocus::InputTargetColumn | AddLogicFocus::InputDescription | AddLogicFocus::InputScriptContent
|
|
||||||
);
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
Some("select") => {
|
|
||||||
match add_logic_state.current_focus {
|
|
||||||
AddLogicFocus::InputScriptContent => {
|
|
||||||
*is_edit_mode = true;
|
|
||||||
let mut editor_borrow = add_logic_state.script_content_editor.borrow_mut();
|
|
||||||
match add_logic_state.editor_keybinding_mode {
|
|
||||||
EditorKeybindingMode::Vim => {
|
|
||||||
TextEditor::handle_input(
|
|
||||||
&mut editor_borrow,
|
|
||||||
KeyEvent::new(KeyCode::Char('i'), KeyModifiers::NONE),
|
|
||||||
&add_logic_state.editor_keybinding_mode,
|
|
||||||
&mut add_logic_state.vim_state,
|
|
||||||
);
|
|
||||||
*command_message = "VIM: Insert Mode.".to_string();
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
*command_message = "Entered script edit mode.".to_string();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
AddLogicFocus::SaveButton => { handled = true; }
|
|
||||||
AddLogicFocus::CancelButton => { *is_edit_mode = false; handled = true; }
|
|
||||||
AddLogicFocus::InputLogicName | AddLogicFocus::InputTargetColumn | AddLogicFocus::InputDescription => {
|
|
||||||
*is_edit_mode = !*is_edit_mode;
|
|
||||||
*command_message = format!("Field edit mode: {}", if *is_edit_mode { "ON" } else { "OFF" });
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some("toggle_edit_mode") => {
|
|
||||||
match add_logic_state.current_focus {
|
|
||||||
AddLogicFocus::InputScriptContent => {
|
|
||||||
let mut editor_borrow = add_logic_state.script_content_editor.borrow_mut();
|
|
||||||
match add_logic_state.editor_keybinding_mode {
|
match add_logic_state.editor_keybinding_mode {
|
||||||
EditorKeybindingMode::Vim => {
|
EditorKeybindingMode::Vim => {
|
||||||
if *is_edit_mode {
|
if *is_edit_mode {
|
||||||
|
// First escape: try to go to Vim Normal mode
|
||||||
TextEditor::handle_input(
|
TextEditor::handle_input(
|
||||||
&mut editor_borrow,
|
&mut editor_borrow,
|
||||||
KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE),
|
key_event,
|
||||||
&add_logic_state.editor_keybinding_mode,
|
&add_logic_state.editor_keybinding_mode,
|
||||||
&mut add_logic_state.vim_state,
|
&mut add_logic_state.vim_state,
|
||||||
);
|
);
|
||||||
if TextEditor::is_vim_normal_mode(&add_logic_state.vim_state) {
|
if TextEditor::is_vim_normal_mode(&add_logic_state.vim_state) {
|
||||||
*is_edit_mode = false;
|
*is_edit_mode = false;
|
||||||
*command_message = "VIM: Normal Mode. Tab to navigate.".to_string();
|
*command_message = "VIM: Normal Mode. Esc again to exit script.".to_string();
|
||||||
} else {
|
|
||||||
*command_message = "VIM: Still in Insert Mode (toggle error?).".to_string();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TextEditor::handle_input(
|
// Second escape: exit fullscreen
|
||||||
&mut editor_borrow,
|
add_logic_state.current_focus = AddLogicFocus::ScriptContentPreview;
|
||||||
KeyEvent::new(KeyCode::Char('i'), KeyModifiers::NONE),
|
app_state.ui.focus_outside_canvas = true;
|
||||||
&add_logic_state.editor_keybinding_mode,
|
*is_edit_mode = false;
|
||||||
&mut add_logic_state.vim_state,
|
*command_message = "Exited script editing.".to_string();
|
||||||
);
|
|
||||||
*is_edit_mode = true;
|
|
||||||
*command_message = "VIM: Insert Mode.".to_string();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
*is_edit_mode = !*is_edit_mode;
|
if *is_edit_mode {
|
||||||
*command_message = format!("Script edit mode: {}", if *is_edit_mode { "ON" } else { "OFF. Tab to navigate." });
|
*is_edit_mode = false;
|
||||||
|
*command_message = "Exited script edit. Esc again to exit script.".to_string();
|
||||||
|
} else {
|
||||||
|
// Exit fullscreen
|
||||||
|
add_logic_state.current_focus = AddLogicFocus::ScriptContentPreview;
|
||||||
|
app_state.ui.focus_outside_canvas = true;
|
||||||
|
*is_edit_mode = false;
|
||||||
|
*command_message = "Exited script editing.".to_string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
handled = true;
|
|
||||||
}
|
}
|
||||||
AddLogicFocus::InputLogicName | AddLogicFocus::InputTargetColumn | AddLogicFocus::InputDescription => {
|
return true;
|
||||||
*is_edit_mode = !*is_edit_mode;
|
|
||||||
*command_message = format!("Canvas field edit mode: {}", if *is_edit_mode { "ON" } else { "OFF" });
|
|
||||||
handled = true;
|
|
||||||
}
|
}
|
||||||
_ => { *command_message = "Cannot toggle edit mode here.".to_string(); handled = true; }
|
|
||||||
}
|
// ALL OTHER KEYS: Pass directly to textarea without any interference
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
if add_logic_state.current_focus == AddLogicFocus::InputScriptContent &&
|
|
||||||
!*is_edit_mode &&
|
|
||||||
add_logic_state.editor_keybinding_mode == EditorKeybindingMode::Vim {
|
|
||||||
let mut editor_borrow = add_logic_state.script_content_editor.borrow_mut();
|
|
||||||
let changed = TextEditor::handle_input(
|
let changed = TextEditor::handle_input(
|
||||||
&mut editor_borrow,
|
&mut editor_borrow,
|
||||||
key_event,
|
key_event,
|
||||||
&add_logic_state.editor_keybinding_mode,
|
&add_logic_state.editor_keybinding_mode,
|
||||||
&mut add_logic_state.vim_state
|
&mut add_logic_state.vim_state,
|
||||||
);
|
);
|
||||||
if changed { add_logic_state.has_unsaved_changes = true; }
|
if changed {
|
||||||
handled = true;
|
add_logic_state.has_unsaved_changes = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update edit mode status for Vim
|
||||||
|
if add_logic_state.editor_keybinding_mode == EditorKeybindingMode::Vim {
|
||||||
|
*is_edit_mode = !TextEditor::is_vim_normal_mode(&add_logic_state.vim_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true; // Always consume the event in fullscreen mode
|
||||||
|
}
|
||||||
|
// === END FULLSCREEN ISOLATION ===
|
||||||
|
|
||||||
|
// Regular navigation logic for non-fullscreen elements
|
||||||
|
let action = config.get_general_action(key_event.code, key_event.modifiers);
|
||||||
|
let current_focus = add_logic_state.current_focus;
|
||||||
|
let mut handled = true;
|
||||||
|
let mut new_focus = current_focus;
|
||||||
|
|
||||||
|
match action.as_deref() {
|
||||||
|
Some("exit_table_scroll") => {
|
||||||
|
// This shouldn't happen since we handle InsideScriptContent above
|
||||||
|
handled = false;
|
||||||
|
}
|
||||||
|
Some("move_up") => {
|
||||||
|
match current_focus {
|
||||||
|
AddLogicFocus::InputLogicName => {
|
||||||
|
// Stay at top
|
||||||
|
}
|
||||||
|
AddLogicFocus::InputTargetColumn => new_focus = AddLogicFocus::InputLogicName,
|
||||||
|
AddLogicFocus::InputDescription => new_focus = AddLogicFocus::InputTargetColumn,
|
||||||
|
AddLogicFocus::ScriptContentPreview => new_focus = AddLogicFocus::InputDescription,
|
||||||
|
AddLogicFocus::SaveButton => new_focus = AddLogicFocus::ScriptContentPreview,
|
||||||
|
AddLogicFocus::CancelButton => new_focus = AddLogicFocus::SaveButton,
|
||||||
|
_ => handled = false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some("move_down") => {
|
||||||
|
match current_focus {
|
||||||
|
AddLogicFocus::InputLogicName => new_focus = AddLogicFocus::InputTargetColumn,
|
||||||
|
AddLogicFocus::InputTargetColumn => new_focus = AddLogicFocus::InputDescription,
|
||||||
|
AddLogicFocus::InputDescription => {
|
||||||
|
add_logic_state.last_canvas_field = 2;
|
||||||
|
new_focus = AddLogicFocus::ScriptContentPreview;
|
||||||
|
},
|
||||||
|
AddLogicFocus::ScriptContentPreview => new_focus = AddLogicFocus::SaveButton,
|
||||||
|
AddLogicFocus::SaveButton => new_focus = AddLogicFocus::CancelButton,
|
||||||
|
AddLogicFocus::CancelButton => {
|
||||||
|
// Stay at bottom
|
||||||
|
}
|
||||||
|
_ => handled = false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some("next_option") => {
|
||||||
|
match current_focus {
|
||||||
|
AddLogicFocus::InputLogicName | AddLogicFocus::InputTargetColumn | AddLogicFocus::InputDescription =>
|
||||||
|
{ new_focus = AddLogicFocus::ScriptContentPreview; }
|
||||||
|
AddLogicFocus::ScriptContentPreview => new_focus = AddLogicFocus::SaveButton,
|
||||||
|
AddLogicFocus::SaveButton => new_focus = AddLogicFocus::CancelButton,
|
||||||
|
AddLogicFocus::CancelButton => { /* Stay at last */ }
|
||||||
|
_ => handled = false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some("previous_option") => {
|
||||||
|
match current_focus {
|
||||||
|
AddLogicFocus::InputLogicName | AddLogicFocus::InputTargetColumn | AddLogicFocus::InputDescription =>
|
||||||
|
{ /* Stay at first */ }
|
||||||
|
AddLogicFocus::ScriptContentPreview => new_focus = AddLogicFocus::InputDescription,
|
||||||
|
AddLogicFocus::SaveButton => new_focus = AddLogicFocus::ScriptContentPreview,
|
||||||
|
AddLogicFocus::CancelButton => new_focus = AddLogicFocus::SaveButton,
|
||||||
|
_ => handled = false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some("next_field") => {
|
||||||
|
new_focus = match current_focus {
|
||||||
|
AddLogicFocus::InputLogicName => AddLogicFocus::InputTargetColumn,
|
||||||
|
AddLogicFocus::InputTargetColumn => AddLogicFocus::InputDescription,
|
||||||
|
AddLogicFocus::InputDescription => AddLogicFocus::ScriptContentPreview,
|
||||||
|
AddLogicFocus::ScriptContentPreview => AddLogicFocus::SaveButton,
|
||||||
|
AddLogicFocus::SaveButton => AddLogicFocus::CancelButton,
|
||||||
|
AddLogicFocus::CancelButton => AddLogicFocus::InputLogicName,
|
||||||
|
_ => current_focus,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Some("prev_field") => {
|
||||||
|
new_focus = match current_focus {
|
||||||
|
AddLogicFocus::InputLogicName => AddLogicFocus::CancelButton,
|
||||||
|
AddLogicFocus::InputTargetColumn => AddLogicFocus::InputLogicName,
|
||||||
|
AddLogicFocus::InputDescription => AddLogicFocus::InputTargetColumn,
|
||||||
|
AddLogicFocus::ScriptContentPreview => AddLogicFocus::InputDescription,
|
||||||
|
AddLogicFocus::SaveButton => AddLogicFocus::ScriptContentPreview,
|
||||||
|
AddLogicFocus::CancelButton => AddLogicFocus::SaveButton,
|
||||||
|
_ => current_focus,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Some("select") => {
|
||||||
|
match current_focus {
|
||||||
|
AddLogicFocus::ScriptContentPreview => {
|
||||||
|
new_focus = AddLogicFocus::InsideScriptContent;
|
||||||
|
*is_edit_mode = false; // Start in preview mode
|
||||||
|
app_state.ui.focus_outside_canvas = false; // Script is like canvas
|
||||||
|
let mode_hint = match add_logic_state.editor_keybinding_mode {
|
||||||
|
EditorKeybindingMode::Vim => "VIM mode - 'i'/'a'/'o' to edit",
|
||||||
|
_ => "Enter/Ctrl+E to edit",
|
||||||
|
};
|
||||||
|
*command_message = format!("Fullscreen script editing. {} or Esc to exit.", mode_hint);
|
||||||
|
}
|
||||||
|
AddLogicFocus::SaveButton => {
|
||||||
|
*command_message = "Save logic action".to_string();
|
||||||
|
}
|
||||||
|
AddLogicFocus::CancelButton => {
|
||||||
|
buffer_state.update_history(AppView::Admin);
|
||||||
|
app_state.ui.show_add_logic = false;
|
||||||
|
*command_message = "Cancelled Add Logic".to_string();
|
||||||
|
*is_edit_mode = false;
|
||||||
|
}
|
||||||
|
AddLogicFocus::InputLogicName | AddLogicFocus::InputTargetColumn | AddLogicFocus::InputDescription => {
|
||||||
|
*is_edit_mode = !*is_edit_mode;
|
||||||
|
*command_message = format!("Field edit mode: {}", if *is_edit_mode { "ON" } else { "OFF" });
|
||||||
|
}
|
||||||
|
_ => handled = false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some("toggle_edit_mode") => {
|
||||||
|
match current_focus {
|
||||||
|
AddLogicFocus::InputLogicName | AddLogicFocus::InputTargetColumn | AddLogicFocus::InputDescription => {
|
||||||
|
*is_edit_mode = !*is_edit_mode;
|
||||||
|
*command_message = format!("Canvas field edit mode: {}", if *is_edit_mode { "ON" } else { "OFF" });
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
*command_message = "Cannot toggle edit mode here.".to_string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ => handled = false,
|
||||||
|
}
|
||||||
|
|
||||||
|
if handled && current_focus != new_focus {
|
||||||
|
add_logic_state.current_focus = new_focus;
|
||||||
|
|
||||||
|
// Set edit mode and canvas focus based on new focus
|
||||||
|
let new_is_canvas_input_focus = matches!(new_focus,
|
||||||
|
AddLogicFocus::InputLogicName | AddLogicFocus::InputTargetColumn | AddLogicFocus::InputDescription
|
||||||
|
);
|
||||||
|
|
||||||
|
if new_is_canvas_input_focus {
|
||||||
|
// Entering canvas - start in readonly mode
|
||||||
|
*is_edit_mode = false;
|
||||||
|
app_state.ui.focus_outside_canvas = false;
|
||||||
|
} else {
|
||||||
|
// Outside canvas
|
||||||
|
app_state.ui.focus_outside_canvas = true;
|
||||||
|
if matches!(new_focus, AddLogicFocus::ScriptContentPreview) {
|
||||||
|
*is_edit_mode = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handled
|
handled
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ fn find_prev_word_end(text: &str, current_pos: usize) -> usize {
|
|||||||
pub async fn execute_action(
|
pub async fn execute_action(
|
||||||
action: &str,
|
action: &str,
|
||||||
app_state: &mut AppState,
|
app_state: &mut AppState,
|
||||||
state: &mut AddLogicState, // Changed
|
state: &mut AddLogicState,
|
||||||
ideal_cursor_column: &mut usize,
|
ideal_cursor_column: &mut usize,
|
||||||
key_sequence_tracker: &mut KeySequenceTracker,
|
key_sequence_tracker: &mut KeySequenceTracker,
|
||||||
command_message: &mut String,
|
command_message: &mut String,
|
||||||
@@ -75,7 +75,7 @@ pub async fn execute_action(
|
|||||||
match action {
|
match action {
|
||||||
"move_up" => {
|
"move_up" => {
|
||||||
key_sequence_tracker.reset();
|
key_sequence_tracker.reset();
|
||||||
let num_fields = AddLogicState::INPUT_FIELD_COUNT; // Changed
|
let num_fields = AddLogicState::INPUT_FIELD_COUNT;
|
||||||
if num_fields == 0 { return Ok("No fields.".to_string()); }
|
if num_fields == 0 { return Ok("No fields.".to_string()); }
|
||||||
let current_field = state.current_field();
|
let current_field = state.current_field();
|
||||||
|
|
||||||
@@ -87,20 +87,13 @@ pub async fn execute_action(
|
|||||||
let new_pos = (*ideal_cursor_column).min(max_cursor_pos);
|
let new_pos = (*ideal_cursor_column).min(max_cursor_pos);
|
||||||
state.set_current_cursor_pos(new_pos);
|
state.set_current_cursor_pos(new_pos);
|
||||||
} else {
|
} else {
|
||||||
// Moving up from the first field (InputLogicName)
|
*command_message = "At top of form.".to_string();
|
||||||
app_state.ui.focus_outside_canvas = true;
|
|
||||||
// Focus should go to the element logically above the canvas.
|
|
||||||
// Based on AddLogicFocus, this might be CancelButton or another element.
|
|
||||||
// For AddLogic, let's assume it's CancelButton, similar to AddTable.
|
|
||||||
state.current_focus = crate::state::pages::add_logic::AddLogicFocus::CancelButton; // Changed
|
|
||||||
key_sequence_tracker.reset();
|
|
||||||
return Ok("Focus moved above canvas".to_string());
|
|
||||||
}
|
}
|
||||||
Ok("".to_string())
|
Ok(command_message.clone())
|
||||||
}
|
}
|
||||||
"move_down" => {
|
"move_down" => {
|
||||||
key_sequence_tracker.reset();
|
key_sequence_tracker.reset();
|
||||||
let num_fields = AddLogicState::INPUT_FIELD_COUNT; // Changed
|
let num_fields = AddLogicState::INPUT_FIELD_COUNT;
|
||||||
if num_fields == 0 { return Ok("No fields.".to_string()); }
|
if num_fields == 0 { return Ok("No fields.".to_string()); }
|
||||||
let current_field = state.current_field();
|
let current_field = state.current_field();
|
||||||
let last_field_index = num_fields - 1;
|
let last_field_index = num_fields - 1;
|
||||||
@@ -113,17 +106,13 @@ pub async fn execute_action(
|
|||||||
let new_pos = (*ideal_cursor_column).min(max_cursor_pos);
|
let new_pos = (*ideal_cursor_column).min(max_cursor_pos);
|
||||||
state.set_current_cursor_pos(new_pos);
|
state.set_current_cursor_pos(new_pos);
|
||||||
} else {
|
} else {
|
||||||
// Moving down from the last field (InputDescription)
|
// Move focus outside canvas when moving down from the last field
|
||||||
app_state.ui.focus_outside_canvas = true;
|
app_state.ui.focus_outside_canvas = true;
|
||||||
// Focus should go to the element logically below the canvas.
|
state.last_canvas_field = 2;
|
||||||
// This is likely InputScriptContent or SaveButton.
|
state.current_focus = crate::state::pages::add_logic::AddLogicFocus::SaveButton;
|
||||||
// The add_logic_nav.rs handles transitions to InputScriptContent.
|
*command_message = "Focus moved below canvas".to_string();
|
||||||
// If moving from canvas directly to buttons, it would be SaveButton.
|
|
||||||
state.current_focus = crate::state::pages::add_logic::AddLogicFocus::InputScriptContent; // Or SaveButton
|
|
||||||
key_sequence_tracker.reset();
|
|
||||||
return Ok("Focus moved to script/button area".to_string());
|
|
||||||
}
|
}
|
||||||
Ok("".to_string())
|
Ok(command_message.clone())
|
||||||
}
|
}
|
||||||
"move_first_line" => {
|
"move_first_line" => {
|
||||||
key_sequence_tracker.reset();
|
key_sequence_tracker.reset();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// src/state/pages/add_logic.rs
|
// src/state/pages/add_logic.rs
|
||||||
use crate::config::binds::config::{EditorConfig, EditorKeybindingMode};
|
use crate::config::binds::config::{EditorConfig, EditorKeybindingMode};
|
||||||
use crate::state::pages::canvas_state::CanvasState;
|
use crate::state::pages::canvas_state::CanvasState;
|
||||||
use crate::components::common::text_editor::{TextEditor, VimState}; // Add VimState import
|
use crate::components::common::text_editor::{TextEditor, VimState};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use tui_textarea::TextArea;
|
use tui_textarea::TextArea;
|
||||||
@@ -11,8 +11,9 @@ pub enum AddLogicFocus {
|
|||||||
#[default]
|
#[default]
|
||||||
InputLogicName,
|
InputLogicName,
|
||||||
InputTargetColumn,
|
InputTargetColumn,
|
||||||
InputScriptContent,
|
|
||||||
InputDescription,
|
InputDescription,
|
||||||
|
ScriptContentPreview, // Like ColumnsTable - can be highlighted/selected
|
||||||
|
InsideScriptContent, // Like InsideColumnsTable - full editing mode
|
||||||
SaveButton,
|
SaveButton,
|
||||||
CancelButton,
|
CancelButton,
|
||||||
}
|
}
|
||||||
@@ -27,12 +28,13 @@ pub struct AddLogicState {
|
|||||||
pub script_content_editor: Rc<RefCell<TextArea<'static>>>,
|
pub script_content_editor: Rc<RefCell<TextArea<'static>>>,
|
||||||
pub description_input: String,
|
pub description_input: String,
|
||||||
pub current_focus: AddLogicFocus,
|
pub current_focus: AddLogicFocus,
|
||||||
|
pub last_canvas_field: usize,
|
||||||
pub logic_name_cursor_pos: usize,
|
pub logic_name_cursor_pos: usize,
|
||||||
pub target_column_cursor_pos: usize,
|
pub target_column_cursor_pos: usize,
|
||||||
pub description_cursor_pos: usize,
|
pub description_cursor_pos: usize,
|
||||||
pub has_unsaved_changes: bool,
|
pub has_unsaved_changes: bool,
|
||||||
pub editor_keybinding_mode: EditorKeybindingMode,
|
pub editor_keybinding_mode: EditorKeybindingMode,
|
||||||
pub vim_state: VimState, // Add this field
|
pub vim_state: VimState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddLogicState {
|
impl AddLogicState {
|
||||||
@@ -47,12 +49,13 @@ impl AddLogicState {
|
|||||||
script_content_editor: Rc::new(RefCell::new(editor)),
|
script_content_editor: Rc::new(RefCell::new(editor)),
|
||||||
description_input: String::new(),
|
description_input: String::new(),
|
||||||
current_focus: AddLogicFocus::InputLogicName,
|
current_focus: AddLogicFocus::InputLogicName,
|
||||||
|
last_canvas_field: 2,
|
||||||
logic_name_cursor_pos: 0,
|
logic_name_cursor_pos: 0,
|
||||||
target_column_cursor_pos: 0,
|
target_column_cursor_pos: 0,
|
||||||
description_cursor_pos: 0,
|
description_cursor_pos: 0,
|
||||||
has_unsaved_changes: false,
|
has_unsaved_changes: false,
|
||||||
editor_keybinding_mode: editor_config.keybinding_mode.clone(),
|
editor_keybinding_mode: editor_config.keybinding_mode.clone(),
|
||||||
vim_state: VimState::default(), // Add this field initialization
|
vim_state: VimState::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,14 +68,13 @@ impl Default for AddLogicState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ... rest of the CanvasState implementation remains the same
|
|
||||||
impl CanvasState for AddLogicState {
|
impl CanvasState for AddLogicState {
|
||||||
fn current_field(&self) -> usize {
|
fn current_field(&self) -> usize {
|
||||||
match self.current_focus {
|
match self.current_focus {
|
||||||
AddLogicFocus::InputLogicName => 0,
|
AddLogicFocus::InputLogicName => 0,
|
||||||
AddLogicFocus::InputTargetColumn => 1,
|
AddLogicFocus::InputTargetColumn => 1,
|
||||||
AddLogicFocus::InputDescription => 2,
|
AddLogicFocus::InputDescription => 2,
|
||||||
_ => 0,
|
_ => self.last_canvas_field,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,9 +123,18 @@ impl CanvasState for AddLogicState {
|
|||||||
|
|
||||||
fn set_current_field(&mut self, index: usize) {
|
fn set_current_field(&mut self, index: usize) {
|
||||||
self.current_focus = match index {
|
self.current_focus = match index {
|
||||||
0 => AddLogicFocus::InputLogicName,
|
0 => {
|
||||||
1 => AddLogicFocus::InputTargetColumn,
|
self.last_canvas_field = 0;
|
||||||
2 => AddLogicFocus::InputDescription,
|
AddLogicFocus::InputLogicName
|
||||||
|
},
|
||||||
|
1 => {
|
||||||
|
self.last_canvas_field = 1;
|
||||||
|
AddLogicFocus::InputTargetColumn
|
||||||
|
},
|
||||||
|
2 => {
|
||||||
|
self.last_canvas_field = 2;
|
||||||
|
AddLogicFocus::InputDescription
|
||||||
|
},
|
||||||
_ => self.current_focus,
|
_ => self.current_focus,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user