Skip to main content

lib/
fn_filestree.rs

1use crate::fn_pathtype::{DIR_ICON, get_file_type};
2use std::cmp::Ordering;
3use std::collections::BTreeMap;
4use std::path::PathBuf;
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
46            .parent()
47            .map(|p| p.to_path_buf())
48            .unwrap_or_else(|| PathBuf::from("/"));
49        tree_map.entry(parent).or_default().push(p.clone());
50    }
51
52    // ZMIANA: Usuwamy file_icons z funkcji wewnętrznej
53    fn build_node(
54        path: &PathBuf,
55        paths: &BTreeMap<PathBuf, Vec<PathBuf>>,
56        sort_method: &str,
57    ) -> FileNode {
58        let name = path
59            .file_name()
60            .map(|n| n.to_string_lossy().to_string())
61            .unwrap_or_else(|| "/".to_string());
62
63        let is_dir = path.is_dir();
64
65        // Pobieramy ikony z naszego pliku SSoT
66        let icon = if is_dir {
67            DIR_ICON.to_string()
68        } else if let Some(ext) = path.extension().and_then(|e| e.to_str()) {
69            get_file_type(ext).icon.to_string()
70        } else {
71            "📄".to_string()
72        };
73
74        let mut children = vec![];
75        if let Some(child_paths) = paths.get(path) {
76            let mut child_nodes: Vec<FileNode> = child_paths
77                .iter()
78                .map(|c| build_node(c, paths, sort_method)) // Usuwamy argument file_icons
79                .collect();
80
81            crate::fn_filestree::sort_nodes(&mut child_nodes, sort_method);
82            children = child_nodes;
83        }
84
85        FileNode {
86            name,
87            path: path.clone(),
88            is_dir,
89            icon,
90            children,
91        }
92    }
93
94    let roots: Vec<PathBuf> = paths
95        .iter()
96        .filter(|p| p.parent().is_none() || !paths.contains(&p.parent().unwrap().to_path_buf()))
97        .cloned()
98        .collect();
99
100    let mut top_nodes: Vec<FileNode> = roots
101        .into_iter()
102        .map(|r| build_node(&r, &tree_map, sort_method)) // Usuwamy argument file_icons
103        .collect();
104
105    crate::fn_filestree::sort_nodes(&mut top_nodes, sort_method);
106
107    top_nodes
108}