now no need for init_form_editor everywhere
This commit is contained in:
@@ -7,8 +7,9 @@ use common::proto::komp_ac::table_structure::TableStructureResponse;
|
|||||||
use crate::modes::handlers::mode_manager::AppMode;
|
use crate::modes::handlers::mode_manager::AppMode;
|
||||||
use crate::state::app::search::SearchState;
|
use crate::state::app::search::SearchState;
|
||||||
use crate::ui::handlers::context::DialogPurpose;
|
use crate::ui::handlers::context::DialogPurpose;
|
||||||
use canvas::FormEditor;
|
|
||||||
use crate::state::pages::form::FormState;
|
use crate::state::pages::form::FormState;
|
||||||
|
use crate::config::binds::Config;
|
||||||
|
use canvas::FormEditor;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -185,6 +186,29 @@ impl AppState {
|
|||||||
.get(self.ui.dialog.dialog_active_button_index)
|
.get(self.ui.dialog.dialog_active_button_index)
|
||||||
.map(|s| s.as_str())
|
.map(|s| s.as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn init_form_editor(&mut self, form_state: FormState, config: &Config) {
|
||||||
|
let mut editor = FormEditor::new(form_state);
|
||||||
|
editor.set_keymap(config.build_canvas_keymap()); // inject keymap
|
||||||
|
self.form_editor = Some(editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Replace the current form state and wrap it in a FormEditor with keymap
|
||||||
|
pub fn set_form_state(&mut self, form_state: FormState, config: &Config) {
|
||||||
|
let mut editor = FormEditor::new(form_state);
|
||||||
|
editor.set_keymap(config.build_canvas_keymap());
|
||||||
|
self.form_editor = Some(editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Immutable access to the underlying FormState
|
||||||
|
pub fn form_state(&self) -> Option<&FormState> {
|
||||||
|
self.form_editor.as_ref().map(|e| e.data_provider())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mutable access to the underlying FormState
|
||||||
|
pub fn form_state_mut(&mut self) -> Option<&mut FormState> {
|
||||||
|
self.form_editor.as_mut().map(|e| e.data_provider_mut())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for UiState {
|
impl Default for UiState {
|
||||||
|
|||||||
@@ -116,26 +116,6 @@ impl FormState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(
|
|
||||||
&self,
|
|
||||||
f: &mut Frame,
|
|
||||||
area: Rect,
|
|
||||||
theme: &Theme,
|
|
||||||
is_edit_mode: bool,
|
|
||||||
) {
|
|
||||||
// Wrap in FormEditor for new API
|
|
||||||
let mut editor = FormEditor::new(self.clone());
|
|
||||||
|
|
||||||
// Use new canvas rendering
|
|
||||||
canvas::render_canvas_default(f, area, &editor);
|
|
||||||
|
|
||||||
// If autocomplete is active, render suggestions
|
|
||||||
if self.autocomplete_active && !self.autocomplete_suggestions.is_empty() {
|
|
||||||
// Note: This will need to be updated when suggestions are integrated
|
|
||||||
// canvas::render_suggestions_dropdown(f, area, input_rect, &canvas::DefaultCanvasTheme, &editor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reset_to_empty(&mut self) {
|
pub fn reset_to_empty(&mut self) {
|
||||||
self.id = 0;
|
self.id = 0;
|
||||||
self.values.iter_mut().for_each(|v| v.clear());
|
self.values.iter_mut().for_each(|v| v.clear());
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ use crate::state::pages::auth::LoginState;
|
|||||||
use crate::state::pages::auth::RegisterState;
|
use crate::state::pages::auth::RegisterState;
|
||||||
use crate::state::pages::form::FormState;
|
use crate::state::pages::form::FormState;
|
||||||
use crate::state::pages::intro::IntroState;
|
use crate::state::pages::intro::IntroState;
|
||||||
|
use crate::components::render_form;
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
layout::{Constraint, Direction, Layout},
|
layout::{Constraint, Direction, Layout},
|
||||||
Frame,
|
Frame,
|
||||||
@@ -192,12 +193,15 @@ pub fn render_ui(
|
|||||||
.split(form_actual_area)[1]
|
.split(form_actual_area)[1]
|
||||||
};
|
};
|
||||||
|
|
||||||
// CHANGED: Convert local HighlightState to canvas HighlightState for FormState
|
render_form(
|
||||||
form_state.render(
|
|
||||||
f,
|
f,
|
||||||
form_render_area,
|
form_render_area,
|
||||||
|
app_state,
|
||||||
|
form_state,
|
||||||
|
app_state.current_view_table_name.as_deref().unwrap_or(""),
|
||||||
theme,
|
theme,
|
||||||
is_event_handler_edit_mode,
|
form_state.total_count,
|
||||||
|
form_state.current_position,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -102,25 +102,28 @@ pub async fn run_ui() -> Result<()> {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut form_state = FormState::new(
|
// Replace local form_state with app_state.form_editor
|
||||||
initial_profile.clone(),
|
app_state.set_form_state(
|
||||||
initial_table.clone(),
|
FormState::new(initial_profile.clone(), initial_table.clone(), initial_field_defs),
|
||||||
initial_field_defs,
|
&config,
|
||||||
);
|
);
|
||||||
|
|
||||||
UiService::fetch_and_set_table_count(&mut grpc_client, &mut form_state)
|
// Fetch initial count using app_state accessor
|
||||||
.await
|
if let Some(form_state) = app_state.form_state_mut() {
|
||||||
.context(format!(
|
UiService::fetch_and_set_table_count(&mut grpc_client, form_state)
|
||||||
"Failed to fetch initial count for table {}.{}",
|
.await
|
||||||
initial_profile, initial_table
|
.context(format!(
|
||||||
))?;
|
"Failed to fetch initial count for table {}.{}",
|
||||||
|
initial_profile, initial_table
|
||||||
|
))?;
|
||||||
|
|
||||||
if form_state.total_count > 0 {
|
if form_state.total_count > 0 {
|
||||||
if let Err(e) = UiService::load_table_data_by_position(&mut grpc_client, &mut form_state).await {
|
if let Err(e) = UiService::load_table_data_by_position(&mut grpc_client, form_state).await {
|
||||||
event_handler.command_message = format!("Error loading initial data: {}", e);
|
event_handler.command_message = format!("Error loading initial data: {}", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
form_state.reset_to_empty();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
form_state.reset_to_empty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if auto_logged_in {
|
if auto_logged_in {
|
||||||
@@ -137,7 +140,9 @@ pub async fn run_ui() -> Result<()> {
|
|||||||
let mut table_just_switched = false;
|
let mut table_just_switched = false;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let position_before_event = form_state.current_position;
|
let position_before_event = app_state.form_state()
|
||||||
|
.map(|fs| fs.current_position)
|
||||||
|
.unwrap_or(1);
|
||||||
let mut event_processed = false;
|
let mut event_processed = false;
|
||||||
|
|
||||||
// --- CHANNEL RECEIVERS ---
|
// --- CHANNEL RECEIVERS ---
|
||||||
@@ -162,15 +167,17 @@ pub async fn run_ui() -> Result<()> {
|
|||||||
// --- ADDED: For live form autocomplete ---
|
// --- ADDED: For live form autocomplete ---
|
||||||
match event_handler.autocomplete_result_receiver.try_recv() {
|
match event_handler.autocomplete_result_receiver.try_recv() {
|
||||||
Ok(hits) => {
|
Ok(hits) => {
|
||||||
if form_state.autocomplete_active {
|
if let Some(form_state) = app_state.form_state_mut() {
|
||||||
form_state.autocomplete_suggestions = hits;
|
if form_state.autocomplete_active {
|
||||||
form_state.autocomplete_loading = false;
|
form_state.autocomplete_suggestions = hits;
|
||||||
if !form_state.autocomplete_suggestions.is_empty() {
|
form_state.autocomplete_loading = false;
|
||||||
form_state.selected_suggestion_index = Some(0);
|
if !form_state.autocomplete_suggestions.is_empty() {
|
||||||
} else {
|
form_state.selected_suggestion_index = Some(0);
|
||||||
form_state.selected_suggestion_index = None;
|
} else {
|
||||||
|
form_state.selected_suggestion_index = None;
|
||||||
|
}
|
||||||
|
event_handler.command_message = format!("Found {} suggestions.", form_state.autocomplete_suggestions.len());
|
||||||
}
|
}
|
||||||
event_handler.command_message = format!("Found {} suggestions.", form_state.autocomplete_suggestions.len());
|
|
||||||
}
|
}
|
||||||
needs_redraw = true;
|
needs_redraw = true;
|
||||||
}
|
}
|
||||||
@@ -180,27 +187,38 @@ pub async fn run_ui() -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if app_state.ui.show_search_palette {
|
if app_state.ui.show_search_palette {
|
||||||
needs_redraw = true;
|
needs_redraw = true;
|
||||||
}
|
}
|
||||||
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 = event_handler.handle_event(
|
let event_outcome_result = {
|
||||||
event,
|
// We need to avoid borrowing app_state twice, so we'll need to modify the handle_event call
|
||||||
&config,
|
// For now, let's create a temporary approach
|
||||||
&mut terminal,
|
let mut temp_form_state = app_state.form_state_mut().unwrap().clone();
|
||||||
&mut command_handler,
|
let result = event_handler.handle_event(
|
||||||
&mut form_state,
|
event,
|
||||||
&mut auth_state,
|
&config,
|
||||||
&mut login_state,
|
&mut terminal,
|
||||||
&mut register_state,
|
&mut command_handler,
|
||||||
&mut intro_state,
|
&mut temp_form_state,
|
||||||
&mut admin_state,
|
&mut auth_state,
|
||||||
&mut buffer_state,
|
&mut login_state,
|
||||||
&mut app_state,
|
&mut register_state,
|
||||||
).await;
|
&mut intro_state,
|
||||||
|
&mut admin_state,
|
||||||
|
&mut buffer_state,
|
||||||
|
&mut app_state,
|
||||||
|
).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 {
|
||||||
@@ -216,15 +234,21 @@ pub async fn run_ui() -> Result<()> {
|
|||||||
}
|
}
|
||||||
EventOutcome::DataSaved(save_outcome, message) => {
|
EventOutcome::DataSaved(save_outcome, message) => {
|
||||||
event_handler.command_message = message;
|
event_handler.command_message = message;
|
||||||
|
// Clone form_state to avoid double borrow
|
||||||
|
let mut temp_form_state = app_state.form_state().unwrap().clone();
|
||||||
if let Err(e) = UiService::handle_save_outcome(
|
if let Err(e) = UiService::handle_save_outcome(
|
||||||
save_outcome,
|
save_outcome,
|
||||||
&mut grpc_client,
|
&mut grpc_client,
|
||||||
&mut app_state,
|
&mut app_state,
|
||||||
&mut form_state,
|
&mut temp_form_state,
|
||||||
).await {
|
).await {
|
||||||
event_handler.command_message =
|
event_handler.command_message =
|
||||||
format!("Error handling save outcome: {}", e);
|
format!("Error handling save outcome: {}", e);
|
||||||
}
|
}
|
||||||
|
// Update app_state with changes
|
||||||
|
if let Some(form_state) = app_state.form_state_mut() {
|
||||||
|
*form_state = temp_form_state;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EventOutcome::ButtonSelected { .. } => {}
|
EventOutcome::ButtonSelected { .. } => {}
|
||||||
EventOutcome::TableSelected { path } => {
|
EventOutcome::TableSelected { path } => {
|
||||||
@@ -348,7 +372,7 @@ pub async fn run_ui() -> Result<()> {
|
|||||||
|
|
||||||
// Continue with the rest of the function...
|
// Continue with the rest of the function...
|
||||||
// (The rest remains the same, but now CanvasState trait methods are available)
|
// (The rest remains the same, but now CanvasState trait methods are available)
|
||||||
|
|
||||||
if app_state.ui.show_form {
|
if app_state.ui.show_form {
|
||||||
let current_view_profile = app_state.current_view_profile_name.clone();
|
let current_view_profile = app_state.current_view_profile_name.clone();
|
||||||
let current_view_table = app_state.current_view_table_name.clone();
|
let current_view_table = app_state.current_view_table_name.clone();
|
||||||
@@ -373,39 +397,43 @@ pub async fn run_ui() -> Result<()> {
|
|||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(mut new_form_state) => {
|
Ok(new_form_state) => {
|
||||||
if let Err(e) = UiService::fetch_and_set_table_count(
|
// Set the new form state and fetch count
|
||||||
&mut grpc_client,
|
app_state.set_form_state(new_form_state, &config);
|
||||||
&mut new_form_state,
|
|
||||||
)
|
if let Some(form_state) = app_state.form_state_mut() {
|
||||||
.await
|
if let Err(e) = UiService::fetch_and_set_table_count(
|
||||||
{
|
|
||||||
app_state.update_dialog_content(
|
|
||||||
&format!("Error fetching count: {}", e),
|
|
||||||
vec!["OK".to_string()],
|
|
||||||
DialogPurpose::LoginFailed,
|
|
||||||
);
|
|
||||||
} else if new_form_state.total_count > 0 {
|
|
||||||
if let Err(e) = UiService::load_table_data_by_position(
|
|
||||||
&mut grpc_client,
|
&mut grpc_client,
|
||||||
&mut new_form_state,
|
form_state,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
app_state.update_dialog_content(
|
app_state.update_dialog_content(
|
||||||
&format!("Error loading data: {}", e),
|
&format!("Error fetching count: {}", e),
|
||||||
vec!["OK".to_string()],
|
vec!["OK".to_string()],
|
||||||
DialogPurpose::LoginFailed,
|
DialogPurpose::LoginFailed,
|
||||||
);
|
);
|
||||||
|
} else if form_state.total_count > 0 {
|
||||||
|
if let Err(e) = UiService::load_table_data_by_position(
|
||||||
|
&mut grpc_client,
|
||||||
|
form_state,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
app_state.update_dialog_content(
|
||||||
|
&format!("Error loading data: {}", e),
|
||||||
|
vec!["OK".to_string()],
|
||||||
|
DialogPurpose::LoginFailed,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
app_state.hide_dialog();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
form_state.reset_to_empty();
|
||||||
app_state.hide_dialog();
|
app_state.hide_dialog();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
new_form_state.reset_to_empty();
|
|
||||||
app_state.hide_dialog();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
form_state = new_form_state;
|
|
||||||
prev_view_profile_name = current_view_profile;
|
prev_view_profile_name = current_view_profile;
|
||||||
prev_view_table_name = current_view_table;
|
prev_view_table_name = current_view_table;
|
||||||
table_just_switched = true;
|
table_just_switched = true;
|
||||||
@@ -429,7 +457,7 @@ pub async fn run_ui() -> Result<()> {
|
|||||||
|
|
||||||
// Continue with the rest of the positioning logic...
|
// Continue with the rest of the positioning logic...
|
||||||
// Now we can use CanvasState methods like get_current_input(), current_field(), etc.
|
// Now we can use CanvasState methods like get_current_input(), current_field(), etc.
|
||||||
|
|
||||||
if let Some((profile_name, table_name)) = app_state.pending_table_structure_fetch.take() {
|
if let Some((profile_name, table_name)) = app_state.pending_table_structure_fetch.take() {
|
||||||
if app_state.ui.show_add_logic {
|
if app_state.ui.show_add_logic {
|
||||||
if admin_state.add_logic_state.profile_name == profile_name &&
|
if admin_state.add_logic_state.profile_name == profile_name &&
|
||||||
@@ -488,47 +516,53 @@ pub async fn run_ui() -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let position_changed = form_state.current_position != position_before_event;
|
let current_position = app_state.form_state()
|
||||||
|
.map(|fs| fs.current_position)
|
||||||
|
.unwrap_or(1);
|
||||||
|
let position_changed = current_position != position_before_event;
|
||||||
let mut position_logic_needs_redraw = false;
|
let mut position_logic_needs_redraw = false;
|
||||||
|
|
||||||
if app_state.ui.show_form && !table_just_switched {
|
if app_state.ui.show_form && !table_just_switched {
|
||||||
if position_changed && !event_handler.is_edit_mode {
|
if position_changed && !event_handler.is_edit_mode {
|
||||||
position_logic_needs_redraw = true;
|
position_logic_needs_redraw = true;
|
||||||
|
|
||||||
if form_state.current_position > form_state.total_count {
|
if let Some(form_state) = app_state.form_state_mut() {
|
||||||
form_state.reset_to_empty();
|
if form_state.current_position > form_state.total_count {
|
||||||
event_handler.command_message = format!("New entry for {}.{}", form_state.profile_name, form_state.table_name);
|
form_state.reset_to_empty();
|
||||||
} else {
|
event_handler.command_message = format!("New entry for {}.{}", form_state.profile_name, form_state.table_name);
|
||||||
match UiService::load_table_data_by_position(&mut grpc_client, &mut form_state).await {
|
} else {
|
||||||
Ok(load_message) => {
|
match UiService::load_table_data_by_position(&mut grpc_client, form_state).await {
|
||||||
if event_handler.command_message.is_empty() || !load_message.starts_with("Error") {
|
Ok(load_message) => {
|
||||||
event_handler.command_message = load_message;
|
if event_handler.command_message.is_empty() || !load_message.starts_with("Error") {
|
||||||
|
event_handler.command_message = load_message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
event_handler.command_message = format!("Error loading data: {}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
|
||||||
event_handler.command_message = format!("Error loading data: {}", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let current_input_after_load_str = form_state.get_current_input();
|
||||||
|
let current_input_len_after_load = current_input_after_load_str.chars().count();
|
||||||
|
let max_cursor_pos = if current_input_len_after_load > 0 {
|
||||||
|
current_input_len_after_load.saturating_sub(1)
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
form_state.current_cursor_pos = event_handler.ideal_cursor_column.min(max_cursor_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
let current_input_after_load_str = form_state.get_current_input();
|
|
||||||
let current_input_len_after_load = current_input_after_load_str.chars().count();
|
|
||||||
let max_cursor_pos = if current_input_len_after_load > 0 {
|
|
||||||
current_input_len_after_load.saturating_sub(1)
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
|
||||||
form_state.current_cursor_pos = event_handler.ideal_cursor_column.min(max_cursor_pos);
|
|
||||||
|
|
||||||
} else if !position_changed && !event_handler.is_edit_mode {
|
} else if !position_changed && !event_handler.is_edit_mode {
|
||||||
let current_input_str = form_state.get_current_input();
|
if let Some(form_state) = app_state.form_state_mut() {
|
||||||
let current_input_len = current_input_str.chars().count();
|
let current_input_str = form_state.get_current_input();
|
||||||
let max_cursor_pos = if current_input_len > 0 {
|
let current_input_len = current_input_str.chars().count();
|
||||||
current_input_len.saturating_sub(1)
|
let max_cursor_pos = if current_input_len > 0 {
|
||||||
} else {
|
current_input_len.saturating_sub(1)
|
||||||
0
|
} else {
|
||||||
};
|
0
|
||||||
form_state.current_cursor_pos = event_handler.ideal_cursor_column.min(max_cursor_pos);
|
};
|
||||||
|
form_state.current_cursor_pos = event_handler.ideal_cursor_column.min(max_cursor_pos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if app_state.ui.show_register {
|
} else if app_state.ui.show_register {
|
||||||
if !event_handler.is_edit_mode {
|
if !event_handler.is_edit_mode {
|
||||||
@@ -587,10 +621,23 @@ pub async fn run_ui() -> Result<()> {
|
|||||||
AppMode::Command => { terminal.set_cursor_style(SetCursorStyle::SteadyUnderScore)?; terminal.show_cursor().context("Failed to show cursor in Command mode")?; }
|
AppMode::Command => { terminal.set_cursor_style(SetCursorStyle::SteadyUnderScore)?; terminal.show_cursor().context("Failed to show cursor in Command mode")?; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Temporarily work around borrow checker by extracting needed values
|
||||||
|
let current_dir = app_state.current_dir.clone();
|
||||||
|
|
||||||
|
// Since we can't borrow app_state both mutably and immutably,
|
||||||
|
// we'll need to either:
|
||||||
|
// 1. Modify render_ui to take just app_state and access form_state internally, OR
|
||||||
|
// 2. Extract the specific fields render_ui needs from app_state
|
||||||
|
|
||||||
|
// For now, using approach where we temporarily clone what we need
|
||||||
|
let form_state_clone = app_state.form_state().unwrap().clone();
|
||||||
|
|
||||||
terminal.draw(|f| {
|
terminal.draw(|f| {
|
||||||
|
// Use a mutable clone for rendering
|
||||||
|
let mut temp_form_state = form_state_clone.clone();
|
||||||
render_ui(
|
render_ui(
|
||||||
f,
|
f,
|
||||||
&mut form_state,
|
&mut temp_form_state,
|
||||||
&mut auth_state,
|
&mut auth_state,
|
||||||
&login_state,
|
&login_state,
|
||||||
®ister_state,
|
®ister_state,
|
||||||
@@ -603,10 +650,13 @@ pub async fn run_ui() -> Result<()> {
|
|||||||
event_handler.command_mode,
|
event_handler.command_mode,
|
||||||
&event_handler.command_message,
|
&event_handler.command_message,
|
||||||
&event_handler.navigation_state,
|
&event_handler.navigation_state,
|
||||||
&app_state.current_dir,
|
¤t_dir,
|
||||||
current_fps,
|
current_fps,
|
||||||
&app_state,
|
&app_state,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// If render_ui modified the form_state, we'd need to sync it back
|
||||||
|
// But typically render functions don't modify state, just read it
|
||||||
}).context("Terminal draw call failed")?;
|
}).context("Terminal draw call failed")?;
|
||||||
needs_redraw = false;
|
needs_redraw = false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user