Add desktop search and entry mutation workflows
This commit is contained in:
1 parent
bb650c2b5c
commit
de5dea28ef
8 files changed
+1292
-30
No files matched your search
@@ -2,7 +2,10 @@
|
||||
|
||||
use std::{collections::BTreeSet, path::Path};
|
||||
|
||||
use ironstorage::read::{TreeModel, TreeNode, TreeNodeId, TreeNodeIndicators, TreeNodeKind};
|
||||
use ironstorage::{
|
||||
read::{TreeModel, TreeNode, TreeNodeId, TreeNodeIndicators, TreeNodeKind},
|
||||
repository::DirectoryPath,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum NavigationKey {
|
||||
@@ -86,6 +89,20 @@ impl NavigationTree {
|
||||
rows
|
||||
}
|
||||
|
||||
pub fn directories(&self) -> Vec<TreeNodeId> {
|
||||
fn visit(nodes: &[NavigationNode], directories: &mut Vec<TreeNodeId>) {
|
||||
for node in nodes {
|
||||
if node.id.is_directory() {
|
||||
directories.push(node.id.clone());
|
||||
}
|
||||
visit(&node.children, directories);
|
||||
}
|
||||
}
|
||||
let mut directories = vec![TreeNodeId::Directory(DirectoryPath::root())];
|
||||
visit(&self.nodes, &mut directories);
|
||||
directories
|
||||
}
|
||||
|
||||
pub fn selected_ratio(&self) -> f32 {
|
||||
let rows = self.rows();
|
||||
let Some(index) = selected_index(&rows, self.selected.as_ref()) else {
|
||||
@@ -131,6 +148,19 @@ impl NavigationTree {
|
||||
true
|
||||
}
|
||||
|
||||
pub fn select_id(&mut self, id: &TreeNodeId) -> bool {
|
||||
let mut lineage = Vec::new();
|
||||
if !find_id_lineage(&self.nodes, id, &mut lineage) {
|
||||
return false;
|
||||
}
|
||||
let Some(selected) = lineage.pop() else {
|
||||
return false;
|
||||
};
|
||||
self.expanded.extend(lineage);
|
||||
self.selected = Some(selected);
|
||||
true
|
||||
}
|
||||
|
||||
fn activate_selected(&mut self) -> NavigationIntent {
|
||||
let Some(selected) = self.selected.clone() else {
|
||||
return NavigationIntent::None;
|
||||
@@ -274,6 +304,21 @@ fn find_lineage(nodes: &[NavigationNode], path: &str, lineage: &mut Vec<TreeNode
|
||||
false
|
||||
}
|
||||
|
||||
fn find_id_lineage(
|
||||
nodes: &[NavigationNode],
|
||||
target: &TreeNodeId,
|
||||
lineage: &mut Vec<TreeNodeId>,
|
||||
) -> bool {
|
||||
for node in nodes {
|
||||
lineage.push(node.id.clone());
|
||||
if &node.id == target || find_id_lineage(&node.children, target, lineage) {
|
||||
return true;
|
||||
}
|
||||
lineage.pop();
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) struct TestNode {
|
||||
pub id: TreeNodeId,
|
||||
@@ -365,6 +410,24 @@ mod tests {
|
||||
assert_eq!(tree.rows().len(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typed_search_and_mutation_identities_expand_and_select_hidden_nodes() {
|
||||
let mut tree = NavigationTree::default();
|
||||
tree.replace_test_nodes(populated());
|
||||
let hidden = TreeNodeId::Entry(EntryPath::parse("personal/email").expect("entry"));
|
||||
assert!(tree.select_id(&hidden));
|
||||
assert_eq!(tree.selected(), Some(&hidden));
|
||||
assert!(tree.rows().iter().any(|row| row.id == hidden));
|
||||
assert_eq!(
|
||||
tree.directories(),
|
||||
vec![
|
||||
TreeNodeId::Directory(DirectoryPath::root()),
|
||||
TreeNodeId::Directory(DirectoryPath::parse("personal").expect("personal")),
|
||||
TreeNodeId::Directory(DirectoryPath::parse("work").expect("work")),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn refresh_preserves_valid_typed_identity_and_clears_removed_state() {
|
||||
let mut tree = NavigationTree::default();
|
||||
|
||||
Reference in new issue
Block a user