diff --git a/src/buffers/log.rs b/src/buffers/log.rs index 7a9fbfd..ed82d96 100644 --- a/src/buffers/log.rs +++ b/src/buffers/log.rs @@ -24,7 +24,7 @@ use tokio::sync::mpsc::UnboundedReceiver; use tracing_error::ErrorLayer; use tracing_subscriber::prelude::*; -use super::Buffer; +use super::{Buffer, BufferItem}; /// Maximum number of log lines to be stored in memory const MAX_MEM_LOG_LINES: usize = 100; @@ -61,19 +61,21 @@ impl Buffer for LogBuffer { self.lines.push_back(line); } - fn content(&self) -> Vec { + fn content<'a>(&'a self) -> Box> + 'a> { use ansi_to_tui::IntoText; let (slice1, slice2) = self.lines.as_slices(); - slice1 - .into_iter() - .chain(slice2.into_iter()) - .cloned() - .map(|line| { - line.into_text().unwrap_or_else(|e| { - tracing::error!("Could not convert line from ANSI codes to ratatui: {}", e); - Text::raw(line) - }) - }) - .collect() + Box::new( + slice1 + .into_iter() + .chain(slice2.into_iter()) + .rev() + .cloned() + .map(|line| BufferItem { + text: line.into_text().unwrap_or_else(|e| { + tracing::error!("Could not convert line from ANSI codes to ratatui: {}", e); + Text::raw(line) + }), + }), + ) } } diff --git a/src/buffers/mod.rs b/src/buffers/mod.rs index 5f74768..dd58db8 100644 --- a/src/buffers/mod.rs +++ b/src/buffers/mod.rs @@ -18,12 +18,17 @@ use futures::stream::FuturesUnordered; use futures::StreamExt; use matrix_sdk::async_trait; use nonempty::NonEmpty; +use ratatui::text::Text; mod log; pub use log::LogBuffer; mod room; pub use room::RoomBuffer; +pub struct BufferItem<'a> { + pub text: Text<'a>, +} + #[async_trait] pub trait Buffer: Send + Sync { /// A short human-readable name for the room, eg. to show in compact buflist @@ -34,7 +39,7 @@ pub trait Buffer: Send + Sync { } /// Returns if there are any updates to apply. async fn poll_updates(&mut self); - fn content(&self) -> Vec; // TODO: make this lazy, only the last few are used + fn content<'a>(&'a self) -> Box> + 'a>; /// Called when the user is being showned the oldest items this buffer returned. /// /// This should return immediately, not waiting for anything to be loaded. diff --git a/src/buffers/room.rs b/src/buffers/room.rs index 17c94d8..b54a312 100644 --- a/src/buffers/room.rs +++ b/src/buffers/room.rs @@ -32,7 +32,7 @@ use matrix_sdk_ui::timeline::{ use ratatui::text::Text; use smallvec::SmallVec; -use super::Buffer; +use super::{Buffer, BufferItem}; pub struct SingleClientRoomBuffer { room_id: OwnedRoomId, @@ -304,16 +304,20 @@ impl Buffer for RoomBuffer { .await; } - fn content(&self) -> Vec { + fn content<'a>(&'a self) -> Box> + 'a> { // TODO: merge buffers, etc. - self - .buffers - .first() - .unwrap_or_else(|| panic!("No sub-buffer for {}", self.room_id)) - .items - .iter() - .map(|line| Text::raw(line)) - .collect() + Box::new( + self + .buffers + .first() + .unwrap_or_else(|| panic!("No sub-buffer for {}", self.room_id)) + .items + .iter() + .rev() + .map(|line| BufferItem { + text: Text::raw(line), + }), + ) } fn request_back_pagination(&self, num: u16) { diff --git a/src/components/backlog.rs b/src/components/backlog.rs index c12906f..6ca73f1 100644 --- a/src/components/backlog.rs +++ b/src/components/backlog.rs @@ -64,8 +64,6 @@ impl Component for Backlog { let active_buffer = buffers.active_buffer(); let mut items = active_buffer.content(); - items.reverse(); - let mut items = items.into_iter(); let mut scroll = self.scroll; // Skip widgets at the bottom (if scrolled up), and render the first visible one @@ -73,7 +71,7 @@ impl Component for Backlog { let Some(item) = items.next() else { break; }; - let widget = BottomAlignedParagraph::new(item); + let widget = BottomAlignedParagraph::new(item.text); let expected_height = widget.height(text_area.width); if scroll.saturating_sub(expected_height) > text_area.height.into() { @@ -95,7 +93,7 @@ impl Component for Backlog { // Render other widgets for item in items { - let widget = BottomAlignedParagraph::new(item); + let widget = BottomAlignedParagraph::new(item.text); let height = widget.render_overlap(text_area, frame.buffer_mut()); assert!(area.height >= height, "{:?} {}", area, height); text_area.height = text_area.height.saturating_sub(height); // Remove lines at the bottom used by this paragraph