use crate::monitor::dashboard::IndexRow;
use crate::monitor::tui_common::{ListFocus, ThreeWaySortKey};
use crate::monitor::utils::{ActivityLog, DaemonStatus};
use super::nav::visible_index_ids;
pub type SearchFocus = ListFocus;
#[derive(Debug, Clone)]
pub struct SearchTuiState {
pub base_url: String,
pub daemon_status: DaemonStatus,
pub indexes: Vec<IndexRow>,
pub selected: usize,
pub scroll_offset: usize,
pub log: ActivityLog,
pub input: String,
pub focus: SearchFocus,
pub show_help: bool,
pub filter: String,
pub filter_active: bool,
pub sort_key: ThreeWaySortKey,
pub group_by_project: bool,
pub log_watermark: Option<String>,
pub log_first_poll: bool,
}
impl SearchTuiState {
pub fn new(base_url: impl Into<String>) -> Self {
Self {
base_url: base_url.into(),
daemon_status: DaemonStatus::Connecting,
indexes: Vec::new(),
selected: 0,
scroll_offset: 0,
log: ActivityLog::new(),
input: String::new(),
focus: ListFocus::List,
show_help: false,
filter: String::new(),
filter_active: false,
sort_key: ThreeWaySortKey::default(),
group_by_project: false,
log_watermark: None,
log_first_poll: true,
}
}
pub fn toggle_focus(&mut self) {
self.focus = self.focus.toggled();
}
pub fn select_up(&mut self) {
self.selected = self.selected.saturating_sub(1);
}
pub fn select_down(&mut self) {
if self.selected < self.last_row() {
self.selected += 1;
}
}
pub fn last_row(&self) -> usize {
self.indexes.len()
}
pub fn clamp_selection(&mut self) {
if self.selected > self.last_row() {
self.selected = self.last_row();
}
}
pub fn sync_scroll(&mut self, visible: usize) {
let cursor = self.selected;
self.sync_scroll_to(cursor, visible);
}
pub fn sync_scroll_to(&mut self, cursor_row: usize, visible: usize) {
let window = visible.max(1);
if cursor_row >= self.scroll_offset + window {
self.scroll_offset = cursor_row + 1 - window;
} else if cursor_row < self.scroll_offset {
self.scroll_offset = cursor_row;
}
}
pub fn is_all_selected(&self) -> bool {
self.selected == 0
}
pub fn selected_id(&self) -> Option<&str> {
if self.selected == 0 {
return None;
}
self.indexes.get(self.selected - 1).map(|i| i.id.as_str())
}
pub fn clamp_to_visible(&mut self) {
if self.selected == 0 {
return;
}
let Some(current_id) = self.indexes.get(self.selected - 1).map(|i| i.id.clone()) else {
self.selected = 0;
return;
};
let ids = visible_index_ids(self);
if !ids.iter().any(|id| id == ¤t_id) {
self.selected = 0;
}
}
pub fn scope_filter(&self) -> Option<&str> {
self.selected_id()
}
}