pub struct ChatViewport {
pub scroll_offset: usize,
pub scroll_target: usize,
pub scroll_pos: f32,
pub scrollbar_thumb_top: f32,
pub scrollbar_thumb_size: f32,
pub auto_scroll: bool,
pub width: u16,
pub message_heights: Vec<usize>,
pub message_heights_width: u16,
pub dirty_from: Option<usize>,
pub height_prefix_sums: Vec<usize>,
pub prefix_sums_width: u16,
}Expand description
Single owner of all chat layout state: scroll, per-message heights, and prefix sums.
Consolidates state previously scattered across App (scroll fields, prefix sums),
ChatMessage (cached_visual_height/cached_visual_width), and BlockCache (wrapped_height/wrapped_width).
Per-block heights remain on BlockCache via set_height() / height_at(), but
the viewport owns the validity width that governs whether those caches are considered
current. On resize, on_frame() zeroes message heights and clears prefix sums,
causing the next update_visual_heights() pass to re-measure every message
using ground-truth Paragraph::line_count().
Fields§
§scroll_offset: usizeRendered scroll offset (rounded from scroll_pos).
scroll_target: usizeTarget scroll offset requested by user input or auto-scroll.
scroll_pos: f32Smooth scroll position (fractional) for animation.
scrollbar_thumb_top: f32Smoothed scrollbar thumb top row (fractional) for animation.
scrollbar_thumb_size: f32Smoothed scrollbar thumb height (fractional) for animation.
auto_scroll: boolWhether to auto-scroll to bottom on new content.
width: u16Current terminal width. Set by on_frame() each render cycle.
message_heights: Vec<usize>Visual height (in terminal rows) of each message, indexed by message position.
Zeroed on resize; rebuilt by measure_message_height().
message_heights_width: u16Width at which message_heights was last computed.
dirty_from: Option<usize>Oldest message index whose cached height may be stale.
height_prefix_sums: Vec<usize>Cumulative heights: height_prefix_sums[i] = sum of heights 0..=i.
Enables O(log n) binary search for first visible message and O(1) total height.
prefix_sums_width: u16Width at which prefix sums were last computed.
Implementations§
Source§impl ChatViewport
impl ChatViewport
Sourcepub fn on_frame(&mut self, width: u16)
pub fn on_frame(&mut self, width: u16)
Called at top of each render frame. Detects width change and invalidates all cached heights so they get re-measured at the new width.
Sourcepub fn message_height(&self, idx: usize) -> usize
pub fn message_height(&self, idx: usize) -> usize
Get the cached visual height for message idx. Returns 0 if not yet computed.
Sourcepub fn set_message_height(&mut self, idx: usize, h: usize)
pub fn set_message_height(&mut self, idx: usize, h: usize)
Set the visual height for message idx, growing the vec if needed.
Does NOT update message_heights_width - the caller must call
mark_heights_valid() after the full re-measurement pass completes.
Sourcepub fn mark_heights_valid(&mut self)
pub fn mark_heights_valid(&mut self)
Mark all message heights as valid at the current width.
Call after update_visual_heights() finishes re-measuring.
Sourcepub fn mark_message_dirty(&mut self, idx: usize)
pub fn mark_message_dirty(&mut self, idx: usize)
Mark cached heights dirty from idx onward.
Sourcepub fn rebuild_prefix_sums(&mut self)
pub fn rebuild_prefix_sums(&mut self)
Rebuild prefix sums from message_heights.
O(1) fast path when width unchanged and only the last message changed (streaming).
Sourcepub fn total_message_height(&self) -> usize
pub fn total_message_height(&self) -> usize
Total height of all messages (O(1) via prefix sums).
Sourcepub fn cumulative_height_before(&self, idx: usize) -> usize
pub fn cumulative_height_before(&self, idx: usize) -> usize
Cumulative height of messages 0..idx (O(1) via prefix sums).
Sourcepub fn find_first_visible(&self, scroll_offset: usize) -> usize
pub fn find_first_visible(&self, scroll_offset: usize) -> usize
Binary search for the first message whose cumulative range overlaps scroll_offset.
Sourcepub fn scroll_down(&mut self, lines: usize)
pub fn scroll_down(&mut self, lines: usize)
Scroll down by lines. Auto-scroll re-engagement handled by render.
Sourcepub fn engage_auto_scroll(&mut self)
pub fn engage_auto_scroll(&mut self)
Re-engage auto-scroll (stick to bottom).
Trait Implementations§
Auto Trait Implementations§
impl Freeze for ChatViewport
impl RefUnwindSafe for ChatViewport
impl Send for ChatViewport
impl Sync for ChatViewport
impl Unpin for ChatViewport
impl UnsafeUnpin for ChatViewport
impl UnwindSafe for ChatViewport
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more