fresh/view/file_tree/
decorations.rs1use std::collections::HashMap;
2use std::path::{Path, PathBuf};
3
4pub use fresh_core::file_explorer::FileExplorerDecoration;
6
7#[derive(Debug, Default, Clone)]
9pub struct FileExplorerDecorationCache {
10 direct: HashMap<PathBuf, FileExplorerDecoration>,
11 bubbled: HashMap<PathBuf, FileExplorerDecoration>,
12}
13
14impl FileExplorerDecorationCache {
15 pub fn rebuild<I>(
20 decorations: I,
21 root: &Path,
22 symlink_mappings: &HashMap<PathBuf, PathBuf>,
23 ) -> Self
24 where
25 I: IntoIterator<Item = FileExplorerDecoration>,
26 {
27 let mut direct = HashMap::new();
28 for decoration in decorations {
29 if !decoration.path.starts_with(root) {
30 continue;
31 }
32 insert_best(&mut direct, decoration.clone());
33
34 for (symlink_path, canonical_target) in symlink_mappings {
38 if let Ok(suffix) = decoration.path.strip_prefix(canonical_target) {
39 let aliased_path = symlink_path.join(suffix);
40 insert_best(
41 &mut direct,
42 FileExplorerDecoration {
43 path: aliased_path,
44 symbol: decoration.symbol.clone(),
45 color: decoration.color,
46 priority: decoration.priority,
47 },
48 );
49 }
50 }
51 }
52
53 let mut bubbled = HashMap::new();
54 for (path, decoration) in &direct {
55 for ancestor in path.ancestors() {
56 if !ancestor.starts_with(root) {
57 break;
58 }
59 insert_best(
60 &mut bubbled,
61 FileExplorerDecoration {
62 path: ancestor.to_path_buf(),
63 symbol: decoration.symbol.clone(),
64 color: decoration.color,
65 priority: decoration.priority,
66 },
67 );
68 }
69 }
70
71 Self { direct, bubbled }
72 }
73
74 pub fn direct_for_path(&self, path: &Path) -> Option<&FileExplorerDecoration> {
76 self.direct.get(path)
77 }
78
79 pub fn bubbled_for_path(&self, path: &Path) -> Option<&FileExplorerDecoration> {
81 self.bubbled.get(path)
82 }
83}
84
85fn insert_best(
86 map: &mut HashMap<PathBuf, FileExplorerDecoration>,
87 decoration: FileExplorerDecoration,
88) {
89 let replace = match map.get(&decoration.path) {
90 Some(existing) => decoration.priority >= existing.priority,
91 None => true,
92 };
93
94 if replace {
95 map.insert(decoration.path.clone(), decoration);
96 }
97}