Implement help page and delay receiving area to hopefully improve first-page performance a bit

This commit is contained in:
itsjunetime
2025-03-01 18:04:33 -07:00
parent 10e1f6cb9f
commit d2be289e80
2 changed files with 107 additions and 20 deletions
+17 -9
View File
@@ -71,14 +71,6 @@ pub fn start_rendering(
receiver: Receiver<RenderNotif>, receiver: Receiver<RenderNotif>,
size: WindowSize size: WindowSize
) -> Result<(), SendError<Result<RenderInfo, RenderError>>> { ) -> Result<(), SendError<Result<RenderInfo, RenderError>>> {
// first, wait 'til we get told what the current starting area is so that we can set it to
// know what to render to
let mut area = loop {
if let RenderNotif::Area(r) = receiver.recv().unwrap() {
break r;
}
};
// We want this outside of 'reload so that if the doc reloads, the search term that somebody // We want this outside of 'reload so that if the doc reloads, the search term that somebody
// set will still get highlighted in the reloaded doc // set will still get highlighted in the reloaded doc
let mut search_term = None; let mut search_term = None;
@@ -90,6 +82,7 @@ pub fn start_rendering(
let mut stored_doc = None; let mut stored_doc = None;
let mut invert = false; let mut invert = false;
let mut preserved_area = None;
'reload: loop { 'reload: loop {
let doc = match Document::open(path) { let doc = match Document::open(path) {
@@ -143,6 +136,21 @@ pub fn start_rendering(
fill_default::<PrevRender>(&mut rendered, n_pages); fill_default::<PrevRender>(&mut rendered, n_pages);
let mut start_point = 0; let mut start_point = 0;
// next, we gotta wait 'til we get told what the current starting area is so that we can
// set it to know what to render to
let area = match preserved_area {
Some(a) => a,
None => {
let new_area = loop {
if let RenderNotif::Area(r) = receiver.recv().unwrap() {
break r;
}
};
preserved_area = Some(new_area);
new_area
}
};
// This is kinda a weird way of doing this, but if we get a notification that the area // This is kinda a weird way of doing this, but if we get a notification that the area
// changed, we want to start re-rending all of the pages, but we don't want to reload the // changed, we want to start re-rending all of the pages, but we don't want to reload the
// document. If there was a mechanism to say 'start this for-loop over' then I would do // document. If there was a mechanism to say 'start this for-loop over' then I would do
@@ -164,7 +172,7 @@ pub fn start_rendering(
RenderNotif::Area(new_area) => { RenderNotif::Area(new_area) => {
let bigger = let bigger =
new_area.width > area.width || new_area.height > area.height; new_area.width > area.width || new_area.height > area.height;
area = new_area; preserved_area = Some(new_area);
// we only want to re-render pages if the new area is greater than the old // we only want to re-render pages if the new area is greater than the old
// one, 'cause then we might need sharper images to make it all look good. // one, 'cause then we might need sharper images to make it all look good.
// If the new area is smaller, then the same high-quality-rendered images // If the new area is smaller, then the same high-quality-rendered images
+90 -11
View File
@@ -16,8 +16,9 @@ use ratatui::{
Frame, Frame,
layout::{Constraint, Flex, Layout, Rect}, layout::{Constraint, Flex, Layout, Rect},
style::{Color, Style}, style::{Color, Style},
text::Span, symbols::border,
widgets::{Block, Borders, Padding} text::{Span, Text},
widgets::{Block, Borders, Clear, Padding}
}; };
use ratatui_image::{Image, protocol::Protocol}; use ratatui_image::{Image, protocol::Protocol};
@@ -32,7 +33,8 @@ pub struct Tui {
// jumping to a specific page // jumping to a specific page
prev_msg: Option<BottomMessage>, prev_msg: Option<BottomMessage>,
rendered: Vec<RenderedInfo>, rendered: Vec<RenderedInfo>,
page_constraints: PageConstraints page_constraints: PageConstraints,
showing_help_msg: bool
} }
#[derive(Default, Debug)] #[derive(Default, Debug)]
@@ -86,7 +88,8 @@ impl Tui {
bottom_msg: BottomMessage::Help, bottom_msg: BottomMessage::Help,
last_render: LastRender::default(), last_render: LastRender::default(),
rendered: vec![], rendered: vec![],
page_constraints: PageConstraints { max_wide, r_to_l } page_constraints: PageConstraints { max_wide, r_to_l },
showing_help_msg: false
} }
} }
@@ -104,6 +107,11 @@ impl Tui {
// TODO: Make a way to fill the width of the screen with one page and scroll down to view it // TODO: Make a way to fill the width of the screen with one page and scroll down to view it
pub fn render(&mut self, frame: &mut Frame<'_>, main_area: &[Rect]) { pub fn render(&mut self, frame: &mut Frame<'_>, main_area: &[Rect]) {
if self.showing_help_msg {
self.render_help_msg(frame);
return;
}
let top_block = Block::new() let top_block = Block::new()
.padding(Padding { .padding(Padding {
right: 2, right: 2,
@@ -161,10 +169,7 @@ impl Tui {
frame.render_widget(rendered_span, bottom_layout[1]); frame.render_widget(rendered_span, bottom_layout[1]);
let (msg_str, color): (Cow<'_, str>, _) = match self.bottom_msg { let (msg_str, color): (Cow<'_, str>, _) = match self.bottom_msg {
BottomMessage::Help => ( BottomMessage::Help => ("?: Show help page".into(), Color::Blue),
"/: Search, g: Go To Page, n: Next Search Result, N: Previous Search Result".into(),
Color::Blue
),
BottomMessage::Error(ref e) => (e.as_str().into(), Color::Red), BottomMessage::Error(ref e) => (e.as_str().into(), Color::Red),
BottomMessage::Input(ref input_state) => ( BottomMessage::Input(ref input_state) => (
match input_state { match input_state {
@@ -415,6 +420,10 @@ impl Tui {
Some(InputAction::Redraw) Some(InputAction::Redraw)
} }
'i' => Some(InputAction::Invert), 'i' => Some(InputAction::Invert),
'?' => {
self.showing_help_msg = true;
Some(InputAction::Redraw)
}
'n' if self.page < self.rendered.len() - 1 => { 'n' if self.page < self.rendered.len() - 1 => {
// TODO: If we can't find one, then maybe like block until we've verified // TODO: If we can't find one, then maybe like block until we've verified
// all the pages have been checked? // all the pages have been checked?
@@ -486,8 +495,8 @@ impl Tui {
KeyCode::Down => self.change_page(PageChange::Next, ChangeAmount::WholeScreen), KeyCode::Down => self.change_page(PageChange::Next, ChangeAmount::WholeScreen),
KeyCode::Left => self.change_page(PageChange::Prev, ChangeAmount::Single), KeyCode::Left => self.change_page(PageChange::Prev, ChangeAmount::Single),
KeyCode::Up => self.change_page(PageChange::Prev, ChangeAmount::WholeScreen), KeyCode::Up => self.change_page(PageChange::Prev, ChangeAmount::WholeScreen),
KeyCode::Esc => match self.bottom_msg { KeyCode::Esc => match (self.showing_help_msg, &self.bottom_msg) {
BottomMessage::Help => Some(InputAction::QuitApp), (false, BottomMessage::Help) => Some(InputAction::QuitApp),
_ => { _ => {
// When we hit escape, we just want to pop off the current message and // When we hit escape, we just want to pop off the current message and
// show the underlying one. // show the underlying one.
@@ -598,11 +607,81 @@ impl Tui {
self.prev_msg = None; self.prev_msg = None;
self.bottom_msg = BottomMessage::default(); self.bottom_msg = BottomMessage::default();
} }
MessageSetting::Pop => self.bottom_msg = self.prev_msg.take().unwrap_or_default() MessageSetting::Pop =>
if self.showing_help_msg {
self.last_render.rect = Rect::default();
self.showing_help_msg = false;
} else {
self.bottom_msg = self.prev_msg.take().unwrap_or_default();
},
} }
} }
pub fn render_help_msg(&self, frame: &mut Frame<'_>) {
let frame_area = frame.area();
frame.render_widget(Clear, frame_area);
let block = Block::new()
.title("Help")
.padding(Padding::proportional(1))
.borders(Borders::ALL)
.border_set(border::ROUNDED)
.border_style(Color::Blue);
let help_span = Text::raw(HELP_PAGE);
let max_w: u16 = HELP_PAGE
.lines()
.map(str::len)
.max()
.unwrap_or_default()
.try_into()
.expect("Every help text line must be shorter than u16::MAX");
let layout = Layout::horizontal([
Constraint::Fill(1),
Constraint::Length(max_w + 6),
Constraint::Fill(1)
])
.split(frame_area);
let block_area = Layout::vertical([
Constraint::Fill(1),
Constraint::Length(u16::try_from(HELP_PAGE.lines().count()).unwrap() + 4),
Constraint::Fill(1)
])
.split(layout[1]);
let block_inner = block.inner(block_area[1]);
frame.render_widget(block, block_area[1]);
frame.render_widget(help_span, block_inner);
}
} }
static HELP_PAGE: &str = "\
l, h, left, right:
Go forward/backwards a single page
j, k, down, up:
Go forwards/backwards a screen's worth of pages
q, esc:
Quit
g:
Go to specific page (type numbers after 'g')
/:
Search
n, N:
Next/Previous search result
i:
Invert colors
f:
Remove borders/fullscreen
?:
Show this page
ctrl+z:
Suspend & background tdf \
";
pub enum InputAction { pub enum InputAction {
Redraw, Redraw,
JumpingToPage(usize), JumpingToPage(usize),