post doesnt work, but refactored code displays the autocomplete at least, needs fix
This commit is contained in:
@@ -1,30 +1,18 @@
|
||||
// src/components/common/autocomplete.rs
|
||||
|
||||
use common::proto::multieko2::search::search_response::Hit;
|
||||
use crate::config::colors::themes::Theme;
|
||||
use crate::state::pages::form::FormState;
|
||||
use common::proto::multieko2::search::search_response::Hit;
|
||||
use ratatui::{
|
||||
layout::Rect,
|
||||
style::{Color, Modifier, Style},
|
||||
widgets::{Block, List, ListItem, ListState},
|
||||
Frame,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
|
||||
/// Converts a serde_json::Value into a displayable String.
|
||||
/// Handles String, Number, and Bool variants. Returns an empty string for Null and others.
|
||||
fn json_value_to_string(value: &serde_json::Value) -> String {
|
||||
match value {
|
||||
serde_json::Value::String(s) => s.clone(),
|
||||
serde_json::Value::Number(n) => n.to_string(),
|
||||
serde_json::Value::Bool(b) => b.to_string(),
|
||||
// Return an empty string for Null, Array, or Object so we can filter them out.
|
||||
_ => String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Renders an opaque dropdown list for simple string-based suggestions.
|
||||
/// This function remains unchanged.
|
||||
/// THIS IS THE RESTORED FUNCTION.
|
||||
pub fn render_autocomplete_dropdown(
|
||||
f: &mut Frame,
|
||||
input_rect: Rect,
|
||||
@@ -84,22 +72,22 @@ pub fn render_autocomplete_dropdown(
|
||||
.collect();
|
||||
|
||||
let list = List::new(items);
|
||||
let mut profile_list_state = ListState::default();
|
||||
profile_list_state.select(selected_index);
|
||||
let mut list_state = ListState::default();
|
||||
list_state.select(selected_index);
|
||||
|
||||
f.render_stateful_widget(list, dropdown_area, &mut profile_list_state);
|
||||
f.render_stateful_widget(list, dropdown_area, &mut list_state);
|
||||
}
|
||||
|
||||
// --- MODIFIED FUNCTION FOR RICH SUGGESTIONS ---
|
||||
/// Renders an opaque dropdown list for rich `Hit`-based suggestions.
|
||||
/// Displays the value of the first meaningful column, followed by the Hit ID.
|
||||
pub fn render_rich_autocomplete_dropdown(
|
||||
/// RENAMED from render_rich_autocomplete_dropdown
|
||||
pub fn render_hit_autocomplete_dropdown(
|
||||
f: &mut Frame,
|
||||
input_rect: Rect,
|
||||
frame_area: Rect,
|
||||
theme: &Theme,
|
||||
suggestions: &[Hit],
|
||||
selected_index: Option<usize>,
|
||||
form_state: &FormState,
|
||||
) {
|
||||
if suggestions.is_empty() {
|
||||
return;
|
||||
@@ -107,50 +95,9 @@ pub fn render_rich_autocomplete_dropdown(
|
||||
|
||||
let display_names: Vec<String> = suggestions
|
||||
.iter()
|
||||
.map(|hit| {
|
||||
// Use serde_json::Value to handle mixed types (string, null, etc.)
|
||||
if let Ok(content_map) =
|
||||
serde_json::from_str::<HashMap<String, serde_json::Value>>(
|
||||
&hit.content_json,
|
||||
)
|
||||
{
|
||||
// Define keys to ignore for a cleaner display
|
||||
const IGNORED_KEYS: &[&str] = &["id", "deleted", "created_at"];
|
||||
|
||||
// Get keys, filter out ignored ones, and sort for consistency
|
||||
let mut keys: Vec<_> = content_map
|
||||
.keys()
|
||||
.filter(|k| !IGNORED_KEYS.contains(&k.as_str()))
|
||||
.cloned()
|
||||
.collect();
|
||||
keys.sort();
|
||||
|
||||
// Get only the first non-empty value from the sorted keys
|
||||
let values: Vec<_> = keys
|
||||
.iter()
|
||||
.map(|key| {
|
||||
content_map
|
||||
.get(key)
|
||||
.map(json_value_to_string)
|
||||
.unwrap_or_default()
|
||||
})
|
||||
.filter(|s| !s.is_empty()) // Filter out null/empty values
|
||||
.take(1) // Changed from take(2) to take(1)
|
||||
.collect();
|
||||
|
||||
let display_part = values.first().cloned().unwrap_or_default(); // Get the first value
|
||||
if display_part.is_empty() {
|
||||
format!("{}", hit.id)
|
||||
} else {
|
||||
format!("{} | {}", display_part, hit.id) // ID at the end
|
||||
}
|
||||
} else {
|
||||
format!("{} (parse error)", hit.id)
|
||||
}
|
||||
})
|
||||
.map(|hit| form_state.get_display_name_for_hit(hit))
|
||||
.collect();
|
||||
|
||||
// --- Calculate Dropdown Size & Position ---
|
||||
let max_suggestion_width =
|
||||
display_names.iter().map(|s| s.width()).max().unwrap_or(0) as u16;
|
||||
let horizontal_padding: u16 = 2;
|
||||
@@ -164,7 +111,6 @@ pub fn render_rich_autocomplete_dropdown(
|
||||
height: dropdown_height,
|
||||
};
|
||||
|
||||
// --- Clamping Logic ---
|
||||
if dropdown_area.bottom() > frame_area.height {
|
||||
dropdown_area.y = input_rect.y.saturating_sub(dropdown_height);
|
||||
}
|
||||
@@ -174,7 +120,6 @@ pub fn render_rich_autocomplete_dropdown(
|
||||
dropdown_area.x = dropdown_area.x.max(0);
|
||||
dropdown_area.y = dropdown_area.y.max(0);
|
||||
|
||||
// --- Rendering Logic ---
|
||||
let background_block =
|
||||
Block::default().style(Style::default().bg(Color::DarkGray));
|
||||
f.render_widget(background_block, dropdown_area);
|
||||
|
||||
@@ -78,25 +78,25 @@ pub fn render_form(
|
||||
|
||||
// --- NEW: RENDER AUTOCOMPLETE ---
|
||||
if form_state.autocomplete_active {
|
||||
// Use the Rect of the active field that render_canvas found for us.
|
||||
if let Some(active_rect) = active_field_rect {
|
||||
let selected_index = form_state.get_selected_suggestion_index();
|
||||
|
||||
// THE DECIDER LOGIC:
|
||||
// 1. Check for rich suggestions first.
|
||||
if let Some(rich_suggestions) = form_state.get_rich_suggestions() {
|
||||
if !rich_suggestions.is_empty() {
|
||||
autocomplete::render_rich_autocomplete_dropdown(
|
||||
// CHANGE THIS to call the renamed function
|
||||
autocomplete::render_hit_autocomplete_dropdown(
|
||||
f,
|
||||
active_rect,
|
||||
f.area(), // Use f.area() for clamping, not f.size()
|
||||
f.area(),
|
||||
theme,
|
||||
rich_suggestions,
|
||||
selected_index,
|
||||
form_state,
|
||||
);
|
||||
}
|
||||
}
|
||||
// 2. Fallback to simple suggestions if rich ones aren't available.
|
||||
// The fallback to simple suggestions is now correctly handled
|
||||
// because the original render_autocomplete_dropdown exists again.
|
||||
else if let Some(simple_suggestions) = form_state.get_suggestions() {
|
||||
if !simple_suggestions.is_empty() {
|
||||
autocomplete::render_autocomplete_dropdown(
|
||||
@@ -112,3 +112,4 @@ pub fn render_form(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user