use crate::db; use super::State; use notmuch::DatabaseMode; use std::io::Write; use termion::{color, event::Key}; pub struct Threads { threads: Vec, i: isize, query: Option, } pub struct Thread { subject: String, authors: Vec, _id: String, messages: Vec, } impl<'d, 'q> Thread { pub fn new(thread: notmuch::Thread<'d, 'q>) -> Self { Self { subject: thread.subject().to_string(), authors: thread.authors().clone(), _id: thread.id().to_string(), messages: thread.messages().map(|m| m.id().to_string()).collect(), } } pub fn remove_tag(&self, tag: &str) { let db = db::open(DatabaseMode::ReadWrite).unwrap(); for m_id in self.messages.iter() { db .find_message(m_id) .unwrap() .unwrap() .remove_tag(tag) .unwrap(); } } } impl<'d, 'q> Threads { pub fn from_query(query: Option, threads: notmuch::Threads<'d, 'q>) -> Self { Self { threads: threads.map(Thread::new).collect(), i: 0, query, } } pub fn reload(&mut self) { if let Some(query) = &self.query { self.threads = db::open(DatabaseMode::ReadOnly) .unwrap() .create_query(query) .unwrap() .search_threads() .unwrap() .map(Thread::new) .collect(); if self.i >= self.threads.len() as isize { self.i = self.threads.len() as isize - 1; } } } pub fn init(&mut self, out: &mut W) { draw(&self, out); } pub fn tick(mut self, out: &mut W, key: Key) -> State { match key { Key::Char('j') => self.i += 1, Key::Char('k') => self.i -= 1, Key::Char('i') => { self.threads[self.i as usize].remove_tag("inbox"); } Key::Char('r') => self.reload(), _ => (), } self.i = self.i.rem_euclid(self.threads.len() as isize); draw(&self, out); State::Threads(self) } } fn draw(state: &Threads, out: &mut W) { write!(out, "{}", termion::clear::All).unwrap(); for (i, thread) in state.threads.iter().enumerate() { write!(out, "{}", termion::cursor::Goto(1, (i + 1) as u16)).unwrap(); let highlight = i == state.i as usize; if highlight { write!(out, "{}", color::Fg(color::Red)).unwrap(); } write!(out, "thread {:?}, {:?}", thread.subject, thread.authors).unwrap(); if highlight { write!(out, "{}", color::Fg(color::Reset)).unwrap(); } } out.flush().unwrap(); }