Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6833ac5fad | ||
|
|
3dff2ced6c | ||
|
|
ea7ff3796f | ||
|
|
310617d62b | ||
|
|
1d94e82f4b | ||
|
|
00dad5d673 | ||
|
|
414c6957e7 | ||
|
|
f127298e5a |
10
Cargo.lock
generated
10
Cargo.lock
generated
@@ -493,7 +493,7 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
|
||||
|
||||
[[package]]
|
||||
name = "canvas"
|
||||
version = "0.4.2"
|
||||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -584,7 +584,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "client"
|
||||
version = "0.4.2"
|
||||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -635,7 +635,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "common"
|
||||
version = "0.4.2"
|
||||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"prost",
|
||||
"prost-types",
|
||||
@@ -3022,7 +3022,7 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
|
||||
|
||||
[[package]]
|
||||
name = "search"
|
||||
version = "0.4.2"
|
||||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"common",
|
||||
@@ -3121,7 +3121,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "server"
|
||||
version = "0.4.2"
|
||||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bcrypt",
|
||||
|
||||
@@ -5,7 +5,7 @@ resolver = "2"
|
||||
[workspace.package]
|
||||
# TODO: idk how to do the name, fix later
|
||||
# name = "komp_ac"
|
||||
version = "0.4.2"
|
||||
version = "0.5.0"
|
||||
edition = "2021"
|
||||
license = "GPL-3.0-or-later"
|
||||
authors = ["Filip Priečinský <filippriec@gmail.com>"]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// src/components/common/find_file_palette.rs
|
||||
// src/bottom_panel/find_file_palette.rs
|
||||
|
||||
use crate::config::colors::themes::Theme;
|
||||
use crate::modes::general::command_navigation::NavigationState; // Corrected path
|
||||
97
client/src/bottom_panel/layout.rs
Normal file
97
client/src/bottom_panel/layout.rs
Normal file
@@ -0,0 +1,97 @@
|
||||
// src/bottom_panel/layout.rs
|
||||
|
||||
use ratatui::{layout::Constraint, layout::Rect, Frame};
|
||||
use crate::bottom_panel::{status_line::render_status_line, command_line::render_command_line};
|
||||
use crate::bottom_panel::find_file_palette;
|
||||
use crate::config::colors::themes::Theme;
|
||||
use crate::modes::general::command_navigation::NavigationState;
|
||||
use crate::state::app::state::AppState;
|
||||
|
||||
/// Calculate the layout constraints for the bottom panel (status line + command line/palette).
|
||||
pub fn bottom_panel_constraints(
|
||||
app_state: &AppState,
|
||||
navigation_state: &NavigationState,
|
||||
event_handler_command_mode_active: bool,
|
||||
) -> Vec<Constraint> {
|
||||
let mut status_line_height = 1;
|
||||
#[cfg(feature = "ui-debug")]
|
||||
{
|
||||
if let Some(debug_state) = &app_state.debug_state {
|
||||
if debug_state.is_error {
|
||||
status_line_height = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const PALETTE_OPTIONS_HEIGHT_FOR_LAYOUT: u16 = 15;
|
||||
let command_palette_area_height = if navigation_state.active {
|
||||
1 + PALETTE_OPTIONS_HEIGHT_FOR_LAYOUT
|
||||
} else if event_handler_command_mode_active {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let mut constraints = vec![Constraint::Length(status_line_height)];
|
||||
if command_palette_area_height > 0 {
|
||||
constraints.push(Constraint::Length(command_palette_area_height));
|
||||
}
|
||||
constraints
|
||||
}
|
||||
|
||||
/// Render the bottom panel (status line + command line/palette).
|
||||
pub fn render_bottom_panel(
|
||||
f: &mut Frame,
|
||||
root_chunks: &[Rect],
|
||||
chunk_idx: &mut usize,
|
||||
current_dir: &str,
|
||||
theme: &Theme,
|
||||
is_event_handler_edit_mode: bool,
|
||||
current_fps: f64,
|
||||
app_state: &AppState,
|
||||
navigation_state: &NavigationState,
|
||||
event_handler_command_input: &str,
|
||||
event_handler_command_mode_active: bool,
|
||||
event_handler_command_message: &str,
|
||||
) {
|
||||
// --- Status line area ---
|
||||
let status_line_area = root_chunks[*chunk_idx];
|
||||
*chunk_idx += 1;
|
||||
|
||||
// --- Command line / palette area ---
|
||||
let command_render_area = if root_chunks.len() > *chunk_idx {
|
||||
Some(root_chunks[*chunk_idx])
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if command_render_area.is_some() {
|
||||
*chunk_idx += 1;
|
||||
}
|
||||
|
||||
// --- Render status line ---
|
||||
render_status_line(
|
||||
f,
|
||||
status_line_area,
|
||||
current_dir,
|
||||
theme,
|
||||
is_event_handler_edit_mode,
|
||||
current_fps,
|
||||
app_state,
|
||||
);
|
||||
|
||||
// --- Render command line or palette ---
|
||||
if let Some(area) = command_render_area {
|
||||
if navigation_state.active {
|
||||
find_file_palette::render_find_file_palette(f, area, theme, navigation_state);
|
||||
} else if event_handler_command_mode_active {
|
||||
render_command_line(
|
||||
f,
|
||||
area,
|
||||
event_handler_command_input,
|
||||
true,
|
||||
theme,
|
||||
event_handler_command_message,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
6
client/src/bottom_panel/mod.rs
Normal file
6
client/src/bottom_panel/mod.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
// src/bottom_panel/mod.rs
|
||||
|
||||
pub mod status_line;
|
||||
pub mod command_line;
|
||||
pub mod layout;
|
||||
pub mod find_file_palette;
|
||||
@@ -5,10 +5,9 @@ use ratatui::{
|
||||
layout::Rect,
|
||||
style::Style,
|
||||
text::{Line, Span, Text},
|
||||
widgets::Paragraph,
|
||||
widgets::{Paragraph, Wrap},
|
||||
Frame,
|
||||
};
|
||||
use ratatui::widgets::Wrap;
|
||||
use std::path::Path;
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// src/functions/common/buffer.rs
|
||||
// src/buffer/functions/buffer.rs
|
||||
|
||||
use crate::state::app::buffer::BufferState;
|
||||
use crate::state::app::buffer::AppView;
|
||||
use crate::buffer::state::BufferState;
|
||||
use crate::buffer::state::AppView;
|
||||
|
||||
pub fn get_view_layer(view: &AppView) -> u8 {
|
||||
match view {
|
||||
20
client/src/buffer/logic.rs
Normal file
20
client/src/buffer/logic.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
// src/buffer/logic.rs
|
||||
use crossterm::event::{KeyCode, KeyModifiers};
|
||||
use crate::config::binds::config::Config;
|
||||
use crate::state::app::state::UiState;
|
||||
|
||||
/// Toggle the buffer list visibility based on keybindings.
|
||||
pub fn toggle_buffer_list(
|
||||
ui_state: &mut UiState,
|
||||
config: &Config,
|
||||
key: KeyCode,
|
||||
modifiers: KeyModifiers,
|
||||
) -> bool {
|
||||
if let Some(action) = config.get_common_action(key, modifiers) {
|
||||
if action == "toggle_buffer_list" {
|
||||
ui_state.show_buffer_list = !ui_state.show_buffer_list;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
11
client/src/buffer/mod.rs
Normal file
11
client/src/buffer/mod.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
// src/buffer/mod.rs
|
||||
|
||||
pub mod state;
|
||||
pub mod functions;
|
||||
pub mod ui;
|
||||
pub mod logic;
|
||||
|
||||
pub use state::{AppView, BufferState};
|
||||
pub use functions::*;
|
||||
pub use ui::render_buffer_list;
|
||||
pub use logic::toggle_buffer_list;
|
||||
@@ -1,4 +1,4 @@
|
||||
// src/state/app/buffer.rs
|
||||
// src/buffer/state/buffer.rs
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum AppView {
|
||||
@@ -1,7 +1,7 @@
|
||||
// src/components/handlers/buffer_list.rs
|
||||
// src/buffer/ui.rs
|
||||
|
||||
use crate::config::colors::themes::Theme;
|
||||
use crate::state::app::buffer::BufferState;
|
||||
use crate::buffer::state::BufferState;
|
||||
use crate::state::app::state::AppState; // Add this import
|
||||
use ratatui::{
|
||||
layout::{Alignment, Rect},
|
||||
@@ -11,7 +11,7 @@ use ratatui::{
|
||||
Frame,
|
||||
};
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
use crate::functions::common::buffer::get_view_layer;
|
||||
use crate::buffer::functions::get_view_layer;
|
||||
|
||||
pub fn render_buffer_list(
|
||||
f: &mut Frame,
|
||||
@@ -2,7 +2,7 @@
|
||||
use crate::config::colors::themes::Theme;
|
||||
use crate::state::app::state::AppState;
|
||||
use crate::state::pages::add_table::{AddTableFocus, AddTableState};
|
||||
use canvas::{render_canvas_default, render_canvas, FormEditor};
|
||||
use canvas::{render_canvas, FormEditor};
|
||||
use ratatui::{
|
||||
layout::{Alignment, Constraint, Direction, Layout, Rect},
|
||||
style::{Modifier, Style},
|
||||
|
||||
@@ -13,7 +13,7 @@ use ratatui::{
|
||||
widgets::{Block, BorderType, Borders, Paragraph},
|
||||
Frame,
|
||||
};
|
||||
use canvas::{FormEditor, render_canvas_default, render_canvas, render_suggestions_dropdown, DefaultCanvasTheme};
|
||||
use canvas::{FormEditor, render_canvas, render_suggestions_dropdown, DefaultCanvasTheme};
|
||||
|
||||
pub fn render_register(
|
||||
f: &mut Frame,
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
// src/components/common.rs
|
||||
pub mod command_line;
|
||||
pub mod status_line;
|
||||
|
||||
pub mod text_editor;
|
||||
pub mod background;
|
||||
pub mod dialog;
|
||||
pub mod autocomplete;
|
||||
pub mod search_palette;
|
||||
pub mod find_file_palette;
|
||||
|
||||
pub use command_line::*;
|
||||
pub use status_line::*;
|
||||
pub use text_editor::*;
|
||||
pub use background::*;
|
||||
pub use dialog::*;
|
||||
pub use autocomplete::*;
|
||||
pub use search_palette::*;
|
||||
pub use find_file_palette::*;
|
||||
|
||||
@@ -8,9 +8,8 @@ use ratatui::{
|
||||
widgets::{Block, Borders, Paragraph},
|
||||
Frame,
|
||||
};
|
||||
use canvas::canvas::HighlightState;
|
||||
use canvas::{
|
||||
render_canvas, render_suggestions_dropdown, DefaultCanvasTheme, FormEditor,
|
||||
render_canvas, render_suggestions_dropdown, DefaultCanvasTheme,
|
||||
};
|
||||
|
||||
pub fn render_form(
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
// src/components/handlers.rs
|
||||
pub mod sidebar;
|
||||
pub mod buffer_list;
|
||||
|
||||
pub use sidebar::*;
|
||||
pub use buffer_list::*;
|
||||
@@ -1,5 +1,4 @@
|
||||
// src/components/mod.rs
|
||||
pub mod handlers;
|
||||
pub mod intro;
|
||||
pub mod admin;
|
||||
pub mod common;
|
||||
@@ -7,7 +6,6 @@ pub mod form;
|
||||
pub mod auth;
|
||||
pub mod utils;
|
||||
|
||||
pub use handlers::*;
|
||||
pub use intro::*;
|
||||
pub use admin::*;
|
||||
pub use common::*;
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
// src/functions/common.rs
|
||||
|
||||
pub mod buffer;
|
||||
|
||||
pub use buffer::*;
|
||||
@@ -1,6 +1,5 @@
|
||||
// src/functions/mod.rs
|
||||
|
||||
pub mod common;
|
||||
pub mod modes;
|
||||
|
||||
pub use modes::*;
|
||||
|
||||
@@ -3,9 +3,8 @@ use crate::config::binds::config::{Config, EditorKeybindingMode};
|
||||
use crate::state::{
|
||||
app::state::AppState,
|
||||
pages::add_logic::{AddLogicFocus, AddLogicState},
|
||||
app::buffer::AppView,
|
||||
app::buffer::BufferState,
|
||||
};
|
||||
use crate::buffer::{AppView, BufferState};
|
||||
use crossterm::event::{KeyEvent, KeyCode, KeyModifiers};
|
||||
use crate::services::GrpcClient;
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
use crate::state::pages::admin::{AdminFocus, AdminState};
|
||||
use crate::state::app::state::AppState;
|
||||
use crate::config::binds::config::Config;
|
||||
use crate::state::app::buffer::{BufferState, AppView};
|
||||
use crate::buffer::state::{BufferState, AppView};
|
||||
use crate::state::pages::add_table::{AddTableState, LinkDefinition};
|
||||
use ratatui::widgets::ListState;
|
||||
use crate::state::pages::add_logic::{AddLogicState, AddLogicFocus}; // Added AddLogicFocus import
|
||||
|
||||
@@ -8,6 +8,10 @@ pub mod modes;
|
||||
pub mod functions;
|
||||
pub mod services;
|
||||
pub mod utils;
|
||||
pub mod buffer;
|
||||
pub mod sidebar;
|
||||
pub mod search;
|
||||
pub mod bottom_panel;
|
||||
|
||||
pub use ui::run_ui;
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
use crossterm::event::{KeyEvent, KeyCode, KeyModifiers};
|
||||
use crate::config::binds::config::Config;
|
||||
use crate::services::grpc_client::GrpcClient;
|
||||
use crate::state::pages::form::FormState;
|
||||
use crate::state::{app::state::AppState, pages::auth::LoginState, pages::auth::RegisterState};
|
||||
use crate::modes::common::commands::CommandHandler;
|
||||
use crate::tui::terminal::core::TerminalCore;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// src/modes/common/commands.rs
|
||||
use crate::tui::terminal::core::TerminalCore;
|
||||
use crate::state::app::state::AppState;
|
||||
use crate::state::pages::{form::FormState, auth::LoginState, auth::RegisterState};
|
||||
use crate::state::pages::{auth::LoginState, auth::RegisterState};
|
||||
use anyhow::Result;
|
||||
|
||||
pub struct CommandHandler;
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
use crossterm::event::{Event, KeyCode};
|
||||
use crate::config::binds::config::Config;
|
||||
use crate::ui::handlers::context::DialogPurpose;
|
||||
use crate::state::app::{state::AppState, buffer::AppView};
|
||||
use crate::state::app::buffer::BufferState;
|
||||
use crate::state::app::state::AppState;
|
||||
use crate::buffer::AppView;
|
||||
use crate::buffer::state::BufferState;
|
||||
use crate::state::pages::auth::{LoginState, RegisterState};
|
||||
use crate::state::pages::admin::AdminState;
|
||||
use crate::modes::handlers::event::EventOutcome;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// src/modes/handlers/event.rs
|
||||
use crate::config::binds::config::Config;
|
||||
use crate::config::binds::key_sequences::KeySequenceTracker;
|
||||
use crate::functions::common::buffer;
|
||||
use crate::buffer::{AppView, BufferState, switch_buffer, toggle_buffer_list};
|
||||
use crate::sidebar::toggle_sidebar;
|
||||
use crate::search::event::handle_search_palette_event;
|
||||
use crate::functions::modes::navigation::add_logic_nav;
|
||||
use crate::functions::modes::navigation::add_logic_nav::SaveLogicResultSender;
|
||||
use crate::functions::modes::navigation::add_table_nav::SaveTableResultSender;
|
||||
@@ -16,11 +18,9 @@ use crate::modes::{
|
||||
};
|
||||
use crate::services::auth::AuthClient;
|
||||
use crate::services::grpc_client::GrpcClient;
|
||||
use canvas::{FormEditor, AppMode as CanvasMode};
|
||||
use canvas::AppMode as CanvasMode;
|
||||
use crate::state::{
|
||||
app::{
|
||||
buffer::{AppView, BufferState},
|
||||
search::SearchState,
|
||||
state::AppState,
|
||||
},
|
||||
pages::{
|
||||
@@ -30,6 +30,7 @@ use crate::state::{
|
||||
intro::IntroState,
|
||||
},
|
||||
};
|
||||
use crate::search::state::SearchState;
|
||||
use crate::tui::functions::common::login::LoginResult;
|
||||
use crate::tui::functions::common::register::RegisterResult;
|
||||
use crate::tui::{
|
||||
@@ -38,15 +39,12 @@ use crate::tui::{
|
||||
{admin, intro},
|
||||
};
|
||||
use crate::ui::handlers::context::UiContext;
|
||||
use crate::ui::handlers::rat_state::UiStateHandler;
|
||||
use canvas::KeyEventOutcome;
|
||||
use anyhow::Result;
|
||||
use common::proto::komp_ac::search::search_response::Hit;
|
||||
use crossterm::event::KeyModifiers;
|
||||
use crossterm::event::{Event, KeyCode, KeyEvent};
|
||||
use crossterm::event::{Event, KeyCode};
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::sync::mpsc::unbounded_channel;
|
||||
use tracing::{error, info};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum EventOutcome {
|
||||
@@ -216,132 +214,6 @@ impl EventHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// This function handles state changes.
|
||||
async fn handle_search_palette_event(
|
||||
&mut self,
|
||||
key_event: KeyEvent,
|
||||
app_state: &mut AppState,
|
||||
) -> Result<EventOutcome> {
|
||||
let mut should_close = false;
|
||||
let mut outcome_message = String::new();
|
||||
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() {
|
||||
match key_event.code {
|
||||
KeyCode::Esc => {
|
||||
should_close = true;
|
||||
outcome_message = "Search cancelled".to_string();
|
||||
(None, None)
|
||||
}
|
||||
KeyCode::Enter => {
|
||||
if let Some(selected_hit) =
|
||||
search_state.results.get(search_state.selected_index)
|
||||
{
|
||||
if let Ok(data) = serde_json::from_str::<
|
||||
std::collections::HashMap<String, String>,
|
||||
>(&selected_hit.content_json)
|
||||
{
|
||||
(Some(data), Some(selected_hit.id))
|
||||
} else {
|
||||
(None, None)
|
||||
}
|
||||
} else {
|
||||
(None, None)
|
||||
}
|
||||
}
|
||||
KeyCode::Up => {
|
||||
search_state.previous_result();
|
||||
(None, None)
|
||||
}
|
||||
KeyCode::Down => {
|
||||
search_state.next_result();
|
||||
(None, None)
|
||||
}
|
||||
KeyCode::Char(c) => {
|
||||
search_state.input.insert(search_state.cursor_position, c);
|
||||
search_state.cursor_position += 1;
|
||||
trigger_search = true;
|
||||
(None, None)
|
||||
}
|
||||
KeyCode::Backspace => {
|
||||
if search_state.cursor_position > 0 {
|
||||
search_state.cursor_position -= 1;
|
||||
search_state.input.remove(search_state.cursor_position);
|
||||
trigger_search = true;
|
||||
}
|
||||
(None, None)
|
||||
}
|
||||
KeyCode::Left => {
|
||||
search_state.cursor_position =
|
||||
search_state.cursor_position.saturating_sub(1);
|
||||
(None, None)
|
||||
}
|
||||
KeyCode::Right => {
|
||||
if search_state.cursor_position < search_state.input.len() {
|
||||
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 let Some(search_state) = app_state.search_state.as_mut() {
|
||||
search_state.is_loading = true;
|
||||
search_state.results.clear();
|
||||
search_state.selected_index = 0;
|
||||
|
||||
let query = search_state.input.clone();
|
||||
let table_name = search_state.table_name.clone();
|
||||
let sender = self.search_result_sender.clone();
|
||||
let mut grpc_client = self.grpc_client.clone();
|
||||
|
||||
info!("--- 1. Spawning search task for query: '{}' ---", query);
|
||||
tokio::spawn(async move {
|
||||
info!("--- 2. Background task started. ---");
|
||||
match grpc_client.search_table(table_name, query).await {
|
||||
Ok(response) => {
|
||||
info!(
|
||||
"--- 3a. gRPC call successful. Found {} hits. ---",
|
||||
response.hits.len()
|
||||
);
|
||||
let _ = sender.send(response.hits);
|
||||
}
|
||||
Err(e) => {
|
||||
error!("--- 3b. gRPC call failed: {:?} ---", e);
|
||||
let _ = sender.send(vec![]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if should_close {
|
||||
app_state.search_state = None;
|
||||
app_state.ui.show_search_palette = false;
|
||||
app_state.ui.focus_outside_canvas = false;
|
||||
}
|
||||
|
||||
Ok(EventOutcome::Ok(outcome_message))
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn handle_event(
|
||||
&mut self,
|
||||
@@ -359,10 +231,17 @@ impl EventHandler {
|
||||
) -> Result<EventOutcome> {
|
||||
if app_state.ui.show_search_palette {
|
||||
if let Event::Key(key_event) = event {
|
||||
return self.handle_search_palette_event(key_event, app_state).await;
|
||||
if let Some(message) = handle_search_palette_event(
|
||||
key_event,
|
||||
app_state,
|
||||
&mut self.grpc_client,
|
||||
self.search_result_sender.clone(),
|
||||
).await? {
|
||||
return Ok(EventOutcome::Ok(message));
|
||||
}
|
||||
return Ok(EventOutcome::Ok(String::new()));
|
||||
}
|
||||
}
|
||||
|
||||
let mut current_mode =
|
||||
ModeManager::derive_mode(app_state, self, admin_state);
|
||||
@@ -436,7 +315,7 @@ impl EventHandler {
|
||||
let key_code = key_event.code;
|
||||
let modifiers = key_event.modifiers;
|
||||
|
||||
if UiStateHandler::toggle_sidebar(
|
||||
if toggle_sidebar(
|
||||
&mut app_state.ui,
|
||||
config,
|
||||
key_code,
|
||||
@@ -452,7 +331,7 @@ impl EventHandler {
|
||||
);
|
||||
return Ok(EventOutcome::Ok(message));
|
||||
}
|
||||
if UiStateHandler::toggle_buffer_list(
|
||||
if toggle_buffer_list(
|
||||
&mut app_state.ui,
|
||||
config,
|
||||
key_code,
|
||||
@@ -477,14 +356,14 @@ impl EventHandler {
|
||||
) {
|
||||
match action {
|
||||
"next_buffer" => {
|
||||
if buffer::switch_buffer(buffer_state, true) {
|
||||
if switch_buffer(buffer_state, true) {
|
||||
return Ok(EventOutcome::Ok(
|
||||
"Switched to next buffer".to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
"previous_buffer" => {
|
||||
if buffer::switch_buffer(buffer_state, false) {
|
||||
if switch_buffer(buffer_state, false) {
|
||||
return Ok(EventOutcome::Ok(
|
||||
"Switched to previous buffer".to_string(),
|
||||
));
|
||||
|
||||
@@ -3,7 +3,6 @@ use crate::state::app::state::AppState;
|
||||
use crate::modes::handlers::event::EventHandler;
|
||||
use crate::state::pages::add_logic::AddLogicFocus;
|
||||
use crate::state::pages::admin::AdminState;
|
||||
use canvas::AppMode as CanvasMode;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum AppMode {
|
||||
|
||||
@@ -7,4 +7,3 @@ pub mod canvas;
|
||||
pub use handlers::*;
|
||||
pub use general::*;
|
||||
pub use common::*;
|
||||
pub use canvas::*;
|
||||
|
||||
106
client/src/search/event.rs
Normal file
106
client/src/search/event.rs
Normal file
@@ -0,0 +1,106 @@
|
||||
// src/search/event.rs
|
||||
use crate::state::app::state::AppState;
|
||||
use crate::services::grpc_client::GrpcClient;
|
||||
use common::proto::komp_ac::search::search_response::Hit;
|
||||
use crossterm::event::KeyCode;
|
||||
use tokio::sync::mpsc;
|
||||
use tracing::{error, info};
|
||||
use std::collections::HashMap;
|
||||
use anyhow::Result;
|
||||
|
||||
pub async fn handle_search_palette_event(
|
||||
key_event: crossterm::event::KeyEvent,
|
||||
app_state: &mut AppState,
|
||||
grpc_client: &mut GrpcClient,
|
||||
search_result_sender: mpsc::UnboundedSender<Vec<Hit>>,
|
||||
) -> Result<Option<String>> {
|
||||
let mut should_close = false;
|
||||
let mut outcome_message = None;
|
||||
let mut trigger_search = false;
|
||||
|
||||
if let Some(search_state) = app_state.search_state.as_mut() {
|
||||
match key_event.code {
|
||||
KeyCode::Esc => {
|
||||
should_close = true;
|
||||
outcome_message = Some("Search cancelled".to_string());
|
||||
}
|
||||
KeyCode::Enter => {
|
||||
// Step 1: Extract the data we need while holding the borrow
|
||||
let maybe_data = search_state
|
||||
.results
|
||||
.get(search_state.selected_index)
|
||||
.map(|hit| (hit.id, hit.content_json.clone()));
|
||||
|
||||
// Step 2: Process outside the borrow
|
||||
if let Some((id, content_json)) = maybe_data {
|
||||
if let Ok(data) = serde_json::from_str::<HashMap<String, String>>(&content_json) {
|
||||
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 = Some(format!("Loaded record ID {}", id));
|
||||
}
|
||||
}
|
||||
}
|
||||
KeyCode::Up => search_state.previous_result(),
|
||||
KeyCode::Down => search_state.next_result(),
|
||||
KeyCode::Char(c) => {
|
||||
search_state.input.insert(search_state.cursor_position, c);
|
||||
search_state.cursor_position += 1;
|
||||
trigger_search = true;
|
||||
}
|
||||
KeyCode::Backspace => {
|
||||
if search_state.cursor_position > 0 {
|
||||
search_state.cursor_position -= 1;
|
||||
search_state.input.remove(search_state.cursor_position);
|
||||
trigger_search = true;
|
||||
}
|
||||
}
|
||||
KeyCode::Left => {
|
||||
search_state.cursor_position =
|
||||
search_state.cursor_position.saturating_sub(1);
|
||||
}
|
||||
KeyCode::Right => {
|
||||
if search_state.cursor_position < search_state.input.len() {
|
||||
search_state.cursor_position += 1;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if trigger_search {
|
||||
if let Some(search_state) = app_state.search_state.as_mut() {
|
||||
search_state.is_loading = true;
|
||||
search_state.results.clear();
|
||||
search_state.selected_index = 0;
|
||||
|
||||
let query = search_state.input.clone();
|
||||
let table_name = search_state.table_name.clone();
|
||||
let sender = search_result_sender.clone();
|
||||
let mut grpc_client = grpc_client.clone();
|
||||
|
||||
info!("Spawning search task for query: '{}'", query);
|
||||
tokio::spawn(async move {
|
||||
match grpc_client.search_table(table_name, query).await {
|
||||
Ok(response) => {
|
||||
let _ = sender.send(response.hits);
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Search failed: {:?}", e);
|
||||
let _ = sender.send(vec![]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if should_close {
|
||||
app_state.search_state = None;
|
||||
app_state.ui.show_search_palette = false;
|
||||
app_state.ui.focus_outside_canvas = false;
|
||||
}
|
||||
|
||||
Ok(outcome_message)
|
||||
}
|
||||
31
client/src/search/grpc.rs
Normal file
31
client/src/search/grpc.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
// src/search/grpc.rs
|
||||
|
||||
use common::proto::komp_ac::search::{
|
||||
searcher_client::SearcherClient, SearchRequest, SearchResponse,
|
||||
};
|
||||
use tonic::transport::Channel;
|
||||
use anyhow::Result;
|
||||
|
||||
/// Internal search gRPC wrapper
|
||||
#[derive(Clone)]
|
||||
pub struct SearchGrpc {
|
||||
client: SearcherClient<Channel>,
|
||||
}
|
||||
|
||||
impl SearchGrpc {
|
||||
pub fn new(channel: Channel) -> Self {
|
||||
Self {
|
||||
client: SearcherClient::new(channel),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn search_table(
|
||||
&mut self,
|
||||
table_name: String,
|
||||
query: String,
|
||||
) -> Result<SearchResponse> {
|
||||
let request = tonic::Request::new(SearchRequest { table_name, query });
|
||||
let response = self.client.search_table(request).await?;
|
||||
Ok(response.into_inner())
|
||||
}
|
||||
}
|
||||
9
client/src/search/mod.rs
Normal file
9
client/src/search/mod.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
// src/search/mod.rs
|
||||
|
||||
pub mod state;
|
||||
pub mod ui;
|
||||
pub mod event;
|
||||
pub mod grpc;
|
||||
|
||||
pub use ui::*;
|
||||
pub use grpc::SearchGrpc;
|
||||
@@ -1,4 +1,4 @@
|
||||
// src/state/app/search.rs
|
||||
// src/search/state.rs
|
||||
|
||||
use common::proto::komp_ac::search::search_response::Hit;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// src/components/common/search_palette.rs
|
||||
// src/search/ui.rs
|
||||
|
||||
use crate::config::colors::themes::Theme;
|
||||
use crate::state::app::search::SearchState;
|
||||
use crate::search::state::SearchState;
|
||||
use ratatui::{
|
||||
layout::{Constraint, Direction, Layout, Rect},
|
||||
style::{Modifier, Style},
|
||||
@@ -22,9 +22,8 @@ use common::proto::komp_ac::tables_data::{
|
||||
PostTableDataRequest, PostTableDataResponse, PutTableDataRequest,
|
||||
PutTableDataResponse,
|
||||
};
|
||||
use common::proto::komp_ac::search::{
|
||||
searcher_client::SearcherClient, SearchRequest, SearchResponse,
|
||||
};
|
||||
use crate::search::SearchGrpc;
|
||||
use common::proto::komp_ac::search::SearchResponse;
|
||||
use anyhow::{Context, Result};
|
||||
use std::collections::HashMap;
|
||||
use tonic::transport::Channel;
|
||||
@@ -36,7 +35,7 @@ pub struct GrpcClient {
|
||||
table_definition_client: TableDefinitionClient<Channel>,
|
||||
table_script_client: TableScriptClient<Channel>,
|
||||
tables_data_client: TablesDataClient<Channel>,
|
||||
search_client: SearcherClient<Channel>,
|
||||
search_client: SearchGrpc,
|
||||
}
|
||||
|
||||
impl GrpcClient {
|
||||
@@ -52,7 +51,7 @@ impl GrpcClient {
|
||||
TableDefinitionClient::new(channel.clone());
|
||||
let table_script_client = TableScriptClient::new(channel.clone());
|
||||
let tables_data_client = TablesDataClient::new(channel.clone());
|
||||
let search_client = SearcherClient::new(channel.clone());
|
||||
let search_client = SearchGrpc::new(channel.clone());
|
||||
|
||||
Ok(Self {
|
||||
table_structure_client,
|
||||
@@ -247,11 +246,6 @@ impl GrpcClient {
|
||||
table_name: String,
|
||||
query: String,
|
||||
) -> Result<SearchResponse> {
|
||||
let request = tonic::Request::new(SearchRequest { table_name, query });
|
||||
let response = self
|
||||
.search_client
|
||||
.search_table(request)
|
||||
.await?;
|
||||
Ok(response.into_inner())
|
||||
self.search_client.search_table(table_name, query).await
|
||||
}
|
||||
}
|
||||
|
||||
21
client/src/sidebar/logic.rs
Normal file
21
client/src/sidebar/logic.rs
Normal file
@@ -0,0 +1,21 @@
|
||||
// src/sidebar/state.rs
|
||||
use crossterm::event::{KeyCode, KeyModifiers};
|
||||
use crate::config::binds::config::Config;
|
||||
use crate::state::app::state::UiState;
|
||||
|
||||
pub fn toggle_sidebar(
|
||||
ui_state: &mut UiState,
|
||||
config: &Config,
|
||||
key: KeyCode,
|
||||
modifiers: KeyModifiers,
|
||||
) -> bool {
|
||||
if let Some(action) =
|
||||
config.get_action_for_key_in_mode(&config.keybindings.common, key, modifiers)
|
||||
{
|
||||
if action == "toggle_sidebar" {
|
||||
ui_state.show_sidebar = !ui_state.show_sidebar;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
7
client/src/sidebar/mod.rs
Normal file
7
client/src/sidebar/mod.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
// src/sidebar/mod.rs
|
||||
|
||||
pub mod ui;
|
||||
pub mod logic;
|
||||
|
||||
pub use ui::{calculate_sidebar_layout, render_sidebar};
|
||||
pub use logic::toggle_sidebar;
|
||||
@@ -1,4 +1,4 @@
|
||||
// src/components/handlers/sidebar.rs
|
||||
// src/sidebar/ui.rs
|
||||
use ratatui::{
|
||||
widgets::{Block, List, ListItem},
|
||||
layout::{Rect, Direction, Layout, Constraint},
|
||||
@@ -1,5 +1,3 @@
|
||||
// src/state/app.rs
|
||||
|
||||
pub mod state;
|
||||
pub mod buffer;
|
||||
pub mod search;
|
||||
|
||||
@@ -5,7 +5,7 @@ use common::proto::komp_ac::table_definition::ProfileTreeResponse;
|
||||
// NEW: Import the types we need for the cache
|
||||
use common::proto::komp_ac::table_structure::TableStructureResponse;
|
||||
use crate::modes::handlers::mode_manager::AppMode;
|
||||
use crate::state::app::search::SearchState;
|
||||
use crate::search::state::SearchState;
|
||||
use crate::ui::handlers::context::DialogPurpose;
|
||||
use crate::state::pages::form::FormState;
|
||||
use crate::config::binds::Config;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// src/state/pages/add_table.rs
|
||||
|
||||
use canvas::{DataProvider, CanvasAction, AppMode};
|
||||
use canvas::{DataProvider, AppMode};
|
||||
use ratatui::widgets::TableState;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// src/state/pages/auth.rs
|
||||
use canvas::{DataProvider, AppMode, SuggestionItem};
|
||||
use canvas::{DataProvider, AppMode};
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
lazy_static! {
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
// src/state/pages/form.rs
|
||||
|
||||
use crate::config::colors::themes::Theme;
|
||||
use canvas::{DataProvider, AppMode, EditorState, FormEditor};
|
||||
use canvas::{DataProvider, AppMode};
|
||||
use common::proto::komp_ac::search::search_response::Hit;
|
||||
use ratatui::layout::Rect;
|
||||
use ratatui::Frame;
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn json_value_to_string(value: &serde_json::Value) -> String {
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::services::auth::AuthClient;
|
||||
use crate::state::pages::auth::AuthState;
|
||||
use crate::state::pages::auth::LoginState;
|
||||
use crate::state::app::state::AppState;
|
||||
use crate::state::app::buffer::{AppView, BufferState};
|
||||
use crate::buffer::state::{AppView, BufferState};
|
||||
use crate::config::storage::storage::{StoredAuthData, save_auth_data};
|
||||
use crate::ui::handlers::context::DialogPurpose;
|
||||
use common::proto::komp_ac::auth::LoginResponse;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
use crate::config::storage::delete_auth_data;
|
||||
use crate::state::pages::auth::AuthState;
|
||||
use crate::state::app::state::AppState;
|
||||
use crate::state::app::buffer::{AppView, BufferState};
|
||||
use crate::buffer::state::{AppView, BufferState};
|
||||
use crate::ui::handlers::context::DialogPurpose;
|
||||
use tracing::{error, info};
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use crate::state::{
|
||||
app::state::AppState,
|
||||
};
|
||||
use crate::ui::handlers::context::DialogPurpose;
|
||||
use crate::state::app::buffer::{AppView, BufferState};
|
||||
use crate::buffer::state::{AppView, BufferState};
|
||||
use common::proto::komp_ac::auth::AuthResponse;
|
||||
use anyhow::Context;
|
||||
use tokio::spawn;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// src/tui/functions/intro.rs
|
||||
use crate::state::app::state::AppState;
|
||||
use crate::state::app::buffer::{AppView, BufferState};
|
||||
use crate::buffer::state::{AppView, BufferState};
|
||||
|
||||
/// Handles intro screen selection by updating view history and managing focus state.
|
||||
/// 0: Continue (restores last form or default)
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
|
||||
pub mod ui;
|
||||
pub mod render;
|
||||
pub mod rat_state;
|
||||
pub mod context;
|
||||
|
||||
pub use ui::run_ui;
|
||||
pub use rat_state::*;
|
||||
pub use context::*;
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
// client/src/ui/handlers/rat_state.rs
|
||||
use crossterm::event::{KeyCode, KeyModifiers};
|
||||
use crate::config::binds::config::Config;
|
||||
use crate::state::app::state::UiState;
|
||||
|
||||
pub struct UiStateHandler;
|
||||
|
||||
impl UiStateHandler {
|
||||
pub fn toggle_sidebar(
|
||||
ui_state: &mut UiState,
|
||||
config: &Config,
|
||||
key: KeyCode,
|
||||
modifiers: KeyModifiers,
|
||||
) -> bool {
|
||||
if let Some(action) = config.get_action_for_key_in_mode(&config.keybindings.common, key, modifiers) {
|
||||
if action == "toggle_sidebar" {
|
||||
ui_state.show_sidebar = !ui_state.show_sidebar;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn toggle_buffer_list(
|
||||
ui_state: &mut UiState,
|
||||
config: &Config,
|
||||
key: KeyCode,
|
||||
modifiers: KeyModifiers,
|
||||
) -> bool {
|
||||
if let Some(action) = config.get_common_action(key, modifiers) {
|
||||
if action == "toggle_buffer_list" {
|
||||
ui_state.show_buffer_list = !ui_state.show_buffer_list;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
@@ -5,18 +5,16 @@ use crate::components::{
|
||||
admin::render_add_table,
|
||||
auth::{login::render_login, register::render_register},
|
||||
common::dialog::render_dialog,
|
||||
common::find_file_palette,
|
||||
common::search_palette::render_search_palette,
|
||||
handlers::sidebar::{self, calculate_sidebar_layout},
|
||||
intro::intro::render_intro,
|
||||
render_background,
|
||||
render_buffer_list,
|
||||
render_command_line,
|
||||
render_status_line,
|
||||
};
|
||||
use crate::bottom_panel::{command_line::render_command_line, status_line::render_status_line, find_file_palette};
|
||||
use crate::sidebar::{calculate_sidebar_layout, render_sidebar};
|
||||
use crate::buffer::render_buffer_list;
|
||||
use crate::search::render_search_palette;
|
||||
use crate::config::colors::themes::Theme;
|
||||
use crate::modes::general::command_navigation::NavigationState;
|
||||
use crate::state::app::buffer::BufferState;
|
||||
use crate::buffer::state::BufferState;
|
||||
use crate::state::app::state::AppState;
|
||||
use crate::state::pages::admin::AdminState;
|
||||
use crate::state::pages::auth::AuthState;
|
||||
@@ -24,6 +22,7 @@ use crate::state::pages::auth::LoginState;
|
||||
use crate::state::pages::auth::RegisterState;
|
||||
use crate::state::pages::form::FormState;
|
||||
use crate::state::pages::intro::IntroState;
|
||||
use crate::bottom_panel::layout::{bottom_panel_constraints, render_bottom_panel};
|
||||
use crate::components::render_form;
|
||||
use ratatui::{
|
||||
layout::{Constraint, Direction, Layout},
|
||||
@@ -52,38 +51,15 @@ pub fn render_ui(
|
||||
) {
|
||||
render_background(f, f.area(), theme);
|
||||
|
||||
// --- START DYNAMIC LAYOUT LOGIC ---
|
||||
let mut status_line_height = 1;
|
||||
#[cfg(feature = "ui-debug")]
|
||||
{
|
||||
if let Some(debug_state) = &app_state.debug_state {
|
||||
if debug_state.is_error {
|
||||
status_line_height = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
// --- END DYNAMIC LAYOUT LOGIC ---
|
||||
|
||||
const PALETTE_OPTIONS_HEIGHT_FOR_LAYOUT: u16 = 15;
|
||||
|
||||
let mut bottom_area_constraints: Vec<Constraint> = vec![Constraint::Length(status_line_height)];
|
||||
let command_palette_area_height = if navigation_state.active {
|
||||
1 + PALETTE_OPTIONS_HEIGHT_FOR_LAYOUT
|
||||
} else if event_handler_command_mode_active {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
if command_palette_area_height > 0 {
|
||||
bottom_area_constraints.push(Constraint::Length(command_palette_area_height));
|
||||
}
|
||||
|
||||
let mut main_layout_constraints = vec![Constraint::Min(1)];
|
||||
if app_state.ui.show_buffer_list {
|
||||
main_layout_constraints.insert(0, Constraint::Length(1));
|
||||
}
|
||||
main_layout_constraints.extend(bottom_area_constraints);
|
||||
main_layout_constraints.extend(bottom_panel_constraints(
|
||||
app_state,
|
||||
navigation_state,
|
||||
event_handler_command_mode_active,
|
||||
));
|
||||
|
||||
let root_chunks = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
@@ -102,19 +78,6 @@ pub fn render_ui(
|
||||
let main_content_area = root_chunks[chunk_idx];
|
||||
chunk_idx += 1;
|
||||
|
||||
let status_line_area = root_chunks[chunk_idx];
|
||||
chunk_idx += 1;
|
||||
|
||||
let command_render_area = if command_palette_area_height > 0 {
|
||||
if root_chunks.len() > chunk_idx {
|
||||
Some(root_chunks[chunk_idx])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if app_state.ui.show_intro {
|
||||
render_intro(f, intro_state, main_content_area, theme);
|
||||
} else if app_state.ui.show_register {
|
||||
@@ -168,7 +131,7 @@ pub fn render_ui(
|
||||
let (sidebar_area, form_actual_area) =
|
||||
calculate_sidebar_layout(app_state.ui.show_sidebar, main_content_area);
|
||||
if let Some(sidebar_rect) = sidebar_area {
|
||||
sidebar::render_sidebar(
|
||||
render_sidebar(
|
||||
f,
|
||||
sidebar_rect,
|
||||
theme,
|
||||
@@ -209,36 +172,6 @@ pub fn render_ui(
|
||||
render_buffer_list(f, area, theme, buffer_state, app_state);
|
||||
}
|
||||
|
||||
render_status_line(
|
||||
f,
|
||||
status_line_area,
|
||||
current_dir,
|
||||
theme,
|
||||
is_event_handler_edit_mode,
|
||||
current_fps,
|
||||
app_state,
|
||||
);
|
||||
|
||||
if let Some(palette_or_command_area) = command_render_area {
|
||||
if navigation_state.active {
|
||||
find_file_palette::render_find_file_palette(
|
||||
f,
|
||||
palette_or_command_area,
|
||||
theme,
|
||||
navigation_state,
|
||||
);
|
||||
} else if event_handler_command_mode_active {
|
||||
render_command_line(
|
||||
f,
|
||||
palette_or_command_area,
|
||||
event_handler_command_input,
|
||||
true,
|
||||
theme,
|
||||
event_handler_command_message,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// This block now correctly handles drawing popups over any view.
|
||||
if app_state.ui.show_search_palette {
|
||||
if let Some(search_state) = &app_state.search_state {
|
||||
@@ -256,4 +189,19 @@ pub fn render_ui(
|
||||
app_state.ui.dialog.is_loading,
|
||||
);
|
||||
}
|
||||
|
||||
render_bottom_panel(
|
||||
f,
|
||||
&root_chunks,
|
||||
&mut chunk_idx,
|
||||
current_dir,
|
||||
theme,
|
||||
is_event_handler_edit_mode,
|
||||
current_fps,
|
||||
app_state,
|
||||
navigation_state,
|
||||
event_handler_command_input,
|
||||
event_handler_command_mode_active,
|
||||
event_handler_command_message,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@ use crate::state::pages::auth::RegisterState;
|
||||
use crate::state::pages::admin::AdminState;
|
||||
use crate::state::pages::admin::AdminFocus;
|
||||
use crate::state::pages::intro::IntroState;
|
||||
use crate::state::app::buffer::BufferState;
|
||||
use crate::state::app::buffer::AppView;
|
||||
use crate::buffer::state::BufferState;
|
||||
use crate::buffer::state::AppView;
|
||||
use crate::state::app::state::AppState;
|
||||
use crate::tui::terminal::{EventReader, TerminalCore};
|
||||
use crate::ui::handlers::render::render_ui;
|
||||
@@ -32,7 +32,8 @@ use crossterm::cursor::SetCursorStyle;
|
||||
use crossterm::event as crossterm_event;
|
||||
use tracing::{error, info, warn};
|
||||
use tokio::sync::mpsc;
|
||||
use std::time::{Instant, Duration};
|
||||
use std::time::Instant;
|
||||
use std::time::Duration;
|
||||
#[cfg(feature = "ui-debug")]
|
||||
use crate::state::app::state::DebugState;
|
||||
#[cfg(feature = "ui-debug")]
|
||||
|
||||
Reference in New Issue
Block a user