use crate::models::cls_file_entry::FileEntry;
use crate::models::cls_sort_by::SortBy;
use std::ops::{Deref, DerefMut};
#[derive(Debug, Default)]
pub struct FileList {
items: Vec<FileEntry>,
hidden: Vec<FileEntry>,
revision: u64,
version: u64,
sort_by: SortBy,
show_hidden: bool,
}
impl Deref for FileList {
type Target = Vec<FileEntry>;
fn deref(&self) -> &Self::Target {
&self.items
}
}
impl DerefMut for FileList {
fn deref_mut(&mut self) -> &mut Self::Target {
self.revision += 1;
&mut self.items
}
}
impl FileList {
pub fn new() -> Self {
Self::default()
}
pub fn from_entries(entries: Vec<FileEntry>) -> Self {
let mut list = Self::new();
list.update_full(entries);
list
}
pub fn update_full(&mut self, entries: Vec<FileEntry>) {
self.revision += 1;
if self.show_hidden {
self.items = entries;
self.hidden.clear();
} else {
let (hidden, visible): (Vec<_>, Vec<_>) =
entries.into_iter().partition(|e| e.is_hidden);
self.items = visible;
self.hidden = hidden;
}
}
pub fn push_batch(&mut self, entries: Vec<FileEntry>) {
self.revision += 1;
if self.show_hidden {
self.items.extend(entries);
} else {
for entry in entries {
if entry.is_hidden {
self.hidden.push(entry);
} else {
self.items.push(entry);
}
}
}
}
pub fn catchup(&mut self) -> bool {
if self.version == self.revision {
return false;
}
self.version = self.revision;
self.sort_items();
true
}
pub fn set_sort(&mut self, sort_by: SortBy) {
if self.sort_by != sort_by {
self.sort_by = sort_by;
self.revision += 1;
}
}
pub fn set_show_hidden(&mut self, show: bool) {
if self.show_hidden == show {
return;
}
self.show_hidden = show;
self.revision += 1;
if show {
self.items.append(&mut self.hidden);
} else {
let items = std::mem::take(&mut self.items);
let (hidden, visible): (Vec<_>, Vec<_>) = items.into_iter().partition(|e| e.is_hidden);
self.items = visible;
self.hidden = hidden;
}
}
pub fn revision(&self) -> u64 {
self.revision
}
pub fn needs_sort(&self) -> bool {
self.version != self.revision
}
pub fn sort_by(&self) -> SortBy {
self.sort_by
}
pub fn hidden_count(&self) -> usize {
self.hidden.len()
}
fn sort_items(&mut self) {
match self.sort_by {
SortBy::Name => {
self.items
.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase()));
}
SortBy::NameDesc => {
self.items
.sort_by(|a, b| b.name.to_lowercase().cmp(&a.name.to_lowercase()));
}
SortBy::Size => {
self.items.sort_by_key(|e| e.size);
}
SortBy::SizeDesc => {
self.items.sort_by(|a, b| b.size.cmp(&a.size));
}
SortBy::Modified => {
self.items.sort_by_key(|e| e.modified);
}
SortBy::ModifiedDesc => {
self.items.sort_by(|a, b| b.modified.cmp(&a.modified));
}
SortBy::Extension => {
self.items.sort_by(|a, b| {
let ext_cmp = a.extension().cmp(&b.extension());
if ext_cmp == std::cmp::Ordering::Equal {
a.name.to_lowercase().cmp(&b.name.to_lowercase())
} else {
ext_cmp
}
});
}
SortBy::DirsFirst => {
self.items.sort_by(|a, b| match (a.is_dir, b.is_dir) {
(true, false) => std::cmp::Ordering::Less,
(false, true) => std::cmp::Ordering::Greater,
_ => a.name.to_lowercase().cmp(&b.name.to_lowercase()),
});
}
}
}
}