Skip to main content

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.prompt, self.context())
54                            .render(main_area, buf);
55                        render_diff_preview(&diff, diff_area, buf);
56                    } else {
57                        List::new(&screen.state, &screen.prompt, self.context()).render(area, buf);
58                    }
59                } else {
60                    List::new(&screen.state, &screen.prompt, self.context()).render(area, buf);
61                }
62            }
63            Screen::Confirm(screen) => {
64                Confirm::new(&screen.diff, self.context()).render(area, buf);
65            }
66        }
67    }
68}
69
70/// Render a diff preview in the given area.
71fn render_diff_preview(diff: &str, area: Rect, buf: &mut Buffer) {
72    let content = Paragraph::new(color_diff_lines(diff))
73        .block(
74            Block::default()
75                .borders(Borders::TOP | Borders::BOTTOM)
76                .border_style(BORDER_STYLE),
77        )
78        .wrap(Wrap { trim: false });
79    content.render(area, buf);
80}