Files
Val Lorentz 1199dd7613 Cache the result of rendering backlog items
It's so much faster when getting lots of updates, especially with the
'Added client for' log storm at startup.
2023-11-04 22:16:33 +01:00

83 lines
2.2 KiB
Rust

/*
* Copyright (C) 2023 Valentin Lorentz
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use std::collections::VecDeque;
use std::sync::Arc;
use std::sync::RwLock;
use matrix_sdk::async_trait;
use ratatui::text::Text;
use tokio::sync::mpsc::UnboundedReceiver;
use tracing_error::ErrorLayer;
use tracing_subscriber::prelude::*;
use super::{Buffer, BufferItem};
use crate::widgets::Prerender;
/// Maximum number of log lines to be stored in memory
const MAX_MEM_LOG_LINES: usize = 100;
pub struct LogBuffer {
lines: VecDeque<(String, Prerender)>,
receiver: UnboundedReceiver<String>,
}
impl LogBuffer {
pub fn new(receiver: UnboundedReceiver<String>) -> Self {
LogBuffer {
lines: VecDeque::new(),
receiver,
}
}
}
#[async_trait]
impl Buffer for LogBuffer {
fn short_name(&self) -> String {
"ratatrix".to_owned()
}
async fn poll_updates(&mut self) {
let line = self
.receiver
.recv()
.await
.expect("LogBuffer's channel was closed");
if self.lines.len() >= MAX_MEM_LOG_LINES {
self.lines.pop_front();
}
self.lines.push_back((line, Prerender::new()));
}
fn content<'a>(&'a self) -> Box<dyn Iterator<Item = BufferItem<'a>> + 'a> {
use ansi_to_tui::IntoText;
let (slice1, slice2) = self.lines.as_slices();
Box::new(
slice1
.into_iter()
.chain(slice2.into_iter())
.rev()
.map(|(line, prerender)| BufferItem {
text: line.clone().into_text().unwrap_or_else(|e| {
tracing::error!("Could not convert line from ANSI codes to ratatui: {}", e);
Text::raw(line)
}),
prerender,
}),
)
}
}