add logic is now using canvas library now

This commit is contained in:
filipriec
2025-08-30 21:10:10 +02:00
parent c7d524c76a
commit 4edec5e72d
9 changed files with 426 additions and 600 deletions

View File

@@ -0,0 +1,199 @@
// src/pages/admin_panel/add_logic/event.rs
use anyhow::Result;
use crossterm::event::{Event, KeyCode, KeyModifiers};
use crate::config::binds::config::Config;
use crate::modes::handlers::event::EventOutcome;
use crate::pages::admin_panel::add_logic::state::{AddLogicFormState, AddLogicFocus};
use crate::components::common::text_editor::TextEditor;
use crate::services::grpc_client::GrpcClient;
use crate::pages::admin_panel::add_logic::nav::SaveLogicResultSender; // keep type alias
use crate::state::app::state::AppState;
use canvas::DataProvider;
pub fn handle_add_logic_event(
event: Event,
config: &Config,
app_state: &mut AppState,
add_logic_page: &mut AddLogicFormState,
grpc_client: GrpcClient,
save_logic_sender: SaveLogicResultSender,
) -> Result<EventOutcome> {
if let Event::Key(key_event) = event {
let st = &mut add_logic_page.state;
let key_code = key_event.code;
let modifiers = key_event.modifiers;
// 1) Fullscreen Script Editor mode
if st.current_focus == AddLogicFocus::InsideScriptContent {
match key_code {
KeyCode::Esc if modifiers == KeyModifiers::NONE => {
st.current_focus = AddLogicFocus::ScriptContentPreview;
app_state.ui.focus_outside_canvas = true;
return Ok(EventOutcome::Ok("Exited script editing.".into()));
}
_ => {
let changed = {
let mut editor_borrow = st.script_content_editor.borrow_mut();
TextEditor::handle_input(
&mut editor_borrow,
key_event,
&st.editor_keybinding_mode,
&mut st.vim_state,
)
};
if changed {
st.has_unsaved_changes = true;
return Ok(EventOutcome::Ok("Script updated".into()));
} else {
return Ok(EventOutcome::Ok(String::new()));
}
}
}
}
// 2) Canvas inputs (three fields) forward to FormEditor
let inside_canvas_inputs = matches!(
st.current_focus,
AddLogicFocus::InputLogicName
| AddLogicFocus::InputTargetColumn
| AddLogicFocus::InputDescription
);
if inside_canvas_inputs {
// Handoff from last field to Script Preview on "down"/"next"
let last_idx = add_logic_page
.editor
.data_provider()
.field_count()
.saturating_sub(1);
let at_last = add_logic_page.editor.current_field() >= last_idx;
// Map to generic "down/next" via config or raw keys
let action_opt = config.get_general_action(key_code, modifiers);
let is_down_or_next = matches!(
action_opt,
Some("down") | Some("next") | Some("move_down") | Some("next_field")
)
|| matches!(key_code, KeyCode::Down)
|| matches!(key_code, KeyCode::Char('j') if modifiers.is_empty());
if at_last && is_down_or_next {
st.last_canvas_field = last_idx;
st.current_focus = AddLogicFocus::ScriptContentPreview;
add_logic_page.focus_outside_canvas = true;
app_state.ui.focus_outside_canvas = true;
return Ok(EventOutcome::Ok(
"Moved to Script Preview".to_string(),
));
}
// Normal canvas input
match add_logic_page.editor.handle_key_event(key_event) {
canvas::keymap::KeyEventOutcome::Consumed(Some(msg)) => {
add_logic_page.sync_from_editor();
return Ok(EventOutcome::Ok(msg));
}
canvas::keymap::KeyEventOutcome::Consumed(None) => {
add_logic_page.sync_from_editor();
return Ok(EventOutcome::Ok("Input updated".into()));
}
canvas::keymap::KeyEventOutcome::Pending => {
return Ok(EventOutcome::Ok(String::new()));
}
canvas::keymap::KeyEventOutcome::NotMatched => {
// fall through to outside handling
}
}
}
// 3) Outside-canvas focus (Script Preview, Save, Cancel)
let action_opt = config.get_general_action(key_code, modifiers);
match action_opt {
Some("up") | Some("move_up") | Some("previous") | Some("previous_option") | Some("prev_field") => {
match st.current_focus {
AddLogicFocus::ScriptContentPreview => {
st.current_focus = AddLogicFocus::InputDescription;
add_logic_page.focus_outside_canvas = false;
app_state.ui.focus_outside_canvas = false;
return Ok(EventOutcome::Ok(
"Back to Description".to_string(),
));
}
AddLogicFocus::SaveButton => {
st.current_focus = AddLogicFocus::ScriptContentPreview;
return Ok(EventOutcome::Ok(
"Back to Script Preview".to_string(),
));
}
AddLogicFocus::CancelButton => {
st.current_focus = AddLogicFocus::SaveButton;
return Ok(EventOutcome::Ok("Back to Save".to_string()));
}
_ => {}
}
}
Some("down") | Some("move_down") | Some("next") | Some("next_option") | Some("next_field") => {
match st.current_focus {
AddLogicFocus::ScriptContentPreview => {
st.current_focus = AddLogicFocus::SaveButton;
return Ok(EventOutcome::Ok("Focus: Save".to_string()));
}
AddLogicFocus::SaveButton => {
st.current_focus = AddLogicFocus::CancelButton;
return Ok(EventOutcome::Ok("Focus: Cancel".to_string()));
}
_ => {}
}
}
Some("select") => {
match st.current_focus {
AddLogicFocus::ScriptContentPreview => {
st.current_focus = AddLogicFocus::InsideScriptContent;
add_logic_page.focus_outside_canvas = false;
app_state.ui.focus_outside_canvas = false;
return Ok(EventOutcome::Ok(
"Fullscreen script editing. Esc to exit.".into(),
));
}
AddLogicFocus::SaveButton => {
if let Some(msg) = st.save_logic() {
return Ok(EventOutcome::Ok(msg));
}
return Ok(EventOutcome::Ok(
"Saved (no changes)".to_string(),
));
}
AddLogicFocus::CancelButton => {
// Keep this simple: you can wire buffer/view navigation where needed
return Ok(EventOutcome::Ok(
"Cancelled Add Logic".to_string(),
));
}
AddLogicFocus::InputLogicName
| AddLogicFocus::InputTargetColumn
| AddLogicFocus::InputDescription => {
add_logic_page.focus_outside_canvas = false;
app_state.ui.focus_outside_canvas = false;
return Ok(EventOutcome::Ok(String::new()));
}
_ => {}
}
}
Some("esc") => {
if st.current_focus == AddLogicFocus::ScriptContentPreview {
// Go back to Description (last canvas field)
st.current_focus = AddLogicFocus::InputDescription;
add_logic_page.focus_outside_canvas = false;
app_state.ui.focus_outside_canvas = false;
return Ok(EventOutcome::Ok(
"Back to Description".to_string(),
));
}
}
_ => {}
}
}
Ok(EventOutcome::Ok(String::new()))
}