forked from janek/mostr
feat: enable setting view depth
This commit is contained in:
parent
87cdecbeee
commit
6ed2299ee0
67
src/main.rs
67
src/main.rs
|
@ -181,10 +181,6 @@ async fn main() {
|
|||
}
|
||||
}
|
||||
Err(_) => {
|
||||
if input.chars().nth(1) == Some(':') {
|
||||
tasks.recursive = !tasks.recursive;
|
||||
continue
|
||||
}
|
||||
let prop = &input[1..];
|
||||
let pos = tasks.properties.iter().position(|s| s == &prop);
|
||||
match pos {
|
||||
|
@ -217,37 +213,42 @@ async fn main() {
|
|||
pos = tasks.parent(pos);
|
||||
}
|
||||
let slice = &input[dots..];
|
||||
if !slice.is_empty() {
|
||||
pos = EventId::parse(slice).ok().or_else(|| {
|
||||
// TODO check what is more intuitive:
|
||||
// currently resets filters before filtering again, maybe keep them
|
||||
tasks.move_to(pos);
|
||||
let filtered: Vec<EventId> = tasks
|
||||
.current_tasks()
|
||||
.iter()
|
||||
.filter(|t| t.event.content.starts_with(slice))
|
||||
.map(|t| t.event.id)
|
||||
.collect();
|
||||
match filtered.len() {
|
||||
0 => {
|
||||
// No match, new task
|
||||
tasks.make_task(slice)
|
||||
}
|
||||
1 => {
|
||||
// One match, activate
|
||||
Some(filtered.first().unwrap().clone())
|
||||
}
|
||||
_ => {
|
||||
// Multiple match, filter
|
||||
tasks.set_filter(filtered);
|
||||
None
|
||||
}
|
||||
if slice.is_empty() {
|
||||
tasks.move_to(pos);
|
||||
continue;
|
||||
}
|
||||
if let Ok(depth) = slice.parse::<i8>() {
|
||||
tasks.move_to(pos);
|
||||
tasks.depth = depth;
|
||||
continue;
|
||||
}
|
||||
pos = EventId::parse(slice).ok().or_else(|| {
|
||||
// TODO check what is more intuitive:
|
||||
// currently resets filters before filtering again, maybe keep them
|
||||
tasks.move_to(pos);
|
||||
let filtered: Vec<EventId> = tasks
|
||||
.current_tasks()
|
||||
.into_iter()
|
||||
.filter(|t| t.event.content.starts_with(slice))
|
||||
.map(|t| t.event.id)
|
||||
.collect();
|
||||
match filtered.len() {
|
||||
0 => {
|
||||
// No match, new task
|
||||
tasks.make_task(slice)
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
99
src/tasks.rs
99
src/tasks.rs
|
@ -1,7 +1,8 @@
|
|||
use std::collections::HashMap;
|
||||
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::task::{State, Task};
|
||||
|
@ -12,8 +13,10 @@ pub(crate) struct Tasks {
|
|||
tasks: TaskMap,
|
||||
/// The task properties currently visible
|
||||
pub(crate) properties: Vec<String>,
|
||||
// TODO: plain, recursive, only leafs
|
||||
pub(crate) recursive: bool,
|
||||
/// Negative: Only Leaf nodes
|
||||
/// Zero: Only Active node
|
||||
/// Positive: Go down the respective level
|
||||
pub(crate) depth: i8,
|
||||
|
||||
/// The task currently selected.
|
||||
position: Option<EventId>,
|
||||
|
@ -30,7 +33,7 @@ impl Tasks {
|
|||
properties: vec!["id".into(), "name".into(), "state".into(), "ttime".into()],
|
||||
position: None,
|
||||
view: Default::default(),
|
||||
recursive: false,
|
||||
depth: 1,
|
||||
sender
|
||||
}
|
||||
}
|
||||
|
@ -55,28 +58,45 @@ impl Tasks {
|
|||
pub(crate) fn set_filter(&mut self, view: Vec<EventId>) {
|
||||
self.view = view
|
||||
}
|
||||
|
||||
|
||||
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| {
|
||||
if self.recursive {
|
||||
self.resolve_tasks(task.children.iter()).into_iter().chain(once(task)).collect()
|
||||
let new_depth = depth - 1;
|
||||
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 {
|
||||
vec![task]
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
|
||||
|
||||
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());
|
||||
if res.len() > 0 {
|
||||
return res;
|
||||
}
|
||||
self.position.map_or_else(
|
||||
|| {
|
||||
if self.recursive {
|
||||
if self.depth > 8 {
|
||||
self.tasks.values().collect()
|
||||
} else {
|
||||
} else if self.depth == 1 {
|
||||
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())),
|
||||
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue