use ratatui::{
buffer::Buffer,
layout::{Alignment, Rect},
style::{Color, Style},
text::{Line, Span},
widgets::{Paragraph, Widget, Wrap},
};
#[derive(Debug, Clone, Default)]
pub struct WelcomeScreen;
impl WelcomeScreen {
#[must_use]
pub const fn new() -> Self {
Self
}
fn content_lines() -> Vec<Line<'static>> {
let style = Style::default().fg(Color::DarkGray);
vec![
Line::from(""),
Line::from(Span::styled("Welcome to tazuna", style)),
Line::from(""),
Line::from(Span::styled("Press Ctrl+s to open Workspace", style)),
Line::from(Span::styled("and create your first session", style)),
]
}
const fn content_height() -> u16 {
5 }
}
impl Widget for WelcomeScreen {
fn render(self, area: Rect, buf: &mut Buffer) {
if area.height == 0 || area.width == 0 {
return;
}
let content_height = Self::content_height();
let vertical_padding = area.height.saturating_sub(content_height) / 2;
let mut lines: Vec<Line<'static>> = Vec::new();
for _ in 0..vertical_padding {
lines.push(Line::from(""));
}
lines.extend(Self::content_lines());
let paragraph = Paragraph::new(lines)
.alignment(Alignment::Center)
.wrap(Wrap { trim: false });
paragraph.render(area, buf);
}
}
#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
use super::*;
use crate::tui::test_utils::{buffer_to_text, render_to_snapshot};
#[test]
fn new_creates_instance() {
let _screen = WelcomeScreen::new();
}
#[test]
fn renders_title() {
let screen = WelcomeScreen::new();
let area = Rect::new(0, 0, 60, 15);
let mut buf = Buffer::empty(area);
screen.render(area, &mut buf);
let output = buffer_to_text(&buf);
assert!(output.contains("Welcome to tazuna"));
}
#[test]
fn renders_ctrl_s_hint() {
let screen = WelcomeScreen::new();
let area = Rect::new(0, 0, 60, 15);
let mut buf = Buffer::empty(area);
screen.render(area, &mut buf);
let output = buffer_to_text(&buf);
assert!(output.contains("Ctrl+s"));
assert!(output.contains("create your first session"));
}
#[test]
fn handles_zero_height() {
let screen = WelcomeScreen::new();
let area = Rect::new(0, 0, 60, 0);
let mut buf = Buffer::empty(area);
screen.render(area, &mut buf);
}
#[test]
fn handles_zero_width() {
let screen = WelcomeScreen::new();
let area = Rect::new(0, 0, 0, 15);
let mut buf = Buffer::empty(area);
screen.render(area, &mut buf);
}
#[test]
fn handles_minimal_area() {
let screen = WelcomeScreen::new();
let area = Rect::new(0, 0, 2, 2);
let mut buf = Buffer::empty(area);
screen.render(area, &mut buf);
}
mod snapshots {
use super::*;
use insta::assert_snapshot;
#[test]
fn standard_size() {
let screen = WelcomeScreen::new();
assert_snapshot!(render_to_snapshot(screen, 60, 15));
}
#[test]
fn small_size() {
let screen = WelcomeScreen::new();
assert_snapshot!(render_to_snapshot(screen, 40, 8));
}
#[test]
fn wide_size() {
let screen = WelcomeScreen::new();
assert_snapshot!(render_to_snapshot(screen, 80, 10));
}
}
}