Skip to main content

lib/
fn_filestree.rs

1use std::collections::BTreeMap;
2use std::path::PathBuf;
3use std::cmp::Ordering;
4use crate::fn_pathtype::{get_file_type, DIR_ICON};
5
6/// Struktura węzła drzewa
7#[derive(Debug, Clone)]
8pub struct FileNode {
9    pub name: String,
10    pub path: PathBuf,
11    pub is_dir: bool,
12    pub icon: String,
13    pub children: Vec<FileNode>,
14}
15
16/// Helper do sortowania węzłów zgodnie z wybraną metodą
17fn sort_nodes(nodes: &mut [FileNode], sort_method: &str) {
18    match sort_method {
19        "files-first" => nodes.sort_by(|a, b| {
20            if a.is_dir == b.is_dir {
21                a.name.cmp(&b.name)
22            } else if !a.is_dir {
23                Ordering::Less // Jeśli 'a' to plik, ma być wcześniej
24            } else {
25                Ordering::Greater // Jeśli 'a' to folder, spada na dół
26            }
27        }),
28        "dirs-first" => nodes.sort_by(|a, b| {
29            if a.is_dir == b.is_dir {
30                a.name.cmp(&b.name)
31            } else if a.is_dir {
32                Ordering::Less // Jeśli 'a' to folder, ma być wcześniej
33            } else {
34                Ordering::Greater
35            }
36        }),
37        _ => nodes.sort_by(|a, b| a.name.cmp(&b.name)),
38    }
39}
40
41/// Funkcja formatująca - buduje drzewo i przypisuje ikony
42pub fn filestree(paths: Vec<PathBuf>, sort_method: &str) -> Vec<FileNode> {
43    let mut tree_map: BTreeMap<PathBuf, Vec<PathBuf>> = BTreeMap::new();
44    for p in &paths {
45        let parent = p.parent().map(|p| p.to_path_buf()).unwrap_or_else(|| PathBuf::from("/"));
46        tree_map.entry(parent).or_default().push(p.clone());
47    }
48
49    // ZMIANA: Usuwamy file_icons z funkcji wewnętrznej
50    fn build_node(
51        path: &PathBuf,
52        paths: &BTreeMap<PathBuf, Vec<PathBuf>>,
53        sort_method: &str,
54    ) -> FileNode {
55        let name = path.file_name()
56            .map(|n| n.to_string_lossy().to_string())
57            .unwrap_or_else(|| "/".to_string());
58
59        let is_dir = path.is_dir();
60
61        // Pobieramy ikony z naszego pliku SSoT
62        let icon = if is_dir {
63            DIR_ICON.to_string()
64        } else if let Some(ext) = path.extension().and_then(|e| e.to_str()) {
65            get_file_type(ext).icon.to_string()
66        } else {
67            "📄".to_string()
68        };
69
70        let mut children = vec![];
71        if let Some(child_paths) = paths.get(path) {
72            let mut child_nodes: Vec<FileNode> = child_paths
73                .iter()
74                .map(|c| build_node(c, paths, sort_method)) // Usuwamy argument file_icons
75                .collect();
76
77            crate::fn_filestree::sort_nodes(&mut child_nodes, sort_method);
78            children = child_nodes;
79        }
80
81        FileNode { name, path: path.clone(), is_dir, icon, children }
82    }
83
84    let roots: Vec<PathBuf> = paths.iter()
85        .filter(|p| p.parent().is_none() || !paths.contains(&p.parent().unwrap().to_path_buf()))
86        .cloned()
87        .collect();
88
89    let mut top_nodes: Vec<FileNode> = roots
90        .into_iter()
91        .map(|r| build_node(&r, &tree_map, sort_method)) // Usuwamy argument file_icons
92        .collect();
93
94    crate::fn_filestree::sort_nodes(&mut top_nodes, sort_method);
95
96    top_nodes
97}