more improvements
This commit is contained in:
@@ -8,7 +8,7 @@ license.workspace = true
|
||||
anyhow = { workspace = true }
|
||||
async-trait = "0.1.88"
|
||||
common = { path = "../common" }
|
||||
canvas = { path = "../canvas", features = ["gui", "suggestions"] }
|
||||
canvas = { path = "../canvas", features = ["gui", "suggestions", "cursor-style"] }
|
||||
|
||||
ratatui = { workspace = true }
|
||||
crossterm = { workspace = true }
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// src/components/form/form.rs
|
||||
use crate::config::colors::themes::Theme;
|
||||
use crate::state::app::state::AppState;
|
||||
use crate::state::pages::form::FormState;
|
||||
use ratatui::{
|
||||
layout::{Alignment, Constraint, Direction, Layout, Margin, Rect},
|
||||
@@ -8,19 +9,17 @@ use ratatui::{
|
||||
Frame,
|
||||
};
|
||||
use canvas::canvas::HighlightState;
|
||||
use canvas::{FormEditor, render_canvas_default, render_canvas, render_suggestions_dropdown, DefaultCanvasTheme};
|
||||
use canvas::{
|
||||
render_canvas, render_suggestions_dropdown, DefaultCanvasTheme, FormEditor,
|
||||
};
|
||||
|
||||
pub fn render_form(
|
||||
f: &mut Frame,
|
||||
area: Rect,
|
||||
form_state: &FormState,
|
||||
fields: &[&str], // no longer needed, FormEditor handles this
|
||||
current_field_idx: &usize, // no longer needed
|
||||
inputs: &[&String], // no longer needed
|
||||
app_state: &AppState,
|
||||
form_state: &FormState, // not needed directly anymore, editor holds it
|
||||
table_name: &str,
|
||||
theme: &Theme,
|
||||
is_edit_mode: bool, // FormEditor tracks mode internally
|
||||
highlight_state: &HighlightState,
|
||||
total_count: u64,
|
||||
current_position: u64,
|
||||
) {
|
||||
@@ -62,15 +61,9 @@ pub fn render_form(
|
||||
.alignment(Alignment::Left);
|
||||
f.render_widget(count_para, main_layout[0]);
|
||||
|
||||
// --- FORM RENDERING (Using new canvas API) ---
|
||||
let editor = FormEditor::new(form_state.clone());
|
||||
|
||||
let active_field_rect = render_canvas(
|
||||
f,
|
||||
main_layout[1],
|
||||
&editor,
|
||||
theme,
|
||||
);
|
||||
// --- FORM RENDERING (Using persistent FormEditor) ---
|
||||
if let Some(editor) = &app_state.form_editor {
|
||||
let active_field_rect = render_canvas(f, main_layout[1], editor, theme);
|
||||
|
||||
// --- SUGGESTIONS DROPDOWN ---
|
||||
if let Some(active_rect) = active_field_rect {
|
||||
@@ -79,7 +72,8 @@ pub fn render_form(
|
||||
main_layout[1],
|
||||
active_rect,
|
||||
&DefaultCanvasTheme,
|
||||
&editor,
|
||||
editor,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ use crate::modes::{
|
||||
};
|
||||
use crate::services::auth::AuthClient;
|
||||
use crate::services::grpc_client::GrpcClient;
|
||||
use canvas::FormEditor;
|
||||
use canvas::{FormEditor, AppMode as CanvasMode};
|
||||
use crate::state::{
|
||||
app::{
|
||||
buffer::{AppView, BufferState},
|
||||
@@ -42,7 +42,6 @@ use crate::ui::handlers::context::UiContext;
|
||||
use crate::ui::handlers::rat_state::UiStateHandler;
|
||||
use anyhow::Result;
|
||||
use common::proto::komp_ac::search::search_response::Hit;
|
||||
use crossterm::cursor::SetCursorStyle;
|
||||
use crossterm::event::KeyModifiers;
|
||||
use crossterm::event::{Event, KeyCode, KeyEvent};
|
||||
use tokio::sync::mpsc;
|
||||
@@ -695,10 +694,12 @@ impl EventHandler {
|
||||
else if config.get_read_only_action_for_key(key_code, modifiers).as_deref() == Some("enter_edit_mode_before")
|
||||
&& ModeManager::can_enter_edit_mode(current_mode)
|
||||
{
|
||||
if let Some(editor) = &mut app_state.form_editor {
|
||||
editor.enter_edit_mode();
|
||||
}
|
||||
self.is_edit_mode = true;
|
||||
self.edit_mode_cooldown = true;
|
||||
self.command_message = "Edit mode".to_string();
|
||||
terminal.set_cursor_style(SetCursorStyle::BlinkingBar)?;
|
||||
return Ok(EventOutcome::Ok(self.command_message.clone()));
|
||||
}
|
||||
else if config.get_read_only_action_for_key(key_code, modifiers).as_deref() == Some("enter_edit_mode_after")
|
||||
@@ -734,16 +735,21 @@ impl EventHandler {
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(editor) = &mut app_state.form_editor {
|
||||
editor.enter_edit_mode();
|
||||
}
|
||||
self.is_edit_mode = true;
|
||||
self.edit_mode_cooldown = true;
|
||||
app_state.ui.focus_outside_canvas = false;
|
||||
self.command_message = "Edit mode (after cursor)".to_string();
|
||||
terminal.set_cursor_style(SetCursorStyle::BlinkingBar)?;
|
||||
return Ok(EventOutcome::Ok(self.command_message.clone()));
|
||||
}
|
||||
else if config.get_read_only_action_for_key(key_code, modifiers) == Some("enter_command_mode")
|
||||
&& ModeManager::can_enter_command_mode(current_mode)
|
||||
{
|
||||
if let Some(editor) = &mut app_state.form_editor {
|
||||
editor.set_mode(CanvasMode::Command);
|
||||
}
|
||||
self.command_mode = true;
|
||||
self.command_input.clear();
|
||||
self.command_message.clear();
|
||||
@@ -772,25 +778,28 @@ impl EventHandler {
|
||||
|
||||
// Try canvas action for form first
|
||||
if app_state.ui.show_form {
|
||||
let mut editor = FormEditor::new(form_state.clone());
|
||||
if let Some(editor) = &mut app_state.form_editor {
|
||||
if let Ok(Some(canvas_message)) = self.handle_form_canvas_action(
|
||||
key_event,
|
||||
&mut editor,
|
||||
editor,
|
||||
config,
|
||||
false,
|
||||
).await {
|
||||
return Ok(EventOutcome::Ok(canvas_message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(EventOutcome::Ok(self.command_message.clone()));
|
||||
}
|
||||
|
||||
AppMode::Highlight => {
|
||||
if config.get_highlight_action_for_key(key_code, modifiers) == Some("exit_highlight_mode") {
|
||||
if let Some(editor) = &mut app_state.form_editor {
|
||||
editor.exit_highlight_mode();
|
||||
}
|
||||
self.highlight_state = HighlightState::Off;
|
||||
self.command_message = "Exited highlight mode".to_string();
|
||||
terminal.set_cursor_style(SetCursorStyle::SteadyBlock)?;
|
||||
return Ok(EventOutcome::Ok(self.command_message.clone()));
|
||||
} else if config.get_highlight_action_for_key(key_code, modifiers) == Some("enter_highlight_mode_linewise") {
|
||||
if let HighlightState::Characterwise { anchor } = self.highlight_state {
|
||||
@@ -827,10 +836,10 @@ impl EventHandler {
|
||||
|
||||
// Try canvas action for form first
|
||||
if app_state.ui.show_form {
|
||||
let mut editor = FormEditor::new(form_state.clone());
|
||||
if let Some(editor) = &mut app_state.form_editor {
|
||||
if let Ok(Some(canvas_message)) = self.handle_form_canvas_action(
|
||||
key_event,
|
||||
&mut editor,
|
||||
editor,
|
||||
config,
|
||||
true,
|
||||
).await {
|
||||
@@ -840,6 +849,7 @@ impl EventHandler {
|
||||
return Ok(EventOutcome::Ok(canvas_message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(EventOutcome::Ok(self.command_message.clone()));
|
||||
}
|
||||
@@ -850,6 +860,9 @@ impl EventHandler {
|
||||
self.command_message.clear();
|
||||
self.command_mode = false;
|
||||
self.key_sequence_tracker.reset();
|
||||
if let Some(editor) = &mut app_state.form_editor {
|
||||
editor.set_mode(CanvasMode::ReadOnly);
|
||||
}
|
||||
return Ok(EventOutcome::Ok(
|
||||
"Exited command mode".to_string(),
|
||||
));
|
||||
@@ -1079,6 +1092,9 @@ impl EventHandler {
|
||||
}
|
||||
}
|
||||
"force_quit" => {
|
||||
if let Some(editor) = &mut app_state.form_editor {
|
||||
editor.cleanup_cursor()?;
|
||||
}
|
||||
terminal.cleanup()?;
|
||||
Ok(EventOutcome::Exit(
|
||||
"Force exiting without saving.".to_string(),
|
||||
@@ -1106,6 +1122,9 @@ impl EventHandler {
|
||||
SaveOutcome::CreatedNew(_) => "New entry created.".to_string(),
|
||||
}
|
||||
};
|
||||
if let Some(editor) = &mut app_state.form_editor {
|
||||
editor.cleanup_cursor()?;
|
||||
}
|
||||
terminal.cleanup()?;
|
||||
Ok(EventOutcome::Exit(format!(
|
||||
"{}. Exiting application.",
|
||||
|
||||
@@ -7,6 +7,8 @@ use common::proto::komp_ac::table_structure::TableStructureResponse;
|
||||
use crate::modes::handlers::mode_manager::AppMode;
|
||||
use crate::state::app::search::SearchState;
|
||||
use crate::ui::handlers::context::DialogPurpose;
|
||||
use canvas::FormEditor;
|
||||
use crate::state::pages::form::FormState;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::sync::Arc;
|
||||
@@ -67,6 +69,8 @@ pub struct AppState {
|
||||
// UI preferences
|
||||
pub ui: UiState,
|
||||
|
||||
pub form_editor: Option<FormEditor<FormState>>,
|
||||
|
||||
#[cfg(feature = "ui-debug")]
|
||||
pub debug_state: Option<DebugState>,
|
||||
}
|
||||
@@ -86,6 +90,7 @@ impl AppState {
|
||||
pending_table_structure_fetch: None,
|
||||
search_state: None,
|
||||
ui: UiState::default(),
|
||||
form_editor: None,
|
||||
|
||||
#[cfg(feature = "ui-debug")]
|
||||
debug_state: None,
|
||||
|
||||
@@ -228,15 +228,6 @@ impl FormState {
|
||||
self.autocomplete_loading = false;
|
||||
}
|
||||
|
||||
// NEW: Add these methods to change modes
|
||||
pub fn set_edit_mode(&mut self) {
|
||||
self.app_mode = AppMode::Edit;
|
||||
}
|
||||
|
||||
pub fn set_readonly_mode(&mut self) {
|
||||
self.app_mode = AppMode::ReadOnly;
|
||||
}
|
||||
|
||||
// Legacy method compatibility
|
||||
pub fn fields(&self) -> Vec<&str> {
|
||||
self.fields
|
||||
|
||||
Reference in New Issue
Block a user