use crate::rendering::{Cell, Charset, CharsetMode, Theme, VideoBuffer};
use std::time::{Duration, Instant};
pub struct Toast {
pub message: String,
pub created_at: Instant,
pub duration: Duration,
}
impl Toast {
pub fn new(message: impl Into<String>) -> Self {
Self {
message: message.into(),
created_at: Instant::now(),
duration: Duration::from_secs(5),
}
}
pub fn is_expired(&self) -> bool {
self.created_at.elapsed() >= self.duration
}
pub fn render(&self, buffer: &mut VideoBuffer, charset: &Charset, theme: &Theme) {
let (cols, rows) = buffer.dimensions();
let message_len = self.message.chars().count() as u16;
let padding = 4u16; let width = message_len + padding;
let x = (cols.saturating_sub(width)) / 2;
let y = rows.saturating_sub(5);
let fg = theme.prompt_info_fg;
let bg = theme.prompt_info_bg;
let (top_left, top_right, bottom_left, bottom_right, horizontal, vertical) = match charset
.mode
{
CharsetMode::Unicode | CharsetMode::UnicodeSingleLine => ('╔', '╗', '╚', '╝', '═', '║'),
CharsetMode::Ascii => ('+', '+', '+', '+', '-', '|'),
};
buffer.set(x, y, Cell::new_unchecked(top_left, fg, bg));
for dx in 1..width - 1 {
buffer.set(x + dx, y, Cell::new_unchecked(horizontal, fg, bg));
}
buffer.set(x + width - 1, y, Cell::new_unchecked(top_right, fg, bg));
let msg_y = y + 1;
buffer.set(x, msg_y, Cell::new_unchecked(vertical, fg, bg));
buffer.set(x + 1, msg_y, Cell::new_unchecked(' ', fg, bg));
for (i, ch) in self.message.chars().enumerate() {
buffer.set(x + 2 + i as u16, msg_y, Cell::new_unchecked(ch, fg, bg));
}
buffer.set(x + 2 + message_len, msg_y, Cell::new_unchecked(' ', fg, bg));
buffer.set(x + width - 1, msg_y, Cell::new_unchecked(vertical, fg, bg));
let bottom_y = y + 2;
buffer.set(x, bottom_y, Cell::new_unchecked(bottom_left, fg, bg));
for dx in 1..width - 1 {
buffer.set(x + dx, bottom_y, Cell::new_unchecked(horizontal, fg, bg));
}
buffer.set(
x + width - 1,
bottom_y,
Cell::new_unchecked(bottom_right, fg, bg),
);
}
}