Compare commits
4 Commits
026915f870
...
9a2f3f8794
Author | SHA1 | Date |
---|---|---|
xeruf | 9a2f3f8794 | |
xeruf | 1ea34898d1 | |
xeruf | 3a444c3ac2 | |
xeruf | c8463e6924 |
|
@ -1 +1,4 @@
|
||||||
/target
|
/target
|
||||||
|
|
||||||
|
*.html
|
||||||
|
/src/bin
|
||||||
|
|
77
src/main.rs
77
src/main.rs
|
@ -62,38 +62,8 @@ async fn main() {
|
||||||
|
|
||||||
CLIENT.connect().await;
|
CLIENT.connect().await;
|
||||||
|
|
||||||
let timeout = Duration::from_secs(3);
|
|
||||||
|
|
||||||
let filter = Filter::new();
|
|
||||||
let sub_id: SubscriptionId = CLIENT.subscribe(vec![filter.clone()], None).await;
|
|
||||||
|
|
||||||
repl().await;
|
repl().await;
|
||||||
|
|
||||||
println!("Finding existing events");
|
|
||||||
let res = CLIENT
|
|
||||||
.get_events_of(vec![filter], Option::from(timeout))
|
|
||||||
.map_ok(|res| {
|
|
||||||
for event in res {
|
|
||||||
println!("Found {} '{}' {:?}", event.kind, event.content, event.tags)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
|
|
||||||
let mut notifications = CLIENT.notifications();
|
|
||||||
println!("Listening for events...");
|
|
||||||
while let Ok(notification) = notifications.recv().await {
|
|
||||||
if let RelayPoolNotification::Event {
|
|
||||||
subscription_id,
|
|
||||||
event,
|
|
||||||
..
|
|
||||||
} = notification
|
|
||||||
{
|
|
||||||
let kind = event.kind;
|
|
||||||
let content = &event.content;
|
|
||||||
println!("{kind}: {content}");
|
|
||||||
//break; // Exit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_task(text: &str, tags: &[Tag]) -> Event {
|
fn make_task(text: &str, tags: &[Tag]) -> Event {
|
||||||
|
@ -105,12 +75,38 @@ fn make_event(kind: Kind, text: &str, tags: &[Tag]) -> Event {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_event(event: &Event) {
|
||||||
|
println!("At {} found {} kind {} '{}' {:?}", event.created_at, event.id, event.kind, event.content, event.tags);
|
||||||
|
}
|
||||||
|
|
||||||
async fn repl() {
|
async fn repl() {
|
||||||
let mut tasks: Tasks = Default::default();
|
let mut tasks: Tasks = Default::default();
|
||||||
for argument in args().skip(1) {
|
for argument in args().skip(1) {
|
||||||
tasks.add_task(make_task(&argument, &[Tag::Hashtag("arg".to_string())]));
|
tasks.add_task(make_task(&argument, &[Tag::Hashtag("arg".to_string())]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let sub_id: SubscriptionId = CLIENT.subscribe(vec![Filter::new()], None).await;
|
||||||
|
let mut notifications = CLIENT.notifications();
|
||||||
|
|
||||||
|
println!("Finding existing events");
|
||||||
|
let res = CLIENT
|
||||||
|
.get_events_of(vec![Filter::new()], None)
|
||||||
|
.map_ok(|res| {
|
||||||
|
println!("Found {} events", res.len());
|
||||||
|
let (mut task_events, props): (Vec<Event>, Vec<Event>) = res.into_iter().partition(|e| e.kind.as_u32() == 1621);
|
||||||
|
task_events.sort_unstable();
|
||||||
|
for event in task_events {
|
||||||
|
print_event(&event);
|
||||||
|
tasks.add_task(event);
|
||||||
|
}
|
||||||
|
for event in props {
|
||||||
|
print_event(&event);
|
||||||
|
tasks.add_prop(&event);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
|
||||||
println!();
|
println!();
|
||||||
tasks.print_current_tasks();
|
tasks.print_current_tasks();
|
||||||
|
|
||||||
|
@ -196,16 +192,31 @@ async fn repl() {
|
||||||
tasks.add_task(tasks.make_task(&input));
|
tasks.add_task(tasks.make_task(&input));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.print_current_tasks();
|
|
||||||
}
|
}
|
||||||
Some(Err(e)) => eprintln!("{}", e),
|
Some(Err(e)) => eprintln!("{}", e),
|
||||||
None => break,
|
None => break,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while let Ok(notification) = notifications.try_recv() {
|
||||||
|
if let RelayPoolNotification::Event {
|
||||||
|
subscription_id,
|
||||||
|
event,
|
||||||
|
..
|
||||||
|
} = notification
|
||||||
|
{
|
||||||
|
print_event(&event);
|
||||||
|
tasks.add(*event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.print_current_tasks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.update_state("", |t| if t.pure_state() == State::Active { Some(State::Open) } else { None });
|
||||||
|
|
||||||
println!();
|
println!();
|
||||||
println!("Submitting created events");
|
println!("Submitting events");
|
||||||
|
// TODO send via message passing
|
||||||
let _ = CLIENT
|
let _ = CLIENT
|
||||||
.batch_event(
|
.batch_event(
|
||||||
tasks
|
tasks
|
||||||
|
|
22
src/task.rs
22
src/task.rs
|
@ -1,6 +1,6 @@
|
||||||
use std::fmt;
|
|
||||||
use nostr_sdk::{Event, EventId, Kind, Tag, Timestamp};
|
|
||||||
use crate::make_event;
|
use crate::make_event;
|
||||||
|
use nostr_sdk::{Event, EventId, Kind, Tag, Timestamp};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
pub(crate) struct Task {
|
pub(crate) struct Task {
|
||||||
pub(crate) event: Event,
|
pub(crate) event: Event,
|
||||||
|
@ -45,15 +45,15 @@ impl Task {
|
||||||
1633 => Some(State::Active),
|
1633 => Some(State::Active),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
.map(|s| TaskState {
|
.map(|s| TaskState {
|
||||||
name: if event.content.is_empty() {
|
name: if event.content.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(event.content.clone())
|
Some(event.content.clone())
|
||||||
},
|
},
|
||||||
state: s,
|
state: s,
|
||||||
time: event.created_at.clone(),
|
time: event.created_at.clone(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
57
src/tasks.rs
57
src/tasks.rs
|
@ -1,8 +1,10 @@
|
||||||
use crate::{make_event, make_task};
|
|
||||||
use crate::task::{Task, State};
|
|
||||||
use nostr_sdk::{Event, EventId, Tag};
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use nostr_sdk::{Event, EventId, Tag};
|
||||||
|
|
||||||
|
use crate::make_task;
|
||||||
|
use crate::task::{State, Task};
|
||||||
|
|
||||||
type TaskMap = HashMap<EventId, Task>;
|
type TaskMap = HashMap<EventId, Task>;
|
||||||
pub(crate) struct Tasks {
|
pub(crate) struct Tasks {
|
||||||
/// The Tasks
|
/// The Tasks
|
||||||
|
@ -38,12 +40,16 @@ impl Tasks {
|
||||||
/// Total time this task and its subtasks have been active
|
/// Total time this task and its subtasks have been active
|
||||||
fn total_time_tracked(&self, task: &EventId) -> u64 {
|
fn total_time_tracked(&self, task: &EventId) -> u64 {
|
||||||
self.tasks.get(task).map_or(0, |t| {
|
self.tasks.get(task).map_or(0, |t| {
|
||||||
t.time_tracked() + t.children.iter().map(|e| self.total_time_tracked(e)).sum::<u64>()
|
t.time_tracked()
|
||||||
|
+ t.children
|
||||||
|
.iter()
|
||||||
|
.map(|e| self.total_time_tracked(e))
|
||||||
|
.sum::<u64>()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn current_tasks(&self) -> Vec<&Task> {
|
pub(crate) fn current_tasks(&self) -> Vec<&Task> {
|
||||||
|
@ -54,10 +60,11 @@ impl Tasks {
|
||||||
self.position.map_or_else(
|
self.position.map_or_else(
|
||||||
|| self.tasks.values().collect(),
|
|| self.tasks.values().collect(),
|
||||||
|p| {
|
|p| {
|
||||||
self.tasks.get(&p).map_or(Vec::new(), |t| {
|
self.tasks
|
||||||
self.collect_tasks(&t.children)
|
.get(&p)
|
||||||
})
|
.map_or(Vec::new(), |t| self.collect_tasks(&t.children))
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn print_current_tasks(&self) {
|
pub(crate) fn print_current_tasks(&self) {
|
||||||
|
@ -97,20 +104,31 @@ impl Tasks {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_task(&mut self, event: Event) {
|
pub(crate) fn referenced_tasks<F: Fn(&mut Task)>(&mut self, event: &Event, f: F) {
|
||||||
for tag in event.tags.iter() {
|
for tag in event.tags.iter() {
|
||||||
match tag {
|
if let Tag::Event { event_id, .. } = tag {
|
||||||
Tag::Event { event_id, .. } => {
|
self.tasks.get_mut(event_id).map(|t| f(t));
|
||||||
self.tasks
|
|
||||||
.get_mut(event_id)
|
|
||||||
.map(|t| t.children.push(event.id));
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn add(&mut self, event: Event) {
|
||||||
|
if event.kind.as_u64() == 1621 {
|
||||||
|
self.add_task(event)
|
||||||
|
} else {
|
||||||
|
self.add_prop(&event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn add_task(&mut self, event: Event) {
|
||||||
|
self.referenced_tasks(&event, |t| t.children.push(event.id));
|
||||||
self.tasks.insert(event.id, Task::new(event));
|
self.tasks.insert(event.id, Task::new(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn add_prop(&mut self, event: &Event) {
|
||||||
|
self.referenced_tasks(&event, |t| t.props.push(event.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn move_up(&mut self) {
|
pub(crate) fn move_up(&mut self) {
|
||||||
self.move_to(
|
self.move_to(
|
||||||
self.position
|
self.position
|
||||||
|
@ -156,6 +174,7 @@ impl Tasks {
|
||||||
ParentIterator {
|
ParentIterator {
|
||||||
tasks: &self.tasks,
|
tasks: &self.tasks,
|
||||||
current: id,
|
current: id,
|
||||||
|
prev: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,12 +202,16 @@ impl Tasks {
|
||||||
struct ParentIterator<'a> {
|
struct ParentIterator<'a> {
|
||||||
tasks: &'a TaskMap,
|
tasks: &'a TaskMap,
|
||||||
current: Option<EventId>,
|
current: Option<EventId>,
|
||||||
|
/// Inexpensive helper to assert correctness
|
||||||
|
prev: Option<EventId>,
|
||||||
}
|
}
|
||||||
impl<'a> Iterator for ParentIterator<'a> {
|
impl<'a> Iterator for ParentIterator<'a> {
|
||||||
type Item = &'a Task;
|
type Item = &'a Task;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
self.current.and_then(|id| self.tasks.get(&id)).map(|t| {
|
self.current.and_then(|id| self.tasks.get(&id)).map(|t| {
|
||||||
|
self.prev.map(|id| assert!(t.children.contains(&id)));
|
||||||
|
self.prev = self.current;
|
||||||
self.current = t.parent_id();
|
self.current = t.parent_id();
|
||||||
t
|
t
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue