use std::collections::{BTreeMap, HashMap, HashSet, hash_map};
use std::io::{Stdout, Write, stdout};
use std::fs::File;
+use std::time::Duration;
use unicode_width::UnicodeWidthStr;
use super::activity_stack::*;
}
}
-#[derive(Debug)]
+#[derive(Debug, Clone)]
enum SubthreadEvent {
TermEv(Event),
StreamEv(StreamUpdate),
+ LDBCheckpointTimer,
}
pub enum PhysicalAction {
}
fn run_inner(&mut self) -> Result<(), TuiError> {
- {
- let sender = self.subthread_sender.clone();
- self.client.start_streaming_thread(
- &StreamId::User, Box::new(move |update| {
- if sender.send(
- SubthreadEvent::StreamEv(update)).is_err() {
- // It would be nice to do something about this
- // error, but what _can_ we do? We can hardly send
- // an error notification back to the main thread,
- // because that communication channel is just what
- // we've had a problem with.
- }
- }))?;
- }
+ self.start_streaming_subthread(StreamId::User)?;
+ self.start_timing_subthread(Duration::from_secs(120),
+ SubthreadEvent::LDBCheckpointTimer)?;
// Now fetch the two basic feeds - home and mentions. Most
// importantly, getting the mentions feed started means that
self.main_loop()
}
+ fn start_streaming_subthread(&mut self, id: StreamId)
+ -> Result<(), TuiError>
+ {
+ let sender = self.subthread_sender.clone();
+ self.client.start_streaming_thread(
+ &id, Box::new(move |update| {
+ if sender.send(
+ SubthreadEvent::StreamEv(update).clone()).is_err() {
+ // It would be nice to do something about this
+ // error, but what _can_ we do? We can hardly send
+ // an error notification back to the main thread,
+ // because that communication channel is just what
+ // we've had a problem with.
+ }
+ }))?;
+
+ Ok(())
+ }
+
+ fn start_timing_subthread(&mut self, dur: Duration, ev: SubthreadEvent)
+ -> Result<(), TuiError>
+ {
+ let sender = self.subthread_sender.clone();
+ let _joinhandle = std::thread::spawn(move || {
+ loop {
+ std::thread::sleep(dur);
+ // Similarly ignore the error (see above)
+ if sender.send(ev.clone()).is_err() {}
+ }
+ });
+ Ok(())
+ }
+
fn main_loop(&mut self) -> Result<(), TuiError> {
'outer: loop {
let state = &mut self.state;
_ => (),
}
}
+ Ok(SubthreadEvent::LDBCheckpointTimer) =>
+ state.checkpoint_ldb(),
}
}
}
}
}
- fn changed_activity(&mut self, client: &mut Client, post: Option<Post>,
- is_interrupt: bool) {
+ fn checkpoint_ldb(&mut self) {
if let Some((feed_id, saved_pos)) =
self.activity_state.save_file_position()
{
self.save_ldb().unwrap();
}
}
+ }
+
+ fn changed_activity(&mut self, client: &mut Client, post: Option<Post>,
+ is_interrupt: bool) {
+ self.checkpoint_ldb();
self.activity_state = self.new_activity_state(
self.activity_stack.top(), client, post, is_interrupt);
self.overlay_activity_state = match self.activity_stack.overlay() {