subconscious: use ScrollPane for history pane

Replace bare history_scroll: u16 with ScrollPaneState. The history
pane now uses ScrollPane for rendering, getting proper height caching
and scrollbar for free.

Also relax ScrollItem lifetime bounds from 'static to 'a so
non-static Lines (built on the fly during render) can be used.

Co-Authored-By: Kent Overstreet <kent.overstreet@gmail.com>
This commit is contained in:
ProofOfConcept 2026-04-11 01:34:39 -04:00 committed by Kent Overstreet
parent 2230fdf3c1
commit d18bf6243a
2 changed files with 14 additions and 12 deletions

View file

@ -22,19 +22,19 @@ pub trait ScrollItem {
// Blanket impls for common types // Blanket impls for common types
impl ScrollItem for Line<'static> { impl<'a> ScrollItem for Line<'a> {
fn content(&self) -> Text<'_> { fn content(&self) -> Text<'_> {
Text::from(self.clone()) Text::from(self.clone())
} }
} }
impl ScrollItem for Vec<Line<'static>> { impl<'a> ScrollItem for Vec<Line<'a>> {
fn content(&self) -> Text<'_> { fn content(&self) -> Text<'_> {
Text::from(self.clone()) Text::from(self.clone())
} }
} }
impl ScrollItem for Text<'static> { impl<'a> ScrollItem for Text<'a> {
fn content(&self) -> Text<'_> { fn content(&self) -> Text<'_> {
self.clone() self.clone()
} }

View file

@ -28,7 +28,7 @@ pub(crate) struct SubconsciousScreen {
list_state: ListState, list_state: ListState,
output_tree: SectionTree, output_tree: SectionTree,
context_tree: SectionTree, context_tree: SectionTree,
history_scroll: u16, history_scroll: super::scroll_pane::ScrollPaneState,
} }
impl SubconsciousScreen { impl SubconsciousScreen {
@ -40,7 +40,7 @@ impl SubconsciousScreen {
list_state, list_state,
output_tree: SectionTree::new(), output_tree: SectionTree::new(),
context_tree: SectionTree::new(), context_tree: SectionTree::new(),
history_scroll: 0, history_scroll: super::scroll_pane::ScrollPaneState::new(),
} }
} }
@ -88,10 +88,10 @@ impl ScreenView for SubconsciousScreen {
} }
Pane::Outputs => self.output_tree.handle_nav(code, &output_sections, area.height), Pane::Outputs => self.output_tree.handle_nav(code, &output_sections, area.height),
Pane::History => match code { Pane::History => match code {
KeyCode::Up => self.history_scroll = self.history_scroll.saturating_sub(3), KeyCode::Up => self.history_scroll.scroll_up(3),
KeyCode::Down => self.history_scroll += 3, KeyCode::Down => self.history_scroll.scroll_down(3),
KeyCode::PageUp => self.history_scroll = self.history_scroll.saturating_sub(20), KeyCode::PageUp => self.history_scroll.scroll_up(20),
KeyCode::PageDown => self.history_scroll += 20, KeyCode::PageDown => self.history_scroll.scroll_down(20),
_ => {} _ => {}
} }
Pane::Context => self.context_tree.handle_nav(code, &context_sections, area.height), Pane::Context => self.context_tree.handle_nav(code, &context_sections, area.height),
@ -146,7 +146,7 @@ impl SubconsciousScreen {
fn reset_pane_state(&mut self) { fn reset_pane_state(&mut self) {
self.output_tree = SectionTree::new(); self.output_tree = SectionTree::new();
self.context_tree = SectionTree::new(); self.context_tree = SectionTree::new();
self.history_scroll = 0; self.history_scroll = super::scroll_pane::ScrollPaneState::new();
} }
/// Get the agent Arc for the selected item, whether subconscious or unconscious. /// Get the agent Arc for the selected item, whether subconscious or unconscious.
@ -300,7 +300,7 @@ impl SubconsciousScreen {
render_scrollable(frame, area, lines, block, self.output_tree.scroll); render_scrollable(frame, area, lines, block, self.output_tree.scroll);
} }
fn draw_history(&self, frame: &mut Frame, area: Rect, app: &App) { fn draw_history(&mut self, frame: &mut Frame, area: Rect, app: &App) {
let dim = Style::default().fg(Color::DarkGray); let dim = Style::default().fg(Color::DarkGray);
let key_style = Style::default().fg(Color::Yellow); let key_style = Style::default().fg(Color::Yellow);
@ -345,7 +345,9 @@ impl SubconsciousScreen {
Style::default().fg(Color::DarkGray), Style::default().fg(Color::DarkGray),
)); ));
} }
render_scrollable(frame, area, lines, block, self.history_scroll); let widget = super::scroll_pane::ScrollPane::new(&lines)
.block(block);
frame.render_stateful_widget(widget, area, &mut self.history_scroll);
} }
fn draw_context( fn draw_context(