forked from janek/mostr
feat(tasks): prevent accidental redundant time-tracking
This commit is contained in:
parent
01305c5a78
commit
3cab294122
|
@ -574,7 +574,7 @@ async fn main() -> Result<()> {
|
||||||
match arg {
|
match arg {
|
||||||
None => tasks.move_to(None),
|
None => tasks.move_to(None),
|
||||||
Some(arg) => {
|
Some(arg) => {
|
||||||
if parse_tracking_stamp(arg).map(|stamp| tasks.track_at(stamp, None)).is_some() {
|
if parse_tracking_stamp(arg).and_then(|stamp| tasks.track_at(stamp, None)).is_some() {
|
||||||
let (label, times) = tasks.times_tracked();
|
let (label, times) = tasks.times_tracked();
|
||||||
println!("{}\n{}", label.italic(), times.rev().take(15).join("\n"));
|
println!("{}\n{}", label.italic(), times.rev().take(15).join("\n"));
|
||||||
}
|
}
|
||||||
|
|
63
src/tasks.rs
63
src/tasks.rs
|
@ -18,6 +18,11 @@ use crate::helpers::{CHARACTER_THRESHOLD, format_timestamp_local, format_timesta
|
||||||
use crate::kinds::*;
|
use crate::kinds::*;
|
||||||
use crate::task::{MARKER_DEPENDS, MARKER_PARENT, State, Task, TaskState};
|
use crate::task::{MARKER_DEPENDS, MARKER_PARENT, State, Task, TaskState};
|
||||||
|
|
||||||
|
const MAX_OFFSET: u64 = 9;
|
||||||
|
fn now() -> Timestamp {
|
||||||
|
Timestamp::now() + MAX_OFFSET
|
||||||
|
}
|
||||||
|
|
||||||
type TaskMap = HashMap<EventId, Task>;
|
type TaskMap = HashMap<EventId, Task>;
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct Tasks {
|
pub(crate) struct Tasks {
|
||||||
|
@ -146,14 +151,17 @@ impl Tasks {
|
||||||
self.get_position_ref().cloned()
|
self.get_position_ref().cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn now() -> Timestamp {
|
pub(crate) fn get_position_ref(&self) -> Option<&EventId> {
|
||||||
Timestamp::now() + Self::MAX_OFFSET
|
self.get_position_at(now()).1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_position_ref(&self) -> Option<&EventId> {
|
fn get_position_at(&self, timestamp: Timestamp) -> (Timestamp, Option<&EventId>) {
|
||||||
self.history_from(Self::now())
|
self.history_from(timestamp)
|
||||||
.last()
|
.last()
|
||||||
.and_then(|e| referenced_events(e))
|
.filter(|e| e.created_at <= timestamp)
|
||||||
|
.map_or_else(
|
||||||
|
|| (Timestamp::now(), None),
|
||||||
|
|e| (e.created_at, referenced_events(e)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ids of all subtasks recursively found for id, including itself
|
/// Ids of all subtasks recursively found for id, including itself
|
||||||
|
@ -387,7 +395,7 @@ impl Tasks {
|
||||||
let mut lock = stdout().lock();
|
let mut lock = stdout().lock();
|
||||||
if let Some(t) = self.get_current_task() {
|
if let Some(t) = self.get_current_task() {
|
||||||
let state = t.state_or_default();
|
let state = t.state_or_default();
|
||||||
let now = &Self::now();
|
let now = &now();
|
||||||
let mut tracking_stamp: Option<Timestamp> = None;
|
let mut tracking_stamp: Option<Timestamp> = None;
|
||||||
for elem in
|
for elem in
|
||||||
timestamps(self.history.get(&self.sender.pubkey()).into_iter().flatten(), &[t.get_id()])
|
timestamps(self.history.get(&self.sender.pubkey()).into_iter().flatten(), &[t.get_id()])
|
||||||
|
@ -627,8 +635,6 @@ impl Tasks {
|
||||||
}).into_iter().flatten()
|
}).into_iter().flatten()
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_OFFSET: u64 = 9;
|
|
||||||
|
|
||||||
pub(crate) fn move_to(&mut self, target: Option<EventId>) {
|
pub(crate) fn move_to(&mut self, target: Option<EventId>) {
|
||||||
self.view.clear();
|
self.view.clear();
|
||||||
let pos = self.get_position_ref();
|
let pos = self.get_position_ref();
|
||||||
|
@ -644,8 +650,8 @@ impl Tasks {
|
||||||
}
|
}
|
||||||
|
|
||||||
let now = Timestamp::now();
|
let now = Timestamp::now();
|
||||||
let offset: u64 = self.history_from(now).skip_while(|e| e.created_at.as_u64() > now.as_u64() + Self::MAX_OFFSET).count() as u64;
|
let offset: u64 = self.history_from(now).skip_while(|e| e.created_at.as_u64() > now.as_u64() + MAX_OFFSET).count() as u64;
|
||||||
if offset >= Self::MAX_OFFSET {
|
if offset >= MAX_OFFSET {
|
||||||
warn!("Whoa you are moving around quickly! Give me a few seconds to process.")
|
warn!("Whoa you are moving around quickly! Give me a few seconds to process.")
|
||||||
}
|
}
|
||||||
self.submit(
|
self.submit(
|
||||||
|
@ -732,22 +738,39 @@ impl Tasks {
|
||||||
self.tasks.get(id).map_or(id.to_string(), |t| t.get_title())
|
self.tasks.get(id).map_or(id.to_string(), |t| t.get_title())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse string and set tracking
|
/// Parse relative time string and track for current position
|
||||||
|
///
|
||||||
/// Returns false and prints a message if parsing failed
|
/// Returns false and prints a message if parsing failed
|
||||||
pub(crate) fn track_from(&mut self, str: &str) -> bool {
|
pub(crate) fn track_from(&mut self, str: &str) -> bool {
|
||||||
parse_tracking_stamp(str)
|
parse_tracking_stamp(str)
|
||||||
.map(|stamp| self.track_at(stamp, self.get_position()))
|
.and_then(|stamp| self.track_at(stamp, self.get_position()))
|
||||||
.is_some()
|
.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn track_at(&mut self, time: Timestamp, task: Option<EventId>) -> EventId {
|
pub(crate) fn track_at(&mut self, time: Timestamp, target: Option<EventId>) -> Option<EventId> {
|
||||||
info!("{} {}", task.map_or(
|
let current_pos = self.get_position_at(time);
|
||||||
String::from("Stopping time-tracking at"),
|
if (time < Timestamp::now() || target.is_none()) && current_pos.1 == target.as_ref() {
|
||||||
|id| format!("Tracking \"{}\" from", self.get_task_title(&id))), format_timestamp_relative(&time));
|
warn!("Already {} from {}",
|
||||||
|
target.map_or("stopped time-tracking".to_string(),
|
||||||
|
|id| format!("tracking \"{}\"", self.get_task_title(&id))),
|
||||||
|
format_timestamp_relative(¤t_pos.0),
|
||||||
|
);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
info!("{}", match target {
|
||||||
|
None => format!("Stopping time-tracking of \"{}\" at {}",
|
||||||
|
current_pos.1.map_or("???".to_string(), |id| self.get_task_title(id)),
|
||||||
|
format_timestamp_relative(&time)),
|
||||||
|
Some(new_id) => format!("Tracking \"{}\" from {}{}",
|
||||||
|
self.get_task_title(&new_id),
|
||||||
|
format_timestamp_relative(&time),
|
||||||
|
current_pos.1.filter(|id| id != &&new_id).map(
|
||||||
|
|id| format!(" replacing \"{}\"", self.get_task_title(id))).unwrap_or_default()),
|
||||||
|
});
|
||||||
self.submit(
|
self.submit(
|
||||||
build_tracking(task)
|
build_tracking(target)
|
||||||
.custom_created_at(time)
|
.custom_created_at(time)
|
||||||
)
|
).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sign and queue the event to the relay, returning its id
|
/// Sign and queue the event to the relay, returning its id
|
||||||
|
@ -1175,7 +1198,7 @@ mod tasks_test {
|
||||||
let zero = EventId::all_zeros();
|
let zero = EventId::all_zeros();
|
||||||
|
|
||||||
tasks.track_at(Timestamp::from(0), None);
|
tasks.track_at(Timestamp::from(0), None);
|
||||||
assert_eq!(tasks.history.len(), 1);
|
assert_eq!(tasks.history.len(), 0);
|
||||||
|
|
||||||
let almost_now: Timestamp = Timestamp::now() - 12u64;
|
let almost_now: Timestamp = Timestamp::now() - 12u64;
|
||||||
tasks.track_at(Timestamp::from(11), Some(zero));
|
tasks.track_at(Timestamp::from(11), Some(zero));
|
||||||
|
@ -1184,7 +1207,7 @@ mod tasks_test {
|
||||||
assert!(tasks.time_tracked(zero) > almost_now.as_u64());
|
assert!(tasks.time_tracked(zero) > almost_now.as_u64());
|
||||||
|
|
||||||
tasks.track_at(Timestamp::from(22), None);
|
tasks.track_at(Timestamp::from(22), None);
|
||||||
assert_eq!(tasks.get_own_history().unwrap().len(), 4);
|
assert_eq!(tasks.get_own_history().unwrap().len(), 2);
|
||||||
assert_eq!(tasks.time_tracked(zero), 11);
|
assert_eq!(tasks.time_tracked(zero), 11);
|
||||||
|
|
||||||
// TODO test received events
|
// TODO test received events
|
||||||
|
|
Loading…
Reference in New Issue