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>(decorations: I, root: &Path) -> Self
17 where
18 I: IntoIterator<Item = FileExplorerDecoration>,
19 {
20 let mut direct = HashMap::new();
21 for decoration in decorations {
22 if !decoration.path.starts_with(root) {
23 continue;
24 }
25 insert_best(&mut direct, decoration);
26 }
27
28 let mut bubbled = HashMap::new();
29 for (path, decoration) in &direct {
30 for ancestor in path.ancestors() {
31 if !ancestor.starts_with(root) {
32 break;
33 }
34 insert_best(
35 &mut bubbled,
36 FileExplorerDecoration {
37 path: ancestor.to_path_buf(),
38 symbol: decoration.symbol.clone(),
39 color: decoration.color,
40 priority: decoration.priority,
41 },
42 );
43 }
44 }
45
46 Self { direct, bubbled }
47 }
48
49 pub fn direct_for_path(&self, path: &Path) -> Option<&FileExplorerDecoration> {
52 self.direct.get(path).or_else(|| {
53 path.canonicalize().ok().and_then(|p| self.direct.get(&p))
55 })
56 }
57
58 pub fn bubbled_for_path(&self, path: &Path) -> Option<&FileExplorerDecoration> {
61 self.bubbled.get(path).or_else(|| {
62 path.canonicalize().ok().and_then(|p| self.bubbled.get(&p))
64 })
65 }
66}
67
68fn insert_best(
69 map: &mut HashMap<PathBuf, FileExplorerDecoration>,
70 decoration: FileExplorerDecoration,
71) {
72 let replace = match map.get(&decoration.path) {
73 Some(existing) => decoration.priority >= existing.priority,
74 None => true,
75 };
76
77 if replace {
78 map.insert(decoration.path.clone(), decoration);
79 }
80}