flake_edit/tui/
view.rs

1//! TUI rendering logic for the App.
2
3use ratatui::{
4    buffer::Buffer,
5    layout::Rect,
6    widgets::{Block, Borders, Paragraph, Widget, Wrap},
7};
8
9use super::app::{App, Screen};
10use super::components::confirm::Confirm;
11use super::components::input::Input;
12use super::components::list::List;
13use super::helpers::{color_diff_lines, layouts};
14use super::style::BORDER_STYLE;
15
16impl Widget for &App {
17    fn render(self, area: Rect, buf: &mut Buffer) {
18        match self.screen() {
19            Screen::Input(screen) => {
20                if self.show_diff() {
21                    let diff = self.pending_diff();
22                    let diff_lines = diff.lines().count();
23                    let (main_area, diff_area) =
24                        layouts::content_with_diff_preview(area, diff_lines);
25                    Input::new(
26                        &screen.state,
27                        &screen.prompt,
28                        self.context(),
29                        screen.label.as_deref(),
30                        self.show_diff(),
31                    )
32                    .render(main_area, buf);
33                    render_diff_preview(&diff, diff_area, buf);
34                } else {
35                    Input::new(
36                        &screen.state,
37                        &screen.prompt,
38                        self.context(),
39                        screen.label.as_deref(),
40                        self.show_diff(),
41                    )
42                    .render(area, buf);
43                }
44            }
45            Screen::List(screen) => {
46                if self.show_diff() {
47                    let diff = self.pending_diff();
48                    // Only show diff preview if there's actual content
49                    if !diff.is_empty() {
50                        let diff_lines = diff.lines().count();
51                        let (main_area, diff_area) =
52                            layouts::content_with_diff_preview(area, diff_lines);
53                        List::new(&screen.state, &screen.items, &screen.prompt, self.context())
54                            .render(main_area, buf);
55                        render_diff_preview(&diff, diff_area, buf);
56                    } else {
57                        List::new(&screen.state, &screen.items, &screen.prompt, self.context())
58                            .render(area, buf);
59                    }
60                } else {
61                    List::new(&screen.state, &screen.items, &screen.prompt, self.context())
62                        .render(area, buf);
63                }
64            }
65            Screen::Confirm(screen) => {
66                Confirm::new(&screen.diff, self.context()).render(area, buf);
67            }
68        }
69    }
70}
71
72/// Render a diff preview in the given area.
73fn render_diff_preview(diff: &str, area: Rect, buf: &mut Buffer) {
74    let content = Paragraph::new(color_diff_lines(diff))
75        .block(
76            Block::default()
77                .borders(Borders::TOP | Borders::BOTTOM)
78                .border_style(BORDER_STYLE),
79        )
80        .wrap(Wrap { trim: false });
81    content.render(area, buf);
82}