use crate::prelude::*;
use crate::utils::NavigatorEntry;
use chrono::NaiveDateTime;
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub(crate) enum EntryType {
UpDir,
File,
Folder,
}
#[derive(Debug)]
pub(crate) struct Entry {
pub(crate) name: String,
pub(crate) size: u64,
pub(crate) created: NaiveDateTime,
pub(crate) entry_type: EntryType,
}
impl Entry {
pub(crate) fn new(name: &str, size: u64, created: NaiveDateTime, entry_type: EntryType) -> Self {
Self {
name: name.to_string(),
size,
created,
entry_type,
}
}
#[cfg(test)]
pub(super) fn from_csv_line(line: &str, path: &str) -> Option<Self> {
let mut parts = line.split(',');
let entry_type = parts.next()?;
let full_path = parts.next()?;
if !full_path.starts_with(path) {
return None;
}
if full_path.len() <= path.len() {
return None;
}
for c in full_path.chars().skip(path.len()).skip_while(|c| (*c == '/') || (*c == '\\' )) {
if (c == '/') || (c == '\\') {
return None;
}
}
let size = parts.next()?;
let created = parts.next()?;
let folder = match entry_type {
"F" | "f" | "file" => false,
"D" | "d" | "dir" | "folder" => true,
_ => return None,
};
let size = size.parse().ok()?;
let created = NaiveDateTime::parse_from_str(created, "%Y-%m-%d %H:%M:%S").ok()?;
let len = path.len() + match full_path.as_bytes()[path.len()] {
b'\\' | b'/' => 1,
_ => 0,
};
Some(Self {
name: full_path[len..].to_string(),
size,
created,
entry_type: if folder { EntryType::Folder } else { EntryType::File },
})
}
}
impl NavigatorEntry for Entry {
fn name(&self) -> &str {
&self.name
}
fn is_container(&self) -> bool {
self.entry_type == EntryType::Folder
}
}
impl listview::ListItem for Entry {
fn render_method(&'_ self, column_index: u16) -> Option<listview::RenderMethod<'_>> {
match column_index {
0 => Some(listview::RenderMethod::Text(&self.name)),
1 => {
match self.entry_type {
EntryType::UpDir => Some(listview::RenderMethod::Ascii("UpDir")),
EntryType::Folder => Some(listview::RenderMethod::Ascii("Folder")),
EntryType::File => Some(listview::RenderMethod::Size(self.size, listview::SizeFormat::AutoWithDecimals)),
}
}
2 => {
match self.entry_type {
EntryType::UpDir => Some(listview::RenderMethod::Ascii("-")),
_ => Some(listview::RenderMethod::DateTime(self.created, listview::DateTimeFormat::Short)),
}
}
_ => None,
}
}
fn column(index: u16) -> Column {
match index {
0 => Column::new("&Name", 28, TextAlignment::Left),
1 => Column::new("&Size", 12, TextAlignment::Right),
2 => Column::new("&Created", 16, TextAlignment::Center),
_ => Column::new("", 10, TextAlignment::Left),
}
}
fn compare(&self, other: &Self, column_index: u16) -> std::cmp::Ordering {
match column_index {
0 => self.name.cmp(&other.name),
1 => self.size.cmp(&other.size),
2 => self.created.cmp(&other.created),
_ => std::cmp::Ordering::Equal
}
}
fn columns_count() -> u16 { 3 }
}
impl Default for Entry {
fn default() -> Self {
Self {
name: String::new(),
size: 0,
created: NaiveDateTime::default(),
entry_type: EntryType::File,
}
}
}