file_desc: Type,
search_direction: Option<SearchDirection>,
last_search: Option<Regex>,
+ latest_read_index: Option<isize>,
}
impl<Type: FileType, Source: FileDataSource> File<Type, Source> {
file_desc,
search_direction: None,
last_search: None,
+ latest_read_index: None,
};
Ok(ff)
}
}
}
+ fn update_latest_read_index(&mut self) {
+ let pos_item_shown_in_full = match self.pos.width {
+ None => self.pos.line > 0,
+ Some(pw) => match self.last_size {
+ None => false, // if in doubt don't mark things as read
+ Some((sw, _sh)) => if pw == sw {
+ self.rendered.get(&self.pos.item)
+ .map_or(false, |lines| self.pos.line == lines.len())
+ } else {
+ false // similarly, if in doubt
+ }
+ }
+ };
+
+ let latest_read_index = if pos_item_shown_in_full {
+ self.pos.item
+ } else {
+ self.pos.item - 1
+ };
+
+ self.latest_read_index = max(
+ self.latest_read_index, Some(latest_read_index));
+ }
+
fn update_pos_for_size(&mut self, w: usize, h: usize) {
if self.pos.width.is_none() && self.pos.line == 0 {
// Special case: look at the _top_ of the item
None => panic!("handle_keypress before resize"),
};
- match self.ui_mode {
+ self.update_latest_read_index();
+
+ // This whole match is in a lambda which we immediately call,
+ // so that if any clause needs to do an early return, it will
+ // only return from this lambda and not the whole function.
+ // That way we never miss the update_latest_read_index at the
+ // end.
+ let action = (|| match self.ui_mode {
UIMode::Normal => match key {
Pr('q') | Pr('Q') => LogicalAction::Pop,
Up => {
Pr('q') | Pr('Q') => self.abort_selection(),
_ => LogicalAction::Nothing,
}
- }
+ })();
+
+ self.update_latest_read_index();
+
+ action
}
fn handle_feed_updates(&mut self, feeds_updated: &HashSet<FeedId>,