use std::fs;
use std::path::PathBuf;
use std::collections::VecDeque;
pub struct SearchHistory {
history: VecDeque<String>,
max_size: usize,
history_file: PathBuf,
}
impl SearchHistory {
pub fn new(max_size: usize) -> Self {
let cache_dir = dirs::cache_dir()
.unwrap_or_else(|| PathBuf::from("."))
.join("listary");
if !cache_dir.exists() {
fs::create_dir_all(&cache_dir).ok();
}
let mut history = Self {
history: VecDeque::new(),
max_size,
history_file: cache_dir.join("search_history.txt"),
};
history.load_history();
history
}
pub fn add_query(&mut self, query: &str) {
let query = query.trim().to_string();
if query.is_empty() || self.history.front() == Some(&query) {
return;
}
if let Some(pos) = self.history.iter().position(|x| x == &query) {
self.history.remove(pos);
}
self.history.push_front(query);
if self.history.len() > self.max_size {
self.history.pop_back();
}
self.save_history();
}
pub fn get_history(&self) -> Vec<String> {
self.history.iter().cloned().collect()
}
pub fn clear(&mut self) {
self.history.clear();
self.save_history();
}
pub fn load_history(&mut self) {
if let Ok(content) = fs::read_to_string(&self.history_file) {
self.history = content
.lines()
.take(self.max_size)
.map(|s| s.to_string())
.collect();
}
}
fn save_history(&self) {
let content = self.history
.iter()
.map(|s| s.as_str())
.collect::<Vec<_>>()
.join("\n");
fs::write(&self.history_file, content).ok();
}
}