use crate::utils::format_size;
use std::path::{Path, PathBuf};
#[derive(Clone, Debug, Default)]
pub enum FileFilter {
#[default]
All,
Extensions(Vec<String>),
Pattern(String),
Custom(String),
DirectoriesOnly,
}
impl FileFilter {
pub fn extensions(exts: &[&str]) -> Self {
Self::Extensions(exts.iter().map(|s| s.to_string()).collect())
}
pub fn pattern(pattern: impl Into<String>) -> Self {
Self::Pattern(pattern.into())
}
pub fn matches(&self, path: &Path) -> bool {
match self {
FileFilter::All => true,
FileFilter::Extensions(exts) => path
.extension()
.and_then(|e| e.to_str())
.map(|e| exts.iter().any(|ext| ext.eq_ignore_ascii_case(e)))
.unwrap_or(false),
FileFilter::Pattern(pattern) => {
path.file_name()
.and_then(|n| n.to_str())
.map(|name| {
if let Some(suffix) = pattern.strip_prefix('*') {
name.ends_with(suffix)
} else if let Some(prefix) = pattern.strip_suffix('*') {
name.starts_with(prefix)
} else {
name == pattern
}
})
.unwrap_or(false)
}
FileFilter::Custom(_) => true, FileFilter::DirectoriesOnly => path.is_dir(),
}
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum PickerMode {
#[default]
Open,
Save,
Directory,
MultiSelect,
}
#[derive(Clone, Debug)]
pub struct PickerEntry {
pub path: PathBuf,
pub name: String,
pub is_dir: bool,
pub is_hidden: bool,
pub size: u64,
pub selected: bool,
}
impl PickerEntry {
pub fn from_path(path: &Path) -> Option<Self> {
let name = path.file_name()?.to_str()?.to_string();
let is_hidden = name.starts_with('.');
let metadata = path.metadata().ok();
let is_dir = metadata.as_ref().map(|m| m.is_dir()).unwrap_or(false);
let size = metadata.as_ref().map(|m| m.len()).unwrap_or(0);
Some(Self {
path: path.to_path_buf(),
name,
is_dir,
is_hidden,
size,
selected: false,
})
}
pub fn format_size(&self) -> String {
if self.is_dir {
return "<DIR>".to_string();
}
format_size(self.size)
}
}
#[derive(Clone, Debug)]
pub enum PickerResult {
None,
Selected(PathBuf),
Multiple(Vec<PathBuf>),
Cancelled,
}