use super::super::{BlockKind, Transcript};
use crate::interactive::tui::types::App;
#[derive(Debug, Clone, Copy)]
struct ResultRef {
block: usize,
chapter: u32,
}
impl Transcript {
fn results(&self) -> Vec<ResultRef> {
self.blocks()
.iter()
.enumerate()
.filter(|(_, block)| block.kind == BlockKind::Table)
.map(|(index, block)| ResultRef {
block: index,
chapter: block.chapter,
})
.collect()
}
pub(crate) fn step_result(&mut self, forward: bool, viewport: (u16, u16)) -> bool {
let (width, height) = (viewport.0 as usize, viewport.1 as usize);
let results = self.results();
if results.is_empty() {
return false;
}
let (rows, starts) = self.render(width);
let rem = rows.len().saturating_sub(height);
let top = rem.saturating_sub(self.scroll_up.min(rem));
let current = if self.is_following_tail() {
Some(results.len() - 1)
} else {
results
.iter()
.rposition(|result| starts[result.block] <= top)
};
let target = match (current, forward) {
(Some(i), true) => (i + 1 < results.len()).then_some(i + 1),
(Some(i), false) => i.checked_sub(1),
(None, true) => Some(0),
(None, false) => None,
};
let Some(target) = target else {
return false;
};
let ResultRef { block, chapter } = results[target];
if self.is_folded(chapter) {
self.toggle_chapter(chapter);
}
let (rows, starts) = self.render(width);
let rem = rows.len().saturating_sub(height);
let top = starts[block].min(rem);
self.scroll_up = rem - top;
if self.scroll_up == 0 {
self.unseen_rows = 0;
}
true
}
}
impl App {
pub(crate) fn step_result(&mut self, forward: bool) {
if self.transcript.step_result(forward, self.viewport.get()) {
return;
}
if self
.transcript
.blocks()
.iter()
.all(|block| block.kind != BlockKind::Table)
{
self.transcript
.push(BlockKind::System, "No results to step to.");
}
}
}