style::{Style, Color, Modifier},
};
use std::cmp::min;
-use std::collections::{HashMap, HashSet};
+use std::collections::{BTreeMap, HashMap, HashSet};
use std::io::{Stdout, Write, stdout};
use std::fs::File;
use unicode_width::UnicodeWidthStr;
PgUp, PgDn, Home, End, Ins, Del,
}
+#[derive(Debug)]
pub struct TuiError {
message: String,
}
}
}
}
+impl From<serde_json::Error> for TuiError {
+ fn from(err: serde_json::Error) -> Self {
+ TuiError {
+ message: err.to_string(),
+ }
+ }
+}
impl std::fmt::Display for TuiError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) ->
let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
terminal.clear()?;
- let state = TuiLogicalState::new(&client);
+ let state = TuiLogicalState::new(&client, cfgloc.clone());
let mut tui = Tui {
terminal,
PostReEdit(Post),
}
+#[derive(PartialEq, Eq, Debug, Clone)]
pub struct SavedFilePos {
// The current position we're _looking at_ within the file, within
// this run
LogicalAction;
fn handle_feed_updates(&mut self, _feeds_updated: &HashSet<FeedId>,
_client: &mut Client) {}
- fn save_file_position(
- &self, _file_positions: &mut HashMap<FeedId, SavedFilePos>) {}
+ fn save_file_position(&self) -> Option<(FeedId, SavedFilePos)> { None }
fn got_search_expression(&mut self, _dir: SearchDirection, _regex: String)
-> LogicalAction
{
overlay_activity_state: Option<Box<dyn ActivityState>>,
last_area: Option<Rect>,
file_positions: HashMap<FeedId, SavedFilePos>,
+ cfgloc: ConfigLocation,
}
impl TuiLogicalState {
- fn new(client: &Client) -> Self {
+ fn new(client: &Client, cfgloc: ConfigLocation) -> Self {
let activity_stack = ActivityStack::new();
let activity_state = main_menu(client);
overlay_activity_state: None,
last_area: None,
file_positions: HashMap::new(),
+ cfgloc,
}
}
}
fn changed_activity(&mut self, client: &mut Client, post: Option<Post>) {
- self.activity_state.save_file_position(&mut self.file_positions);
+ if let Some((feed_id, saved_pos)) =
+ self.activity_state.save_file_position()
+ {
+ let changed = self.file_positions.get(&feed_id) != Some(&saved_pos);
+ self.file_positions.insert(feed_id, saved_pos);
+ if changed {
+ // FIXME: maybe suddenly change our mind and go to the
+ // Error Log
+ self.save_ldb().unwrap();
+ }
+ }
self.activity_state = self.new_activity_state(
self.activity_stack.top(), client, post);
self.overlay_activity_state = match self.activity_stack.overlay() {
result.expect("FIXME: need to implement the Error Log here")
}
+
+ fn save_ldb(&self) -> Result<(), TuiError> {
+ let mut ldb = BTreeMap::new();
+ for (key, value) in &self.file_positions {
+ let keystr = match key {
+ FeedId::Home => "home".to_owned(),
+ FeedId::Mentions => "mentions".to_owned(),
+ FeedId::Ego => "ego".to_owned(),
+
+ // For all other feeds, we don't persist the last-read
+ // position.
+ _ => continue,
+ };
+
+ let valstr = match &value.latest_read_id {
+ Some(s) => s.clone(),
+ None => continue,
+ };
+
+ ldb.insert(keystr, valstr);
+ }
+ let mut json = serde_json::to_string_pretty(&ldb)?;
+ json.push('\n');
+ self.cfgloc.create_file("ldb", &json)?;
+ Ok(())
+ }
}