340 lines
13 KiB
Rust
340 lines
13 KiB
Rust
// src/modes/canvas/read_only.rs
|
|
|
|
use crate::config::binds::config::Config;
|
|
use crate::config::binds::key_sequences::KeySequenceTracker;
|
|
use crate::services::grpc_client::GrpcClient;
|
|
use crate::state::pages::auth::LoginState;
|
|
use crate::state::pages::auth::RegisterState;
|
|
use crate::state::pages::form::FormState;
|
|
use crate::state::pages::add_logic::AddLogicState;
|
|
use crate::state::pages::add_table::AddTableState;
|
|
use crate::state::app::state::AppState;
|
|
use crate::functions::modes::read_only::{add_logic_ro, add_table_ro};
|
|
use canvas::{canvas::{CanvasAction, CanvasState, ActionResult}, dispatcher::ActionDispatcher};
|
|
use crossterm::event::KeyEvent;
|
|
use anyhow::Result;
|
|
|
|
pub async fn handle_form_readonly_with_canvas(
|
|
key_event: KeyEvent,
|
|
config: &Config,
|
|
form_state: &mut FormState,
|
|
ideal_cursor_column: &mut usize,
|
|
) -> Result<String> {
|
|
// Try canvas action from key first
|
|
if let Some(canvas_action) = CanvasAction::from_key(key_event.code) {
|
|
match ActionDispatcher::dispatch(canvas_action, form_state, ideal_cursor_column).await {
|
|
Ok(ActionResult::Success(msg)) => {
|
|
return Ok(msg.unwrap_or_default());
|
|
}
|
|
Ok(ActionResult::HandledByFeature(msg)) => {
|
|
return Ok(msg);
|
|
}
|
|
Ok(ActionResult::Error(msg)) => {
|
|
return Ok(format!("Error: {}", msg));
|
|
}
|
|
Ok(ActionResult::RequiresContext(msg)) => {
|
|
return Ok(format!("Context needed: {}", msg));
|
|
}
|
|
Err(_) => {
|
|
// Fall through to try config mapping
|
|
}
|
|
}
|
|
}
|
|
|
|
// Try config-mapped action
|
|
if let Some(action_str) = config.get_read_only_action_for_key(key_event.code, key_event.modifiers) {
|
|
let canvas_action = CanvasAction::from_string(&action_str);
|
|
match ActionDispatcher::dispatch(canvas_action, form_state, ideal_cursor_column).await {
|
|
Ok(ActionResult::Success(msg)) => {
|
|
return Ok(msg.unwrap_or_default());
|
|
}
|
|
Ok(ActionResult::HandledByFeature(msg)) => {
|
|
return Ok(msg);
|
|
}
|
|
Ok(ActionResult::Error(msg)) => {
|
|
return Ok(format!("Error: {}", msg));
|
|
}
|
|
Ok(ActionResult::RequiresContext(msg)) => {
|
|
return Ok(format!("Context needed: {}", msg));
|
|
}
|
|
Err(e) => {
|
|
return Ok(format!("Action failed: {}", e));
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(String::new())
|
|
}
|
|
|
|
pub async fn handle_read_only_event(
|
|
app_state: &mut AppState,
|
|
key: KeyEvent,
|
|
config: &Config,
|
|
form_state: &mut FormState,
|
|
login_state: &mut LoginState,
|
|
register_state: &mut RegisterState,
|
|
add_table_state: &mut AddTableState,
|
|
add_logic_state: &mut AddLogicState,
|
|
key_sequence_tracker: &mut KeySequenceTracker,
|
|
grpc_client: &mut GrpcClient,
|
|
command_message: &mut String,
|
|
edit_mode_cooldown: &mut bool,
|
|
ideal_cursor_column: &mut usize,
|
|
) -> Result<(bool, String)> {
|
|
if config.is_enter_edit_mode_before(key.code, key.modifiers) {
|
|
*edit_mode_cooldown = true;
|
|
*command_message = "Entering Edit mode".to_string();
|
|
return Ok((false, command_message.clone()));
|
|
}
|
|
|
|
if config.is_enter_edit_mode_after(key.code, key.modifiers) {
|
|
// Determine target state to adjust cursor
|
|
|
|
if app_state.ui.show_login {
|
|
let current_input = login_state.get_current_input();
|
|
let current_pos = login_state.current_cursor_pos();
|
|
if !current_input.is_empty() && current_pos < current_input.len() {
|
|
login_state.set_current_cursor_pos(current_pos + 1);
|
|
*ideal_cursor_column = login_state.current_cursor_pos();
|
|
}
|
|
} else if app_state.ui.show_add_logic {
|
|
let current_input = add_logic_state.get_current_input();
|
|
let current_pos = add_logic_state.current_cursor_pos();
|
|
if !current_input.is_empty() && current_pos < current_input.len() {
|
|
add_logic_state.set_current_cursor_pos(current_pos + 1);
|
|
*ideal_cursor_column = add_logic_state.current_cursor_pos();
|
|
}
|
|
} else if app_state.ui.show_register {
|
|
let current_input = register_state.get_current_input();
|
|
let current_pos = register_state.current_cursor_pos();
|
|
if !current_input.is_empty() && current_pos < current_input.len() {
|
|
register_state.set_current_cursor_pos(current_pos + 1);
|
|
*ideal_cursor_column = register_state.current_cursor_pos();
|
|
}
|
|
} else if app_state.ui.show_add_table {
|
|
let current_input = add_table_state.get_current_input();
|
|
let current_pos = add_table_state.current_cursor_pos();
|
|
if !current_input.is_empty() && current_pos < current_input.len() {
|
|
add_table_state.set_current_cursor_pos(current_pos + 1);
|
|
*ideal_cursor_column = add_table_state.current_cursor_pos();
|
|
}
|
|
} else {
|
|
// Handle FormState (uses library CanvasState)
|
|
use canvas::canvas::CanvasState as LibraryCanvasState; // Import at the top of the function
|
|
let current_input = form_state.get_current_input();
|
|
let current_pos = form_state.current_cursor_pos();
|
|
if !current_input.is_empty() && current_pos < current_input.len() {
|
|
form_state.set_current_cursor_pos(current_pos + 1);
|
|
*ideal_cursor_column = form_state.current_cursor_pos();
|
|
}
|
|
}
|
|
|
|
*edit_mode_cooldown = true;
|
|
*command_message = "Entering Edit mode (after cursor)".to_string();
|
|
return Ok((false, command_message.clone()));
|
|
}
|
|
|
|
const CONTEXT_ACTIONS_FORM: &[&str] = &[
|
|
"previous_entry",
|
|
"next_entry",
|
|
];
|
|
const CONTEXT_ACTIONS_LOGIN: &[&str] = &[
|
|
"previous_entry",
|
|
"next_entry",
|
|
];
|
|
|
|
if key.modifiers.is_empty() {
|
|
key_sequence_tracker.add_key(key.code);
|
|
let sequence = key_sequence_tracker.get_sequence();
|
|
|
|
if let Some(action) = config.matches_key_sequence_generalized(&sequence).as_deref() {
|
|
let result = if app_state.ui.show_form && CONTEXT_ACTIONS_FORM.contains(&action) {
|
|
crate::tui::functions::form::handle_action(
|
|
action,
|
|
form_state,
|
|
grpc_client,
|
|
ideal_cursor_column,
|
|
)
|
|
.await?
|
|
} else if app_state.ui.show_login && CONTEXT_ACTIONS_LOGIN.contains(&action) {
|
|
crate::tui::functions::login::handle_action(action).await?
|
|
} else if app_state.ui.show_add_table {
|
|
add_table_ro::execute_action(
|
|
action,
|
|
app_state,
|
|
add_table_state,
|
|
ideal_cursor_column,
|
|
key_sequence_tracker,
|
|
command_message,
|
|
).await?
|
|
} else if app_state.ui.show_add_logic {
|
|
add_logic_ro::execute_action(
|
|
action,
|
|
app_state,
|
|
add_logic_state,
|
|
ideal_cursor_column,
|
|
key_sequence_tracker,
|
|
command_message,
|
|
).await?
|
|
} else if app_state.ui.show_register{
|
|
auth_ro::execute_action(
|
|
action,
|
|
app_state,
|
|
register_state,
|
|
ideal_cursor_column,
|
|
key_sequence_tracker,
|
|
command_message,
|
|
).await?
|
|
} else if app_state.ui.show_login {
|
|
auth_ro::execute_action(
|
|
action,
|
|
app_state,
|
|
login_state,
|
|
ideal_cursor_column,
|
|
key_sequence_tracker,
|
|
command_message,
|
|
)
|
|
.await?
|
|
} else {
|
|
String::new()
|
|
};
|
|
key_sequence_tracker.reset();
|
|
return Ok((false, result));
|
|
}
|
|
|
|
if config.is_key_sequence_prefix(&sequence) {
|
|
return Ok((false, command_message.clone()));
|
|
}
|
|
|
|
if sequence.len() == 1 && !config.is_key_sequence_prefix(&sequence) {
|
|
if let Some(action) = config.get_read_only_action_for_key(key.code, key.modifiers).as_deref() {
|
|
let result = if app_state.ui.show_form && CONTEXT_ACTIONS_FORM.contains(&action) {
|
|
crate::tui::functions::form::handle_action(
|
|
action,
|
|
form_state,
|
|
grpc_client,
|
|
ideal_cursor_column,
|
|
)
|
|
.await?
|
|
} else if app_state.ui.show_login && CONTEXT_ACTIONS_LOGIN.contains(&action) {
|
|
crate::tui::functions::login::handle_action(action).await?
|
|
} else if app_state.ui.show_add_table {
|
|
add_table_ro::execute_action(
|
|
action,
|
|
app_state,
|
|
add_table_state,
|
|
ideal_cursor_column,
|
|
key_sequence_tracker,
|
|
command_message,
|
|
).await?
|
|
} else if app_state.ui.show_add_logic {
|
|
add_logic_ro::execute_action(
|
|
action,
|
|
app_state,
|
|
add_logic_state,
|
|
ideal_cursor_column,
|
|
key_sequence_tracker,
|
|
command_message,
|
|
).await?
|
|
} else if app_state.ui.show_register {
|
|
auth_ro::execute_action(
|
|
action,
|
|
app_state,
|
|
register_state,
|
|
ideal_cursor_column,
|
|
key_sequence_tracker,
|
|
command_message,
|
|
).await?
|
|
} else if app_state.ui.show_login {
|
|
auth_ro::execute_action(
|
|
action,
|
|
app_state,
|
|
login_state,
|
|
ideal_cursor_column,
|
|
key_sequence_tracker,
|
|
command_message,
|
|
)
|
|
.await?
|
|
} else {
|
|
String::new()
|
|
};
|
|
key_sequence_tracker.reset();
|
|
return Ok((false, result));
|
|
}
|
|
}
|
|
key_sequence_tracker.reset();
|
|
} else {
|
|
key_sequence_tracker.reset();
|
|
|
|
if let Some(action) = config.get_read_only_action_for_key(key.code, key.modifiers).as_deref() {
|
|
let result = if app_state.ui.show_form && CONTEXT_ACTIONS_FORM.contains(&action) {
|
|
crate::tui::functions::form::handle_action(
|
|
action,
|
|
form_state,
|
|
grpc_client,
|
|
ideal_cursor_column,
|
|
)
|
|
.await?
|
|
} else if app_state.ui.show_login && CONTEXT_ACTIONS_LOGIN.contains(&action) {
|
|
crate::tui::functions::login::handle_action(action).await?
|
|
} else if app_state.ui.show_add_table {
|
|
add_table_ro::execute_action(
|
|
action,
|
|
app_state,
|
|
add_table_state,
|
|
ideal_cursor_column,
|
|
key_sequence_tracker,
|
|
command_message,
|
|
).await?
|
|
} else if app_state.ui.show_add_logic {
|
|
add_logic_ro::execute_action(
|
|
action,
|
|
app_state,
|
|
add_logic_state,
|
|
ideal_cursor_column,
|
|
key_sequence_tracker,
|
|
command_message,
|
|
).await?
|
|
} else if app_state.ui.show_register {
|
|
auth_ro::execute_action(
|
|
action,
|
|
app_state,
|
|
register_state,
|
|
ideal_cursor_column,
|
|
key_sequence_tracker,
|
|
command_message,
|
|
).await?
|
|
} else if app_state.ui.show_login {
|
|
auth_ro::execute_action(
|
|
action,
|
|
app_state,
|
|
login_state,
|
|
ideal_cursor_column,
|
|
key_sequence_tracker,
|
|
command_message,
|
|
)
|
|
.await?
|
|
} else {
|
|
String::new()
|
|
};
|
|
return Ok((false, result));
|
|
}
|
|
}
|
|
|
|
if !*edit_mode_cooldown {
|
|
let default_key = "i".to_string();
|
|
let edit_key = config
|
|
.keybindings
|
|
.read_only
|
|
.get("enter_edit_mode_before")
|
|
.and_then(|keys| keys.first())
|
|
.map(|k| k.to_string())
|
|
.unwrap_or(default_key);
|
|
*command_message = format!("Read-only mode - press {} to edit", edit_key);
|
|
}
|
|
|
|
*edit_mode_cooldown = false;
|
|
|
|
Ok((false, command_message.clone()))
|
|
}
|