use anyhow::Result;
use std::{env, fs, path::PathBuf};
use crate::utils::is_image_file;
pub struct FileExplorer {
current_dir: PathBuf,
entries: Vec<PathBuf>,
selected_index: usize,
selected_images: Vec<PathBuf>,
}
impl FileExplorer {
pub fn new() -> Result<Self> {
let current_dir = env::current_dir()?;
let mut explorer = FileExplorer {
current_dir: current_dir.clone(),
entries: Vec::new(),
selected_index: 0,
selected_images: Vec::new(),
};
explorer.refresh_entries()?;
Ok(explorer)
}
fn refresh_entries(&mut self) -> Result<()> {
let mut entries = Vec::new();
if let Some(parent) = self.current_dir.parent() {
entries.push(parent.to_path_buf());
}
for entry in fs::read_dir(&self.current_dir)? {
let entry = entry?;
let path = entry.path();
if path.is_dir() || is_image_file(&path) {
entries.push(path);
}
}
entries.sort_by(|a, b| {
let a_is_dir = a.is_dir();
let b_is_dir = b.is_dir();
match (a_is_dir, b_is_dir) {
(true, false) => std::cmp::Ordering::Less,
(false, true) => std::cmp::Ordering::Greater,
_ => a.file_name().cmp(&b.file_name()),
}
});
self.entries = entries;
self.selected_index = 0;
Ok(())
}
pub fn move_up(&mut self) {
if self.selected_index > 0 {
self.selected_index -= 1;
}
}
pub fn move_down(&mut self) {
if self.selected_index < self.entries.len().saturating_sub(1) {
self.selected_index += 1;
}
}
pub fn enter_selected(&mut self) -> Result<()> {
if let Some(path) = self.entries.get(self.selected_index) {
if path.is_dir() {
self.current_dir = path.clone();
self.refresh_entries()?;
} else if is_image_file(path) {
if let Some(pos) = self.selected_images.iter().position(|p| p == path) {
self.selected_images.remove(pos);
} else if self.selected_images.len() < 4 {
self.selected_images.push(path.clone());
}
}
}
Ok(())
}
pub fn go_up(&mut self) -> Result<()> {
if let Some(parent) = self.current_dir.parent() {
self.current_dir = parent.to_path_buf();
self.refresh_entries()?;
}
Ok(())
}
pub fn current_dir(&self) -> &PathBuf {
&self.current_dir
}
pub fn entries(&self) -> &[PathBuf] {
&self.entries
}
pub fn selected_index(&self) -> usize {
self.selected_index
}
pub fn selected_images(&self) -> &[PathBuf] {
&self.selected_images
}
}