Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1b3cf6136 | ||
|
|
173c4c98b8 | ||
|
|
5a3067c8e5 | ||
|
|
803c748738 | ||
|
|
5879b40e8c |
@@ -27,13 +27,16 @@ pub fn render_canvas(
|
|||||||
.split(area);
|
.split(area);
|
||||||
|
|
||||||
// Input container styling
|
// Input container styling
|
||||||
|
let border_style = if form_state.has_unsaved_changes() {
|
||||||
|
Style::default().fg(theme.warning)
|
||||||
|
} else if is_edit_mode {
|
||||||
|
Style::default().fg(theme.accent)
|
||||||
|
} else {
|
||||||
|
Style::default().fg(theme.secondary)
|
||||||
|
};
|
||||||
let input_container = Block::default()
|
let input_container = Block::default()
|
||||||
.borders(Borders::ALL)
|
.borders(Borders::ALL)
|
||||||
.border_style(if is_edit_mode {
|
.border_style(border_style)
|
||||||
form_state.has_unsaved_changes().then(|| theme.warning).unwrap_or(theme.accent)
|
|
||||||
} else {
|
|
||||||
theme.secondary
|
|
||||||
})
|
|
||||||
.style(Style::default().bg(theme.bg));
|
.style(Style::default().bg(theme.bg));
|
||||||
|
|
||||||
// Input block dimensions
|
// Input block dimensions
|
||||||
|
|||||||
@@ -173,11 +173,7 @@ pub async fn execute_edit_action<S: CanvasState>(
|
|||||||
let num_fields = state.fields().len();
|
let num_fields = state.fields().len();
|
||||||
if num_fields > 0 {
|
if num_fields > 0 {
|
||||||
let current_field = state.current_field();
|
let current_field = state.current_field();
|
||||||
let new_field = if current_field == 0 {
|
let new_field = current_field.saturating_sub(1);
|
||||||
num_fields - 1
|
|
||||||
} else {
|
|
||||||
current_field - 1
|
|
||||||
};
|
|
||||||
state.set_current_field(new_field);
|
state.set_current_field(new_field);
|
||||||
let current_input = state.get_current_input();
|
let current_input = state.get_current_input();
|
||||||
let max_pos = current_input.len();
|
let max_pos = current_input.len();
|
||||||
@@ -191,7 +187,7 @@ pub async fn execute_edit_action<S: CanvasState>(
|
|||||||
"move_down" => {
|
"move_down" => {
|
||||||
let num_fields = state.fields().len();
|
let num_fields = state.fields().len();
|
||||||
if num_fields > 0 {
|
if num_fields > 0 {
|
||||||
let new_field = (state.current_field() + 1) % num_fields;
|
let new_field = (state.current_field() + 1).min(num_fields - 1);
|
||||||
state.set_current_field(new_field);
|
state.set_current_field(new_field);
|
||||||
let current_input = state.get_current_input();
|
let current_input = state.get_current_input();
|
||||||
let max_pos = current_input.len();
|
let max_pos = current_input.len();
|
||||||
|
|||||||
@@ -173,11 +173,7 @@ pub async fn execute_edit_action<S: CanvasState>(
|
|||||||
let num_fields = state.fields().len();
|
let num_fields = state.fields().len();
|
||||||
if num_fields > 0 {
|
if num_fields > 0 {
|
||||||
let current_field = state.current_field();
|
let current_field = state.current_field();
|
||||||
let new_field = if current_field == 0 {
|
let new_field = current_field.saturating_sub(1);
|
||||||
num_fields - 1
|
|
||||||
} else {
|
|
||||||
current_field - 1
|
|
||||||
};
|
|
||||||
state.set_current_field(new_field);
|
state.set_current_field(new_field);
|
||||||
let current_input = state.get_current_input();
|
let current_input = state.get_current_input();
|
||||||
let max_pos = current_input.len();
|
let max_pos = current_input.len();
|
||||||
@@ -191,7 +187,7 @@ pub async fn execute_edit_action<S: CanvasState>(
|
|||||||
"move_down" => {
|
"move_down" => {
|
||||||
let num_fields = state.fields().len();
|
let num_fields = state.fields().len();
|
||||||
if num_fields > 0 {
|
if num_fields > 0 {
|
||||||
let new_field = (state.current_field() + 1) % num_fields;
|
let new_field = (state.current_field() + 1).min(num_fields - 1);
|
||||||
state.set_current_field(new_field);
|
state.set_current_field(new_field);
|
||||||
let current_input = state.get_current_input();
|
let current_input = state.get_current_input();
|
||||||
let max_pos = current_input.len();
|
let max_pos = current_input.len();
|
||||||
|
|||||||
@@ -33,11 +33,7 @@ pub async fn execute_action<S: CanvasState>(
|
|||||||
return Ok("No fields to navigate.".to_string());
|
return Ok("No fields to navigate.".to_string());
|
||||||
}
|
}
|
||||||
let current_field = state.current_field();
|
let current_field = state.current_field();
|
||||||
let new_field = if current_field == 0 {
|
let new_field = current_field.saturating_sub(1);
|
||||||
num_fields - 1
|
|
||||||
} else {
|
|
||||||
current_field - 1
|
|
||||||
};
|
|
||||||
state.set_current_field(new_field);
|
state.set_current_field(new_field);
|
||||||
let current_input = state.get_current_input();
|
let current_input = state.get_current_input();
|
||||||
let max_cursor_pos = if current_input.is_empty() {
|
let max_cursor_pos = if current_input.is_empty() {
|
||||||
@@ -57,7 +53,7 @@ pub async fn execute_action<S: CanvasState>(
|
|||||||
return Ok("No fields to navigate.".to_string());
|
return Ok("No fields to navigate.".to_string());
|
||||||
}
|
}
|
||||||
let current_field = state.current_field();
|
let current_field = state.current_field();
|
||||||
let new_field = (current_field + 1) % num_fields;
|
let new_field = (state.current_field() + 1).min(num_fields - 1);
|
||||||
state.set_current_field(new_field);
|
state.set_current_field(new_field);
|
||||||
let current_input = state.get_current_input();
|
let current_input = state.get_current_input();
|
||||||
let max_cursor_pos = if current_input.is_empty() {
|
let max_cursor_pos = if current_input.is_empty() {
|
||||||
|
|||||||
@@ -33,11 +33,7 @@ pub async fn execute_action<S: CanvasState>(
|
|||||||
return Ok("No fields to navigate.".to_string());
|
return Ok("No fields to navigate.".to_string());
|
||||||
}
|
}
|
||||||
let current_field = state.current_field();
|
let current_field = state.current_field();
|
||||||
let new_field = if current_field == 0 {
|
let new_field = current_field.saturating_sub(1);
|
||||||
num_fields - 1
|
|
||||||
} else {
|
|
||||||
current_field - 1
|
|
||||||
};
|
|
||||||
state.set_current_field(new_field);
|
state.set_current_field(new_field);
|
||||||
let current_input = state.get_current_input();
|
let current_input = state.get_current_input();
|
||||||
let max_cursor_pos = if current_input.is_empty() {
|
let max_cursor_pos = if current_input.is_empty() {
|
||||||
@@ -56,7 +52,7 @@ pub async fn execute_action<S: CanvasState>(
|
|||||||
return Ok("No fields to navigate.".to_string());
|
return Ok("No fields to navigate.".to_string());
|
||||||
}
|
}
|
||||||
let current_field = state.current_field();
|
let current_field = state.current_field();
|
||||||
let new_field = (current_field + 1) % num_fields;
|
let new_field = (current_field + 1).min(num_fields - 1);
|
||||||
state.set_current_field(new_field);
|
state.set_current_field(new_field);
|
||||||
let current_input = state.get_current_input();
|
let current_input = state.get_current_input();
|
||||||
let max_cursor_pos = if current_input.is_empty() {
|
let max_cursor_pos = if current_input.is_empty() {
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
// src/modes/handlers/event.rs
|
// src/modes/handlers/event.rs
|
||||||
use crossterm::event::Event;
|
use crossterm::event::Event;
|
||||||
use crossterm::cursor::SetCursorStyle;
|
use crossterm::cursor::SetCursorStyle;
|
||||||
use crate::tui::terminal::{
|
use crate::tui::terminal::core::TerminalCore;
|
||||||
core::TerminalCore,
|
|
||||||
};
|
|
||||||
use crate::services::grpc_client::GrpcClient;
|
use crate::services::grpc_client::GrpcClient;
|
||||||
use crate::services::auth::AuthClient;
|
use crate::services::auth::AuthClient;
|
||||||
use crate::modes::common::commands::CommandHandler;
|
use crate::modes::common::commands::CommandHandler;
|
||||||
@@ -13,7 +11,7 @@ use crate::state::pages::auth::AuthState;
|
|||||||
use crate::state::canvas_state::CanvasState;
|
use crate::state::canvas_state::CanvasState;
|
||||||
use crate::ui::handlers::rat_state::UiStateHandler;
|
use crate::ui::handlers::rat_state::UiStateHandler;
|
||||||
use crate::modes::{
|
use crate::modes::{
|
||||||
common::{command_mode},
|
common::command_mode,
|
||||||
canvas::{edit, read_only, common_mode},
|
canvas::{edit, read_only, common_mode},
|
||||||
general::navigation,
|
general::navigation,
|
||||||
};
|
};
|
||||||
@@ -28,7 +26,6 @@ pub struct EventHandler {
|
|||||||
pub edit_mode_cooldown: bool,
|
pub edit_mode_cooldown: bool,
|
||||||
pub ideal_cursor_column: usize,
|
pub ideal_cursor_column: usize,
|
||||||
pub key_sequence_tracker: KeySequenceTracker,
|
pub key_sequence_tracker: KeySequenceTracker,
|
||||||
// pub auth_state: AuthState, // Removed
|
|
||||||
pub auth_client: AuthClient,
|
pub auth_client: AuthClient,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +39,6 @@ impl EventHandler {
|
|||||||
edit_mode_cooldown: false,
|
edit_mode_cooldown: false,
|
||||||
ideal_cursor_column: 0,
|
ideal_cursor_column: 0,
|
||||||
key_sequence_tracker: KeySequenceTracker::new(800),
|
key_sequence_tracker: KeySequenceTracker::new(800),
|
||||||
// auth_state: AuthState::new(), // Removed
|
|
||||||
auth_client: AuthClient::new().await?,
|
auth_client: AuthClient::new().await?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -55,12 +51,11 @@ impl EventHandler {
|
|||||||
grpc_client: &mut GrpcClient,
|
grpc_client: &mut GrpcClient,
|
||||||
command_handler: &mut CommandHandler,
|
command_handler: &mut CommandHandler,
|
||||||
form_state: &mut FormState,
|
form_state: &mut FormState,
|
||||||
auth_state: &mut AuthState, // Added
|
auth_state: &mut AuthState,
|
||||||
app_state: &mut crate::state::state::AppState,
|
app_state: &mut crate::state::state::AppState,
|
||||||
total_count: u64,
|
total_count: u64,
|
||||||
current_position: &mut u64,
|
current_position: &mut u64,
|
||||||
) -> Result<(bool, String), Box<dyn std::error::Error>> {
|
) -> Result<(bool, String), Box<dyn std::error::Error>> {
|
||||||
// Determine current mode based on app state and event handler state
|
|
||||||
let current_mode = ModeManager::derive_mode(app_state, self);
|
let current_mode = ModeManager::derive_mode(app_state, self);
|
||||||
app_state.update_mode(current_mode);
|
app_state.update_mode(current_mode);
|
||||||
|
|
||||||
@@ -68,14 +63,12 @@ impl EventHandler {
|
|||||||
let key_code = key.code;
|
let key_code = key.code;
|
||||||
let modifiers = key.modifiers;
|
let modifiers = key.modifiers;
|
||||||
|
|
||||||
// Handle common actions across all modes
|
|
||||||
if UiStateHandler::toggle_sidebar(&mut app_state.ui, config, key_code, modifiers) {
|
if UiStateHandler::toggle_sidebar(&mut app_state.ui, config, key_code, modifiers) {
|
||||||
return Ok((false, format!("Sidebar {}",
|
return Ok((false, format!("Sidebar {}",
|
||||||
if app_state.ui.show_sidebar { "shown" } else { "hidden" }
|
if app_state.ui.show_sidebar { "shown" } else { "hidden" }
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mode-specific handling
|
|
||||||
match current_mode {
|
match current_mode {
|
||||||
AppMode::General => {
|
AppMode::General => {
|
||||||
return navigation::handle_navigation_event(
|
return navigation::handle_navigation_event(
|
||||||
@@ -90,7 +83,6 @@ impl EventHandler {
|
|||||||
},
|
},
|
||||||
|
|
||||||
AppMode::ReadOnly => {
|
AppMode::ReadOnly => {
|
||||||
// Check for mode transitions first
|
|
||||||
if config.is_enter_edit_mode_before(key_code, modifiers) &&
|
if config.is_enter_edit_mode_before(key_code, modifiers) &&
|
||||||
ModeManager::can_enter_edit_mode(current_mode) {
|
ModeManager::can_enter_edit_mode(current_mode) {
|
||||||
self.is_edit_mode = true;
|
self.is_edit_mode = true;
|
||||||
@@ -129,7 +121,6 @@ impl EventHandler {
|
|||||||
return Ok((false, self.command_message.clone()));
|
return Ok((false, self.command_message.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for entering command mode
|
|
||||||
if let Some(action) = config.get_read_only_action_for_key(key_code, modifiers) {
|
if let Some(action) = config.get_read_only_action_for_key(key_code, modifiers) {
|
||||||
if action == "enter_command_mode" && ModeManager::can_enter_command_mode(current_mode) {
|
if action == "enter_command_mode" && ModeManager::can_enter_command_mode(current_mode) {
|
||||||
self.command_mode = true;
|
self.command_mode = true;
|
||||||
@@ -139,7 +130,6 @@ impl EventHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for core application actions (save, quit, etc.)
|
|
||||||
if let Some(action) = config.get_action_for_key_in_mode(
|
if let Some(action) = config.get_action_for_key_in_mode(
|
||||||
&config.keybindings.common,
|
&config.keybindings.common,
|
||||||
key_code,
|
key_code,
|
||||||
@@ -150,7 +140,7 @@ impl EventHandler {
|
|||||||
return common_mode::handle_core_action(
|
return common_mode::handle_core_action(
|
||||||
action,
|
action,
|
||||||
form_state,
|
form_state,
|
||||||
auth_state, // Changed
|
auth_state,
|
||||||
grpc_client,
|
grpc_client,
|
||||||
&mut self.auth_client,
|
&mut self.auth_client,
|
||||||
terminal,
|
terminal,
|
||||||
@@ -163,13 +153,12 @@ impl EventHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let read_only mode handle its own actions
|
|
||||||
return read_only::handle_read_only_event(
|
return read_only::handle_read_only_event(
|
||||||
&app_state,
|
&app_state,
|
||||||
key,
|
key,
|
||||||
config,
|
config,
|
||||||
form_state,
|
form_state,
|
||||||
auth_state, // Changed
|
auth_state,
|
||||||
&mut self.key_sequence_tracker,
|
&mut self.key_sequence_tracker,
|
||||||
current_position,
|
current_position,
|
||||||
total_count,
|
total_count,
|
||||||
@@ -181,21 +170,22 @@ impl EventHandler {
|
|||||||
},
|
},
|
||||||
|
|
||||||
AppMode::Edit => {
|
AppMode::Edit => {
|
||||||
// Check for exiting edit mode
|
|
||||||
if config.is_exit_edit_mode(key_code, modifiers) {
|
if config.is_exit_edit_mode(key_code, modifiers) {
|
||||||
|
self.is_edit_mode = false;
|
||||||
|
self.edit_mode_cooldown = true;
|
||||||
|
|
||||||
let has_changes = if app_state.ui.show_login {
|
let has_changes = if app_state.ui.show_login {
|
||||||
auth_state.has_unsaved_changes()
|
auth_state.has_unsaved_changes()
|
||||||
} else {
|
} else {
|
||||||
form_state.has_unsaved_changes()
|
form_state.has_unsaved_changes()
|
||||||
};
|
};
|
||||||
|
|
||||||
if has_changes {
|
self.command_message = if has_changes {
|
||||||
self.command_message = "Unsaved changes! Use :w to save or :q! to discard".to_string();
|
"Exited edit mode (unsaved changes remain)".to_string()
|
||||||
return Ok((false, self.command_message.clone()));
|
} else {
|
||||||
}
|
"Read-only mode".to_string()
|
||||||
self.is_edit_mode = false;
|
};
|
||||||
self.edit_mode_cooldown = true;
|
|
||||||
self.command_message = "Read-only mode".to_string();
|
|
||||||
terminal.set_cursor_style(SetCursorStyle::SteadyBlock)?;
|
terminal.set_cursor_style(SetCursorStyle::SteadyBlock)?;
|
||||||
|
|
||||||
let current_input = if app_state.ui.show_login {
|
let current_input = if app_state.ui.show_login {
|
||||||
@@ -222,7 +212,6 @@ impl EventHandler {
|
|||||||
return Ok((false, self.command_message.clone()));
|
return Ok((false, self.command_message.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for core application actions (save, quit, etc.)
|
|
||||||
if let Some(action) = config.get_action_for_key_in_mode(
|
if let Some(action) = config.get_action_for_key_in_mode(
|
||||||
&config.keybindings.common,
|
&config.keybindings.common,
|
||||||
key_code,
|
key_code,
|
||||||
@@ -230,29 +219,28 @@ impl EventHandler {
|
|||||||
) {
|
) {
|
||||||
match action {
|
match action {
|
||||||
"save" | "force_quit" | "save_and_quit" | "revert" => {
|
"save" | "force_quit" | "save_and_quit" | "revert" => {
|
||||||
return common_mode::handle_core_action(
|
return common_mode::handle_core_action(
|
||||||
action,
|
action,
|
||||||
form_state,
|
form_state,
|
||||||
auth_state, // Changed
|
auth_state,
|
||||||
grpc_client,
|
grpc_client,
|
||||||
&mut self.auth_client,
|
&mut self.auth_client,
|
||||||
terminal,
|
terminal,
|
||||||
app_state,
|
app_state,
|
||||||
current_position,
|
current_position,
|
||||||
total_count,
|
total_count,
|
||||||
).await;
|
).await;
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let edit mode handle its own actions
|
|
||||||
let result = edit::handle_edit_event(
|
let result = edit::handle_edit_event(
|
||||||
app_state.ui.show_login,
|
app_state.ui.show_login,
|
||||||
key,
|
key,
|
||||||
config,
|
config,
|
||||||
form_state,
|
form_state,
|
||||||
auth_state, // Changed
|
auth_state,
|
||||||
&mut self.ideal_cursor_column,
|
&mut self.ideal_cursor_column,
|
||||||
&mut self.command_message,
|
&mut self.command_message,
|
||||||
&mut app_state.ui.is_saved,
|
&mut app_state.ui.is_saved,
|
||||||
@@ -288,9 +276,7 @@ impl EventHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-key events or if no specific handler was matched
|
|
||||||
self.edit_mode_cooldown = false;
|
self.edit_mode_cooldown = false;
|
||||||
Ok((false, self.command_message.clone()))
|
Ok((false, self.command_message.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,16 +45,13 @@ pub async fn save(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Use the helper method to configure and show the dialog
|
// Use the helper method to configure and show the dialog
|
||||||
|
// TODO Implement logic for pressing menu or exit buttons, not imeplementing it now,
|
||||||
|
// need to do other more important stuff now"
|
||||||
app_state.show_dialog(
|
app_state.show_dialog(
|
||||||
"Login Success",
|
"Login Success",
|
||||||
&success_message,
|
&success_message,
|
||||||
vec!["OK".to_string()], // Pass buttons here
|
vec!["Menu".to_string(), "Exit".to_string()],
|
||||||
);
|
);
|
||||||
// REMOVE these lines:
|
|
||||||
// app_state.ui.dialog.dialog_title = "Login Success".to_string();
|
|
||||||
// app_state.ui.dialog.dialog_message = success_message;
|
|
||||||
// app_state.ui.dialog.dialog_show = true;
|
|
||||||
// app_state.ui.dialog.dialog_button_active = true;
|
|
||||||
|
|
||||||
Ok("Login successful, details shown in dialog.".to_string())
|
Ok("Login successful, details shown in dialog.".to_string())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,13 +11,22 @@ pub async fn handle_action(
|
|||||||
total_count: u64,
|
total_count: u64,
|
||||||
ideal_cursor_column: &mut usize,
|
ideal_cursor_column: &mut usize,
|
||||||
) -> Result<String, Box<dyn std::error::Error>> {
|
) -> Result<String, Box<dyn std::error::Error>> {
|
||||||
|
// TODO store unsaved changes without deleting form state values
|
||||||
|
// First check for unsaved changes in both cases
|
||||||
|
if form_state.has_unsaved_changes() {
|
||||||
|
return Ok(
|
||||||
|
"Unsaved changes. Save (Ctrl+S) or Revert (Ctrl+R) before navigating."
|
||||||
|
.to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
match action {
|
match action {
|
||||||
"previous_entry" => {
|
"previous_entry" => {
|
||||||
let new_position = current_position.saturating_sub(1);
|
let new_position = current_position.saturating_sub(1);
|
||||||
if new_position >= 1 {
|
if new_position >= 1 {
|
||||||
*current_position = new_position;
|
*current_position = new_position;
|
||||||
let response = grpc_client.get_adresar_by_position(*current_position).await?;
|
let response = grpc_client.get_adresar_by_position(*current_position).await?;
|
||||||
|
|
||||||
// Direct field assignments
|
// Direct field assignments
|
||||||
form_state.id = response.id;
|
form_state.id = response.id;
|
||||||
form_state.values = vec![
|
form_state.values = vec![
|
||||||
@@ -27,14 +36,14 @@ pub async fn handle_action(
|
|||||||
response.skladm, response.ico, response.kontakt,
|
response.skladm, response.ico, response.kontakt,
|
||||||
response.telefon, response.skladu, response.fax,
|
response.telefon, response.skladu, response.fax,
|
||||||
];
|
];
|
||||||
|
|
||||||
let current_input = form_state.get_current_input();
|
let current_input = form_state.get_current_input();
|
||||||
let max_cursor_pos = if !current_input.is_empty() {
|
let max_cursor_pos = if !current_input.is_empty() {
|
||||||
current_input.len() - 1
|
current_input.len() - 1
|
||||||
} else { 0 };
|
} else { 0 };
|
||||||
form_state.current_cursor_pos = std::cmp::min(*ideal_cursor_column, max_cursor_pos);
|
form_state.current_cursor_pos = std::cmp::min(*ideal_cursor_column, max_cursor_pos);
|
||||||
form_state.has_unsaved_changes = false;
|
form_state.has_unsaved_changes = false;
|
||||||
|
|
||||||
Ok(format!("Loaded form entry {}", *current_position))
|
Ok(format!("Loaded form entry {}", *current_position))
|
||||||
} else {
|
} else {
|
||||||
Ok("Already at first form entry".into())
|
Ok("Already at first form entry".into())
|
||||||
@@ -45,7 +54,7 @@ pub async fn handle_action(
|
|||||||
*current_position += 1;
|
*current_position += 1;
|
||||||
if *current_position <= total_count {
|
if *current_position <= total_count {
|
||||||
let response = grpc_client.get_adresar_by_position(*current_position).await?;
|
let response = grpc_client.get_adresar_by_position(*current_position).await?;
|
||||||
|
|
||||||
// Direct field assignments
|
// Direct field assignments
|
||||||
form_state.id = response.id;
|
form_state.id = response.id;
|
||||||
form_state.values = vec![
|
form_state.values = vec![
|
||||||
@@ -55,14 +64,14 @@ pub async fn handle_action(
|
|||||||
response.skladm, response.ico, response.kontakt,
|
response.skladm, response.ico, response.kontakt,
|
||||||
response.telefon, response.skladu, response.fax,
|
response.telefon, response.skladu, response.fax,
|
||||||
];
|
];
|
||||||
|
|
||||||
let current_input = form_state.get_current_input();
|
let current_input = form_state.get_current_input();
|
||||||
let max_cursor_pos = if !current_input.is_empty() {
|
let max_cursor_pos = if !current_input.is_empty() {
|
||||||
current_input.len() - 1
|
current_input.len() - 1
|
||||||
} else { 0 };
|
} else { 0 };
|
||||||
form_state.current_cursor_pos = std::cmp::min(*ideal_cursor_column, max_cursor_pos);
|
form_state.current_cursor_pos = std::cmp::min(*ideal_cursor_column, max_cursor_pos);
|
||||||
form_state.has_unsaved_changes = false;
|
form_state.has_unsaved_changes = false;
|
||||||
|
|
||||||
Ok(format!("Loaded form entry {}", *current_position))
|
Ok(format!("Loaded form entry {}", *current_position))
|
||||||
} else {
|
} else {
|
||||||
form_state.reset_to_empty();
|
form_state.reset_to_empty();
|
||||||
@@ -77,4 +86,4 @@ pub async fn handle_action(
|
|||||||
}
|
}
|
||||||
_ => Err("Unknown form action".into())
|
_ => Err("Unknown form action".into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ pub async fn run_ui() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
let total_count = app_state.total_count;
|
let total_count = app_state.total_count;
|
||||||
let mut current_position = app_state.current_position;
|
let mut current_position = app_state.current_position;
|
||||||
|
// Store position before event handling to detect navigation
|
||||||
|
let position_before_event = current_position;
|
||||||
|
|
||||||
let event = event_reader.read_event()?;
|
let event = event_reader.read_event()?;
|
||||||
let (should_exit, message) = event_handler.handle_event(
|
let (should_exit, message) = event_handler.handle_event(
|
||||||
@@ -83,9 +85,11 @@ pub async fn run_ui() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
app_state.current_position = current_position;
|
app_state.current_position = current_position;
|
||||||
|
|
||||||
|
let position_changed = app_state.current_position != position_before_event;
|
||||||
|
|
||||||
// Handle position changes and update form state (Only when form is shown)
|
// Handle position changes and update form state (Only when form is shown)
|
||||||
if app_state.ui.show_form { // Added check
|
if app_state.ui.show_form {
|
||||||
if !event_handler.is_edit_mode {
|
if position_changed && !event_handler.is_edit_mode {
|
||||||
let current_input = form_state.get_current_input();
|
let current_input = form_state.get_current_input();
|
||||||
let max_cursor_pos = if !current_input.is_empty() {
|
let max_cursor_pos = if !current_input.is_empty() {
|
||||||
current_input.len() - 1 // Limit to last character in readonly mode
|
current_input.len() - 1 // Limit to last character in readonly mode
|
||||||
@@ -131,6 +135,16 @@ pub async fn run_ui() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
form_state.current_field = 0;
|
form_state.current_field = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if !position_changed && !event_handler.is_edit_mode {
|
||||||
|
// If position didn't change but we are in read-only, just adjust cursor
|
||||||
|
let current_input = form_state.get_current_input();
|
||||||
|
let max_cursor_pos = if !current_input.is_empty() {
|
||||||
|
current_input.len() - 1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
form_state.current_cursor_pos = event_handler.ideal_cursor_column.min(max_cursor_pos);
|
||||||
|
|
||||||
}
|
}
|
||||||
} else if app_state.ui.show_login {
|
} else if app_state.ui.show_login {
|
||||||
// Handle cursor updates for AuthState if needed, similar to FormState
|
// Handle cursor updates for AuthState if needed, similar to FormState
|
||||||
|
|||||||
Reference in New Issue
Block a user