fixed form state removed, but not won, aint working yet

This commit is contained in:
Priec
2025-08-22 00:27:23 +02:00
parent 3dd6808ea2
commit 4ed8e7b421
7 changed files with 275 additions and 252 deletions

View File

@@ -50,7 +50,7 @@ move_right = ["l", "Right"]
move_down = ["j", "Down"] move_down = ["j", "Down"]
# Optional # Optional
move_line_end = ["$"] move_line_end = ["$"]
# move_word_next = ["w"] move_word_next = ["w"]
next_field = ["Tab"] next_field = ["Tab"]
move_word_prev = ["b"] move_word_prev = ["b"]
move_word_end = ["e"] move_word_end = ["e"]

View File

@@ -18,7 +18,6 @@ pub async fn handle_command_event(
app_state: &mut AppState, app_state: &mut AppState,
login_state: &LoginState, login_state: &LoginState,
register_state: &RegisterState, register_state: &RegisterState,
form_state: &mut FormState,
command_input: &mut String, command_input: &mut String,
command_message: &mut String, command_message: &mut String,
grpc_client: &mut GrpcClient, grpc_client: &mut GrpcClient,
@@ -38,7 +37,6 @@ pub async fn handle_command_event(
if config.is_command_execute(key.code, key.modifiers) { if config.is_command_execute(key.code, key.modifiers) {
return process_command( return process_command(
config, config,
form_state,
app_state, app_state,
login_state, login_state,
register_state, register_state,
@@ -73,7 +71,6 @@ pub async fn handle_command_event(
async fn process_command( async fn process_command(
config: &Config, config: &Config,
form_state: &mut FormState,
app_state: &mut AppState, app_state: &mut AppState,
login_state: &LoginState, login_state: &LoginState,
register_state: &RegisterState, register_state: &RegisterState,
@@ -103,7 +100,6 @@ async fn process_command(
action, action,
terminal, terminal,
app_state, app_state,
form_state,
login_state, login_state,
register_state, register_state,
) )
@@ -118,7 +114,6 @@ async fn process_command(
"save" => { "save" => {
let outcome = save( let outcome = save(
app_state, app_state,
form_state,
grpc_client, grpc_client,
).await?; ).await?;
let message = match outcome { let message = match outcome {
@@ -131,7 +126,7 @@ async fn process_command(
}, },
"revert" => { "revert" => {
let message = revert( let message = revert(
form_state, app_state,
grpc_client, grpc_client,
).await?; ).await?;
command_input.clear(); command_input.clear();

View File

@@ -15,13 +15,12 @@ impl CommandHandler {
&mut self, &mut self,
action: &str, action: &str,
terminal: &mut TerminalCore, terminal: &mut TerminalCore,
app_state: &AppState, app_state: &mut AppState,
form_state: &FormState,
login_state: &LoginState, login_state: &LoginState,
register_state: &RegisterState, register_state: &RegisterState,
) -> Result<(bool, String)> { ) -> Result<(bool, String)> {
match action { match action {
"quit" => self.handle_quit(terminal, app_state, form_state, login_state, register_state).await, "quit" => self.handle_quit(terminal, app_state, login_state, register_state).await,
"force_quit" => self.handle_force_quit(terminal).await, "force_quit" => self.handle_force_quit(terminal).await,
"save_and_quit" => self.handle_save_quit(terminal).await, "save_and_quit" => self.handle_save_quit(terminal).await,
_ => Ok((false, format!("Unknown command: {}", action))), _ => Ok((false, format!("Unknown command: {}", action))),
@@ -31,8 +30,7 @@ impl CommandHandler {
async fn handle_quit( async fn handle_quit(
&self, &self,
terminal: &mut TerminalCore, terminal: &mut TerminalCore,
app_state: &AppState, app_state: &mut AppState,
form_state: &FormState,
login_state: &LoginState, login_state: &LoginState,
register_state: &RegisterState, register_state: &RegisterState,
) -> Result<(bool, String)> { ) -> Result<(bool, String)> {
@@ -41,8 +39,10 @@ impl CommandHandler {
login_state.has_unsaved_changes() login_state.has_unsaved_changes()
} else if app_state.ui.show_register { } else if app_state.ui.show_register {
register_state.has_unsaved_changes() register_state.has_unsaved_changes()
} else if let Some(fs) = app_state.form_state_mut() {
fs.has_unsaved_changes
} else { } else {
form_state.has_unsaved_changes false
}; };
if !has_unsaved { if !has_unsaved {

View File

@@ -17,7 +17,6 @@ use anyhow::Result;
pub async fn handle_navigation_event( pub async fn handle_navigation_event(
key: KeyEvent, key: KeyEvent,
config: &Config, config: &Config,
form_state: &mut FormState,
app_state: &mut AppState, app_state: &mut AppState,
login_state: &mut LoginState, login_state: &mut LoginState,
register_state: &mut RegisterState, register_state: &mut RegisterState,
@@ -52,11 +51,15 @@ pub async fn handle_navigation_event(
return Ok(EventOutcome::Ok(String::new())); return Ok(EventOutcome::Ok(String::new()));
} }
"next_field" => { "next_field" => {
next_field(form_state); if let Some(fs) = app_state.form_state_mut() {
next_field(fs);
}
return Ok(EventOutcome::Ok(String::new())); return Ok(EventOutcome::Ok(String::new()));
} }
"prev_field" => { "prev_field" => {
prev_field(form_state); if let Some(fs) = app_state.form_state_mut() {
prev_field(fs);
}
return Ok(EventOutcome::Ok(String::new())); return Ok(EventOutcome::Ok(String::new()));
} }
"enter_command_mode" => { "enter_command_mode" => {

View File

@@ -220,18 +220,20 @@ impl EventHandler {
async fn handle_search_palette_event( async fn handle_search_palette_event(
&mut self, &mut self,
key_event: KeyEvent, key_event: KeyEvent,
form_state: &mut FormState,
app_state: &mut AppState, app_state: &mut AppState,
) -> Result<EventOutcome> { ) -> Result<EventOutcome> {
let mut should_close = false; let mut should_close = false;
let mut outcome_message = String::new(); let mut outcome_message = String::new();
let mut trigger_search = false; let mut trigger_search = false;
// Step 1: Handle search_state logic in a short scope
let (maybe_data, maybe_id) = {
if let Some(search_state) = app_state.search_state.as_mut() { if let Some(search_state) = app_state.search_state.as_mut() {
match key_event.code { match key_event.code {
KeyCode::Esc => { KeyCode::Esc => {
should_close = true; should_close = true;
outcome_message = "Search cancelled".to_string(); outcome_message = "Search cancelled".to_string();
(None, None)
} }
KeyCode::Enter => { KeyCode::Enter => {
if let Some(selected_hit) = if let Some(selected_hit) =
@@ -241,23 +243,27 @@ impl EventHandler {
std::collections::HashMap<String, String>, std::collections::HashMap<String, String>,
>(&selected_hit.content_json) >(&selected_hit.content_json)
{ {
let detached_pos = form_state.total_count + 2; (Some(data), Some(selected_hit.id))
form_state } else {
.update_from_response(&data, detached_pos); (None, None)
} }
should_close = true; } else {
outcome_message = (None, None)
format!("Loaded record ID {}", selected_hit.id);
} }
} }
KeyCode::Up => search_state.previous_result(), KeyCode::Up => {
KeyCode::Down => search_state.next_result(), search_state.previous_result();
(None, None)
}
KeyCode::Down => {
search_state.next_result();
(None, None)
}
KeyCode::Char(c) => { KeyCode::Char(c) => {
search_state search_state.input.insert(search_state.cursor_position, c);
.input
.insert(search_state.cursor_position, c);
search_state.cursor_position += 1; search_state.cursor_position += 1;
trigger_search = true; trigger_search = true;
(None, None)
} }
KeyCode::Backspace => { KeyCode::Backspace => {
if search_state.cursor_position > 0 { if search_state.cursor_position > 0 {
@@ -265,21 +271,39 @@ impl EventHandler {
search_state.input.remove(search_state.cursor_position); search_state.input.remove(search_state.cursor_position);
trigger_search = true; trigger_search = true;
} }
(None, None)
} }
KeyCode::Left => { KeyCode::Left => {
search_state.cursor_position = search_state.cursor_position =
search_state.cursor_position.saturating_sub(1); search_state.cursor_position.saturating_sub(1);
(None, None)
} }
KeyCode::Right => { KeyCode::Right => {
if search_state.cursor_position < search_state.input.len() if search_state.cursor_position < search_state.input.len() {
{
search_state.cursor_position += 1; search_state.cursor_position += 1;
} }
(None, None)
} }
_ => {} _ => (None, None),
}
} else {
(None, None)
}
};
// Step 2: Now safe to borrow form_state
if let (Some(data), Some(id)) = (maybe_data, maybe_id) {
if let Some(fs) = app_state.form_state_mut() {
let detached_pos = fs.total_count + 2;
fs.update_from_response(&data, detached_pos);
}
should_close = true;
outcome_message = format!("Loaded record ID {}", id);
} }
// Step 3: Trigger async search if needed
if trigger_search { if trigger_search {
if let Some(search_state) = app_state.search_state.as_mut() {
search_state.is_loading = true; search_state.is_loading = true;
search_state.results.clear(); search_state.results.clear();
search_state.selected_index = 0; search_state.selected_index = 0;
@@ -289,10 +313,7 @@ impl EventHandler {
let sender = self.search_result_sender.clone(); let sender = self.search_result_sender.clone();
let mut grpc_client = self.grpc_client.clone(); let mut grpc_client = self.grpc_client.clone();
info!( info!("--- 1. Spawning search task for query: '{}' ---", query);
"--- 1. Spawning search task for query: '{}' ---",
query
);
tokio::spawn(async move { tokio::spawn(async move {
info!("--- 2. Background task started. ---"); info!("--- 2. Background task started. ---");
match grpc_client.search_table(table_name, query).await { match grpc_client.search_table(table_name, query).await {
@@ -328,7 +349,6 @@ impl EventHandler {
config: &Config, config: &Config,
terminal: &mut TerminalCore, terminal: &mut TerminalCore,
command_handler: &mut CommandHandler, command_handler: &mut CommandHandler,
form_state: &mut FormState,
auth_state: &mut AuthState, auth_state: &mut AuthState,
login_state: &mut LoginState, login_state: &mut LoginState,
register_state: &mut RegisterState, register_state: &mut RegisterState,
@@ -339,13 +359,7 @@ impl EventHandler {
) -> Result<EventOutcome> { ) -> Result<EventOutcome> {
if app_state.ui.show_search_palette { if app_state.ui.show_search_palette {
if let Event::Key(key_event) = event { if let Event::Key(key_event) = event {
return self return self.handle_search_palette_event(key_event, app_state).await;
.handle_search_palette_event(
key_event,
form_state,
app_state,
)
.await;
} }
return Ok(EventOutcome::Ok(String::new())); return Ok(EventOutcome::Ok(String::new()));
} }
@@ -570,7 +584,6 @@ impl EventHandler {
let nav_outcome = navigation::handle_navigation_event( let nav_outcome = navigation::handle_navigation_event(
key_event, key_event,
config, config,
form_state,
app_state, app_state,
login_state, login_state,
register_state, register_state,
@@ -580,9 +593,7 @@ impl EventHandler {
&mut self.command_input, &mut self.command_input,
&mut self.command_message, &mut self.command_message,
&mut self.navigation_state, &mut self.navigation_state,
) ).await;
.await;
match nav_outcome { match nav_outcome {
Ok(EventOutcome::ButtonSelected { context, index }) => { Ok(EventOutcome::ButtonSelected { context, index }) => {
let message = match context { let message = match context {
@@ -692,7 +703,6 @@ impl EventHandler {
return self return self
.handle_core_action( .handle_core_action(
action, action,
form_state,
auth_state, auth_state,
login_state, login_state,
register_state, register_state,
@@ -739,7 +749,6 @@ impl EventHandler {
return self return self
.handle_core_action( .handle_core_action(
action, action,
form_state,
auth_state, auth_state,
login_state, login_state,
register_state, register_state,
@@ -792,15 +801,18 @@ impl EventHandler {
} }
if config.is_command_execute(key_code, modifiers) { if config.is_command_execute(key_code, modifiers) {
let mut current_position = form_state.current_position; let (mut current_position, total_count) = if let Some(fs) = app_state.form_state() {
let total_count = form_state.total_count; (fs.current_position, fs.total_count)
} else {
(1, 0)
};
let outcome = command_mode::handle_command_event( let outcome = command_mode::handle_command_event(
key_event, key_event,
config, config,
app_state, app_state,
login_state, login_state,
register_state, register_state,
form_state,
&mut self.command_input, &mut self.command_input,
&mut self.command_message, &mut self.command_message,
&mut self.grpc_client, &mut self.grpc_client,
@@ -808,9 +820,10 @@ impl EventHandler {
terminal, terminal,
&mut current_position, &mut current_position,
total_count, total_count,
) ).await?;
.await?; if let Some(fs) = app_state.form_state_mut() {
form_state.current_position = current_position; fs.current_position = current_position;
}
self.command_mode = false; self.command_mode = false;
self.key_sequence_tracker.reset(); self.key_sequence_tracker.reset();
let new_mode = ModeManager::derive_mode( let new_mode = ModeManager::derive_mode(
@@ -921,7 +934,6 @@ impl EventHandler {
async fn handle_core_action( async fn handle_core_action(
&mut self, &mut self,
action: &str, action: &str,
form_state: &mut FormState,
auth_state: &mut AuthState, auth_state: &mut AuthState,
login_state: &mut LoginState, login_state: &mut LoginState,
register_state: &mut RegisterState, register_state: &mut RegisterState,
@@ -940,12 +952,15 @@ impl EventHandler {
.await?; .await?;
Ok(EventOutcome::Ok(message)) Ok(EventOutcome::Ok(message))
} else { } else {
let save_outcome = crate::tui::functions::common::form::save( let save_outcome = if let Some(fs) = app_state.form_state_mut() {
crate::tui::functions::common::form::save(
app_state, app_state,
form_state,
&mut self.grpc_client, &mut self.grpc_client,
) )
.await?; .await?
} else {
SaveOutcome::NoChange
};
let message = match save_outcome { let message = match save_outcome {
SaveOutcome::NoChange => "No changes to save.".to_string(), SaveOutcome::NoChange => "No changes to save.".to_string(),
SaveOutcome::UpdatedExisting => "Entry updated.".to_string(), SaveOutcome::UpdatedExisting => "Entry updated.".to_string(),
@@ -975,10 +990,8 @@ impl EventHandler {
} else { } else {
let save_outcome = crate::tui::functions::common::form::save( let save_outcome = crate::tui::functions::common::form::save(
app_state, app_state,
form_state,
&mut self.grpc_client, &mut self.grpc_client,
) ).await?;
.await?;
match save_outcome { match save_outcome {
SaveOutcome::NoChange => "No changes to save.".to_string(), SaveOutcome::NoChange => "No changes to save.".to_string(),
SaveOutcome::UpdatedExisting => "Entry updated.".to_string(), SaveOutcome::UpdatedExisting => "Entry updated.".to_string(),
@@ -1005,11 +1018,15 @@ impl EventHandler {
) )
.await .await
} else { } else {
if let Some(fs) = app_state.form_state_mut() {
crate::tui::functions::common::form::revert( crate::tui::functions::common::form::revert(
form_state, app_state,
&mut self.grpc_client, &mut self.grpc_client,
) )
.await? .await?
} else {
"Nothing to revert".to_string()
}
}; };
Ok(EventOutcome::Ok(message)) Ok(EventOutcome::Ok(message))
} }

View File

@@ -1,9 +1,7 @@
// src/tui/functions/common/form.rs // src/tui/functions/common/form.rs
use crate::services::grpc_client::GrpcClient; use crate::services::grpc_client::GrpcClient;
use crate::state::app::state::AppState; // NEW: Import AppState use crate::state::app::state::AppState;
use crate::state::pages::form::FormState; use crate::utils::data_converter;
use crate::utils::data_converter; // NEW: Import our translator
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, Context, Result};
use std::collections::HashMap; use std::collections::HashMap;
@@ -14,143 +12,137 @@ pub enum SaveOutcome {
CreatedNew(i64), CreatedNew(i64),
} }
// MODIFIED save function signature and logic
pub async fn save( pub async fn save(
app_state: &AppState, // NEW: Pass in AppState app_state: &mut AppState,
form_state: &mut FormState,
grpc_client: &mut GrpcClient, grpc_client: &mut GrpcClient,
) -> Result<SaveOutcome> { ) -> Result<SaveOutcome> {
if !form_state.has_unsaved_changes { if let Some(fs) = app_state.form_state_mut() {
if !fs.has_unsaved_changes {
return Ok(SaveOutcome::NoChange); return Ok(SaveOutcome::NoChange);
} }
// --- NEW: VALIDATION & CONVERSION STEP --- // Copy out what we need before dropping the mutable borrow
let cache_key = let profile_name = fs.profile_name.clone();
format!("{}.{}", form_state.profile_name, form_state.table_name); let table_name = fs.table_name.clone();
let schema = match app_state.schema_cache.get(&cache_key) { let fields = fs.fields.clone();
Some(s) => s, let values = fs.values.clone();
None => { let id = fs.id;
return Err(anyhow!( let total_count = fs.total_count;
"Schema for table '{}' not found in cache. Cannot save.", let current_position = fs.current_position;
form_state.table_name
));
}
};
let data_map: HashMap<String, String> = form_state let cache_key = format!("{}.{}", profile_name, table_name);
.fields let schema = app_state
.schema_cache
.get(&cache_key)
.ok_or_else(|| {
anyhow!(
"Schema for table '{}' not found in cache. Cannot save.",
table_name
)
})?;
let data_map: HashMap<String, String> = fields
.iter() .iter()
.zip(form_state.values.iter()) .zip(values.iter())
.map(|(field_def, value)| (field_def.data_key.clone(), value.clone())) .map(|(field_def, value)| (field_def.data_key.clone(), value.clone()))
.collect(); .collect();
// Use our new translator. It returns a user-friendly error on failure.
let converted_data = let converted_data =
match data_converter::convert_and_validate_data(&data_map, schema) { data_converter::convert_and_validate_data(&data_map, schema)
Ok(data) => data, .map_err(|user_error| anyhow!(user_error))?;
Err(user_error) => return Err(anyhow!(user_error)),
};
// --- END OF NEW STEP ---
let outcome: SaveOutcome; let is_new_entry = id == 0
let is_new_entry = form_state.id == 0 || (total_count > 0 && current_position > total_count)
|| (form_state.total_count > 0 || (total_count == 0 && current_position == 1);
&& form_state.current_position > form_state.total_count)
|| (form_state.total_count == 0 && form_state.current_position == 1);
if is_new_entry { let outcome = if is_new_entry {
let response = grpc_client let response = grpc_client
.post_table_data( .post_table_data(profile_name.clone(), table_name.clone(), converted_data)
form_state.profile_name.clone(),
form_state.table_name.clone(),
converted_data, // Use the validated & converted data
)
.await .await
.context("Failed to post new table data")?; .context("Failed to post new table data")?;
if response.success { if response.success {
form_state.id = response.inserted_id; if let Some(fs) = app_state.form_state_mut() {
form_state.total_count += 1; fs.id = response.inserted_id;
form_state.current_position = form_state.total_count; fs.total_count += 1;
outcome = SaveOutcome::CreatedNew(response.inserted_id); fs.current_position = fs.total_count;
fs.has_unsaved_changes = false;
}
SaveOutcome::CreatedNew(response.inserted_id)
} else { } else {
return Err(anyhow!( return Err(anyhow!("Server failed to insert data: {}", response.message));
"Server failed to insert data: {}",
response.message
));
} }
} else { } else {
if form_state.id == 0 { if id == 0 {
return Err(anyhow!( return Err(anyhow!(
"Cannot update record: ID is 0, but not classified as new entry." "Cannot update record: ID is 0, but not classified as new entry."
)); ));
} }
let response = grpc_client let response = grpc_client
.put_table_data( .put_table_data(profile_name.clone(), table_name.clone(), id, converted_data)
form_state.profile_name.clone(),
form_state.table_name.clone(),
form_state.id,
converted_data, // Use the validated & converted data
)
.await .await
.context("Failed to put (update) table data")?; .context("Failed to put (update) table data")?;
if response.success { if response.success {
outcome = SaveOutcome::UpdatedExisting; if let Some(fs) = app_state.form_state_mut() {
fs.has_unsaved_changes = false;
}
SaveOutcome::UpdatedExisting
} else { } else {
return Err(anyhow!( return Err(anyhow!("Server failed to update data: {}", response.message));
"Server failed to update data: {}",
response.message
));
}
} }
};
form_state.has_unsaved_changes = false;
Ok(outcome) Ok(outcome)
} else {
Ok(SaveOutcome::NoChange)
}
} }
pub async fn revert( pub async fn revert(
form_state: &mut FormState, // Takes &mut FormState to update it app_state: &mut AppState,
grpc_client: &mut GrpcClient, grpc_client: &mut GrpcClient,
) -> Result<String> { ) -> Result<String> {
if form_state.id == 0 || (form_state.total_count > 0 && form_state.current_position > form_state.total_count) || (form_state.total_count == 0 && form_state.current_position == 1) { if let Some(fs) = app_state.form_state_mut() {
let old_total_count = form_state.total_count; // Preserve for correct new position if fs.id == 0
form_state.reset_to_empty(); // reset_to_empty will clear values and set id=0 || (fs.total_count > 0 && fs.current_position > fs.total_count)
form_state.total_count = old_total_count; // Restore total_count || (fs.total_count == 0 && fs.current_position == 1)
if form_state.total_count > 0 { // Correctly set current_position for new {
form_state.current_position = form_state.total_count + 1; let old_total_count = fs.total_count;
fs.reset_to_empty();
fs.total_count = old_total_count;
if fs.total_count > 0 {
fs.current_position = fs.total_count + 1;
} else { } else {
form_state.current_position = 1; fs.current_position = 1;
} }
return Ok("New entry cleared".to_string()); return Ok("New entry cleared".to_string());
} }
if form_state.current_position == 0 || form_state.current_position > form_state.total_count { if fs.current_position == 0 || fs.current_position > fs.total_count {
if form_state.total_count > 0 { if fs.total_count > 0 {
form_state.current_position = 1; fs.current_position = 1;
} else { } else {
// No records to revert to, effectively a new entry state. fs.reset_to_empty();
form_state.reset_to_empty();
return Ok("No saved data to revert to; form cleared.".to_string()); return Ok("No saved data to revert to; form cleared.".to_string());
} }
} }
let response = grpc_client let response = grpc_client
.get_table_data_by_position( .get_table_data_by_position(
form_state.profile_name.clone(), fs.profile_name.clone(),
form_state.table_name.clone(), fs.table_name.clone(),
form_state.current_position as i32, fs.current_position as i32,
) )
.await .await
.context(format!( .context(format!(
"Failed to get table data by position {} for table {}.{}", "Failed to get table data by position {} for table {}.{}",
form_state.current_position, fs.current_position, fs.profile_name, fs.table_name
form_state.profile_name,
form_state.table_name
))?; ))?;
// FIX: Pass the current position as the second argument fs.update_from_response(&response.data, fs.current_position);
form_state.update_from_response(&response.data, form_state.current_position);
Ok("Changes discarded, reloaded last saved version".to_string()) Ok("Changes discarded, reloaded last saved version".to_string())
} else {
Ok("Nothing to revert".to_string())
}
} }

View File

@@ -26,6 +26,7 @@ use crate::ui::handlers::context::DialogPurpose;
use crate::tui::functions::common::login; use crate::tui::functions::common::login;
use crate::tui::functions::common::register; use crate::tui::functions::common::register;
use crate::utils::columns::filter_user_columns; use crate::utils::columns::filter_user_columns;
use canvas::keymap::KeyEventOutcome;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use crossterm::cursor::SetCursorStyle; use crossterm::cursor::SetCursorStyle;
use crossterm::event as crossterm_event; use crossterm::event as crossterm_event;
@@ -193,16 +194,40 @@ pub async fn run_ui() -> Result<()> {
if crossterm_event::poll(std::time::Duration::from_millis(1))? { if crossterm_event::poll(std::time::Duration::from_millis(1))? {
let event = event_reader.read_event().context("Failed to read terminal event")?; let event = event_reader.read_event().context("Failed to read terminal event")?;
event_processed = true; event_processed = true;
let event_outcome_result = {
// We need to avoid borrowing app_state twice, so we'll need to modify the handle_event call if let crossterm_event::Event::Key(key_event) = &event {
// For now, let's create a temporary approach if app_state.ui.show_form {
let mut temp_form_state = app_state.form_state_mut().unwrap().clone(); if let Some(editor) = app_state.form_editor.as_mut() {
let result = event_handler.handle_event( match editor.handle_key_event(*key_event) {
KeyEventOutcome::Consumed(Some(msg)) => {
event_handler.command_message = msg;
needs_redraw = true;
continue;
}
KeyEventOutcome::Consumed(None) => {
needs_redraw = true;
continue;
}
KeyEventOutcome::Pending => {
needs_redraw = true;
continue;
}
KeyEventOutcome::NotMatched => {
// fall through to client-level handling
}
}
}
}
}
// Get form state from app_state and pass to handle_event
let form_state = app_state.form_state_mut().unwrap();
let event_outcome_result = event_handler.handle_event(
event, event,
&config, &config,
&mut terminal, &mut terminal,
&mut command_handler, &mut command_handler,
&mut temp_form_state,
&mut auth_state, &mut auth_state,
&mut login_state, &mut login_state,
&mut register_state, &mut register_state,
@@ -211,15 +236,6 @@ pub async fn run_ui() -> Result<()> {
&mut buffer_state, &mut buffer_state,
&mut app_state, &mut app_state,
).await; ).await;
// Update the app_state with any changes from temp_form_state
if let Some(form_state) = app_state.form_state_mut() {
*form_state = temp_form_state;
}
result
};
let mut should_exit = false; let mut should_exit = false;
match event_outcome_result { match event_outcome_result {
Ok(outcome) => match outcome { Ok(outcome) => match outcome {