1use crate::Session;
10use jiff::Zoned;
11use sioul_core::config::{self, Config};
12use sioul_core::reminders;
13
14pub(crate) fn list(s: &Session) -> Result<(), String> {
16 let now = Zoned::now();
17 let (all, _) = reminders::gather(&s.config, &s.tr, &now);
18 let stamp = now.timestamp().as_second();
19 let dir = reminders::told_dir();
20 let coming: Vec<&reminders::Reminder> = all.iter().filter(|r| r.until > stamp && r.at < stamp + 14 * 86_400).collect();
21 if coming.is_empty() {
22 println!("{}", s.tr.text("remind-nothing", None));
23 }
24 for reminder in coming {
25 let at = jiff::Timestamp::from_second(reminder.at).map(|t| t.to_zoned(now.time_zone().clone())).map_err(|e| e.to_string())?;
26 let told = if reminders::told(&dir, &reminder.key) { format!(" ({})", s.tr.text("remind-told", None)) } else { String::new() };
27 println!("{}{told}\n {}{}", s.tr.date(&at, true), crate::one_line(&reminder.title), if reminder.body.is_empty() { String::new() } else { format!(" — {}", crate::one_line(&reminder.body)) });
29 }
30 Ok(())
31}
32
33pub(crate) fn watch(s: &Session) -> Result<(), String> {
36 let lock_path = config::state_dir().join("remind.lock");
37 std::fs::create_dir_all(config::state_dir()).map_err(|e| e.to_string())?;
38 let lock = std::fs::OpenOptions::new().create(true).truncate(false).write(true).open(&lock_path).map_err(|e| format!("{}: {e}", lock_path.display()))?;
39 if lock.try_lock().is_err() {
41 println!("{}", s.tr.text("remind-running", None));
42 return Ok(());
43 }
44 let _ = std::fs::write(config::state_dir().join("remind.pid"), std::process::id().to_string());
46 println!("{}", s.tr.text("remind-watching", None));
47 let dir = reminders::told_dir();
48 let mut forgotten_on = None;
49 loop {
50 let config = Config::load(&s.config_path).unwrap_or_default();
52 let now = Zoned::now();
53 if forgotten_on != Some(now.date()) {
54 reminders::forget_old(&dir);
55 forgotten_on = Some(now.date());
56 }
57 let (all, holds) = reminders::gather(&config, &s.tr, &now);
60 for reminder in reminders::to_tell(all, &dir, now.timestamp().as_second(), &holds) {
61 if let Err(e) = sioul_sync::notify::remind(&reminder.title, &reminder.body, None) {
62 eprintln!("{e}");
63 }
64 }
65 std::thread::sleep(std::time::Duration::from_secs(60));
66 }
67}