gitkraft_tui/features/
skeleton.rs1use ratatui::layout::{Constraint, Direction, Layout, Rect};
12use ratatui::style::Style;
13use ratatui::widgets::{Block, Borders};
14use ratatui::Frame;
15use tui_skeleton::{AnimationMode, SkeletonBlock, SkeletonList, SkeletonTable};
16
17use crate::app::App;
18
19pub fn render(app: &mut App, frame: &mut Frame) {
23 let theme = app.theme();
24
25 let elapsed_ms = app.tick_count.saturating_mul(33);
27
28 let base = theme.border_inactive; let hi = theme.sel_bg; let area = frame.area();
33
34 let outer = Layout::default()
36 .direction(Direction::Vertical)
37 .constraints([
38 Constraint::Length(3),
39 Constraint::Percentage(60),
40 Constraint::Percentage(40),
41 Constraint::Length(1),
42 ])
43 .split(area);
44
45 crate::widgets::header::render(app, frame, outer[0]);
47
48 let main_cols = Layout::default()
50 .direction(Direction::Horizontal)
51 .constraints([
52 Constraint::Length(24),
53 Constraint::Percentage(40),
54 Constraint::Min(20),
55 ])
56 .split(outer[1]);
57
58 let sidebar = Layout::default()
60 .direction(Direction::Vertical)
61 .constraints([
62 Constraint::Min(6),
63 Constraint::Length(5),
64 Constraint::Length(5),
65 ])
66 .split(main_cols[0]);
67
68 let inner = pane(
69 frame,
70 sidebar[0],
71 " Branches ",
72 theme.border_inactive,
73 theme.bg,
74 );
75 frame.render_widget(
76 SkeletonList::new(elapsed_ms)
77 .mode(AnimationMode::Sweep)
78 .items(10)
79 .base(base)
80 .highlight(hi),
81 inner,
82 );
83
84 let inner = pane(
85 frame,
86 sidebar[1],
87 " Stashes ",
88 theme.border_inactive,
89 theme.bg,
90 );
91 frame.render_widget(
92 SkeletonList::new(elapsed_ms)
93 .mode(AnimationMode::Sweep)
94 .items(3)
95 .base(base)
96 .highlight(hi),
97 inner,
98 );
99
100 let inner = pane(
101 frame,
102 sidebar[2],
103 " Remotes ",
104 theme.border_inactive,
105 theme.bg,
106 );
107 frame.render_widget(
108 SkeletonList::new(elapsed_ms)
109 .mode(AnimationMode::Sweep)
110 .items(2)
111 .base(base)
112 .highlight(hi),
113 inner,
114 );
115
116 let inner = pane(
118 frame,
119 main_cols[1],
120 " Commit Log ",
121 theme.border_inactive,
122 theme.bg,
123 );
124 frame.render_widget(
125 SkeletonTable::new(elapsed_ms)
126 .mode(AnimationMode::Sweep)
127 .rows(30)
128 .columns(&[
129 Constraint::Length(2), Constraint::Length(8), Constraint::Fill(1), Constraint::Length(14), Constraint::Length(9), ])
135 .zebra(true)
136 .base(base)
137 .highlight(hi),
138 inner,
139 );
140
141 let inner = pane(
143 frame,
144 main_cols[2],
145 " Diff ",
146 theme.border_inactive,
147 theme.bg,
148 );
149 frame.render_widget(
150 SkeletonBlock::new(elapsed_ms)
151 .mode(AnimationMode::Sweep)
152 .base(base)
153 .highlight(hi),
154 inner,
155 );
156
157 let staging_cols = Layout::default()
159 .direction(Direction::Horizontal)
160 .constraints([Constraint::Ratio(1, 2), Constraint::Ratio(1, 2)])
161 .split(outer[2]);
162
163 let inner = pane(
164 frame,
165 staging_cols[0],
166 " Unstaged ",
167 theme.border_inactive,
168 theme.bg,
169 );
170 frame.render_widget(
171 SkeletonList::new(elapsed_ms)
172 .mode(AnimationMode::Sweep)
173 .items(5)
174 .base(base)
175 .highlight(hi),
176 inner,
177 );
178
179 let inner = pane(
180 frame,
181 staging_cols[1],
182 " Staged ",
183 theme.border_inactive,
184 theme.bg,
185 );
186 frame.render_widget(
187 SkeletonList::new(elapsed_ms)
188 .mode(AnimationMode::Sweep)
189 .items(5)
190 .base(base)
191 .highlight(hi),
192 inner,
193 );
194
195 crate::widgets::status_bar::render(app, frame, outer[3]);
197}
198
199fn pane(
201 frame: &mut Frame,
202 area: Rect,
203 title: &str,
204 border_color: ratatui::style::Color,
205 bg_color: ratatui::style::Color,
206) -> Rect {
207 let block = Block::default()
208 .title(title)
209 .borders(Borders::ALL)
210 .border_style(Style::default().fg(border_color))
211 .style(Style::default().bg(bg_color));
212 let inner = block.inner(area);
213 frame.render_widget(block, area);
214 inner
215}