feat: enable setting view depth

This commit is contained in:
xeruf 2024-07-25 00:26:29 +03:00
parent 87cdecbeee
commit 6ed2299ee0
2 changed files with 123 additions and 43 deletions

View File

@ -181,10 +181,6 @@ async fn main() {
} }
} }
Err(_) => { Err(_) => {
if input.chars().nth(1) == Some(':') {
tasks.recursive = !tasks.recursive;
continue
}
let prop = &input[1..]; let prop = &input[1..];
let pos = tasks.properties.iter().position(|s| s == &prop); let pos = tasks.properties.iter().position(|s| s == &prop);
match pos { match pos {
@ -217,37 +213,42 @@ async fn main() {
pos = tasks.parent(pos); pos = tasks.parent(pos);
} }
let slice = &input[dots..]; let slice = &input[dots..];
if !slice.is_empty() { if slice.is_empty() {
pos = EventId::parse(slice).ok().or_else(|| { tasks.move_to(pos);
// TODO check what is more intuitive: continue;
// currently resets filters before filtering again, maybe keep them }
tasks.move_to(pos); if let Ok(depth) = slice.parse::<i8>() {
let filtered: Vec<EventId> = tasks tasks.move_to(pos);
.current_tasks() tasks.depth = depth;
.iter() continue;
.filter(|t| t.event.content.starts_with(slice)) }
.map(|t| t.event.id) pos = EventId::parse(slice).ok().or_else(|| {
.collect(); // TODO check what is more intuitive:
match filtered.len() { // currently resets filters before filtering again, maybe keep them
0 => { tasks.move_to(pos);
// No match, new task let filtered: Vec<EventId> = tasks
tasks.make_task(slice) .current_tasks()
} .into_iter()
1 => { .filter(|t| t.event.content.starts_with(slice))
// One match, activate .map(|t| t.event.id)
Some(filtered.first().unwrap().clone()) .collect();
} match filtered.len() {
_ => { 0 => {
// Multiple match, filter // No match, new task
tasks.set_filter(filtered); tasks.make_task(slice)
None }
} 1 => {
// One match, activate
Some(filtered.first().unwrap().clone())
}
_ => {
// Multiple match, filter
tasks.set_filter(filtered);
None
} }
});
if pos != None {
tasks.move_to(pos);
} }
} else { });
if pos != None {
tasks.move_to(pos); tasks.move_to(pos);
} }
} }

View File

@ -1,7 +1,8 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::iter::once; use std::iter::once;
use std::sync::mpsc;
use nostr_sdk::{Event, EventBuilder, EventId, Kind, Tag}; use nostr_sdk::{Event, EventBuilder, EventId, Keys, Kind, Tag};
use crate::{EventSender, TASK_KIND}; use crate::{EventSender, TASK_KIND};
use crate::task::{State, Task}; use crate::task::{State, Task};
@ -12,8 +13,10 @@ pub(crate) struct Tasks {
tasks: TaskMap, tasks: TaskMap,
/// The task properties currently visible /// The task properties currently visible
pub(crate) properties: Vec<String>, pub(crate) properties: Vec<String>,
// TODO: plain, recursive, only leafs /// Negative: Only Leaf nodes
pub(crate) recursive: bool, /// Zero: Only Active node
/// Positive: Go down the respective level
pub(crate) depth: i8,
/// The task currently selected. /// The task currently selected.
position: Option<EventId>, position: Option<EventId>,
@ -30,7 +33,7 @@ impl Tasks {
properties: vec!["id".into(), "name".into(), "state".into(), "ttime".into()], properties: vec!["id".into(), "name".into(), "state".into(), "ttime".into()],
position: None, position: None,
view: Default::default(), view: Default::default(),
recursive: false, depth: 1,
sender sender
} }
} }
@ -55,28 +58,45 @@ impl Tasks {
pub(crate) fn set_filter(&mut self, view: Vec<EventId>) { pub(crate) fn set_filter(&mut self, view: Vec<EventId>) {
self.view = view self.view = view
} }
fn resolve_tasks<'a>(&self, iter: impl IntoIterator<Item=&'a EventId>) -> Vec<&Task> { fn resolve_tasks<'a>(&self, iter: impl IntoIterator<Item=&'a EventId>) -> Vec<&Task> {
self.resolve_tasks_rec(iter, self.depth)
}
fn resolve_tasks_rec<'a>(&self, iter: impl IntoIterator<Item=&'a EventId>, depth: i8) -> Vec<&Task> {
iter.into_iter().filter_map(|id| self.tasks.get(&id)).flat_map(|task| { iter.into_iter().filter_map(|id| self.tasks.get(&id)).flat_map(|task| {
if self.recursive { let new_depth = depth - 1;
self.resolve_tasks(task.children.iter()).into_iter().chain(once(task)).collect() if new_depth < 0 {
let tasks = self.resolve_tasks_rec(task.children.iter(), new_depth).into_iter().collect::<Vec<&Task>>();
if tasks.is_empty() {
vec![task]
} else {
tasks
}
} else if new_depth > 0 {
self.resolve_tasks_rec(task.children.iter(), new_depth).into_iter().chain(once(task)).collect()
} else { } else {
vec![task] vec![task]
} }
}).collect() }).collect()
} }
pub(crate) fn current_tasks(&self) -> Vec<&Task> { pub(crate) fn current_tasks(&self) -> Vec<&Task> {
if self.depth == 0 {
return self.position.and_then(|id| self.tasks.get(&id)).into_iter().collect();
}
let res: Vec<&Task> = self.resolve_tasks(self.view.iter()); let res: Vec<&Task> = self.resolve_tasks(self.view.iter());
if res.len() > 0 { if res.len() > 0 {
return res; return res;
} }
self.position.map_or_else( self.position.map_or_else(
|| { || {
if self.recursive { if self.depth > 8 {
self.tasks.values().collect() self.tasks.values().collect()
} else { } else if self.depth == 1 {
self.tasks.values().filter(|t| t.parent_id() == None).collect() self.tasks.values().filter(|t| t.parent_id() == None).collect()
} else {
self.resolve_tasks(self.tasks.values().filter(|t| t.parent_id() == None).map(|t| &t.event.id))
} }
}, },
|p| self.tasks.get(&p).map_or(Vec::new(), |t| self.resolve_tasks(t.children.iter())), |p| self.tasks.get(&p).map_or(Vec::new(), |t| self.resolve_tasks(t.children.iter())),
@ -251,3 +271,62 @@ impl<'a> Iterator for ParentIterator<'a> {
}) })
} }
} }
#[test]
fn test_depth() {
let (tx, rx) = mpsc::channel();
let mut tasks = Tasks::from(EventSender {
tx,
keys: Keys::generate(),
});
let t1 = tasks.make_task("t1");
assert_eq!(tasks.depth, 1);
assert_eq!(tasks.current_tasks().len(), 1);
tasks.depth = 0;
assert_eq!(tasks.current_tasks().len(), 0);
tasks.move_to(t1);
tasks.depth = 2;
assert_eq!(tasks.current_tasks().len(), 0);
let t2 = tasks.make_task("t2");
assert_eq!(tasks.current_tasks().len(), 1);
let t3 = tasks.make_task("t3");
assert_eq!(tasks.current_tasks().len(), 2);
tasks.move_to(t2);
assert_eq!(tasks.current_tasks().len(), 0);
let t4 = tasks.make_task("t4");
assert_eq!(tasks.current_tasks().len(), 1);
tasks.depth = 2;
assert_eq!(tasks.current_tasks().len(), 1);
tasks.depth = -1;
assert_eq!(tasks.current_tasks().len(), 1);
tasks.move_to(t1);
assert_eq!(tasks.current_tasks().len(), 2);
tasks.depth = 2;
assert_eq!(tasks.current_tasks().len(), 3);
tasks.set_filter(vec![t2.unwrap()]);
assert_eq!(tasks.current_tasks().len(), 2);
tasks.depth = 1;
assert_eq!(tasks.current_tasks().len(), 1);
tasks.depth = -1;
assert_eq!(tasks.current_tasks().len(), 1);
tasks.set_filter(vec![t2.unwrap(), t3.unwrap()]);
assert_eq!(tasks.current_tasks().len(), 2);
tasks.depth = 2;
assert_eq!(tasks.current_tasks().len(), 3);
tasks.depth = 1;
assert_eq!(tasks.current_tasks().len(), 2);
tasks.move_to(None);
assert_eq!(tasks.current_tasks().len(), 1);
tasks.depth = 2;
assert_eq!(tasks.current_tasks().len(), 3);
tasks.depth = 3;
assert_eq!(tasks.current_tasks().len(), 4);
tasks.depth = 9;
assert_eq!(tasks.current_tasks().len(), 4);
tasks.depth = -1;
assert_eq!(tasks.current_tasks().len(), 2);
}