gitkraft_tui/widgets/
header.rs1use ratatui::layout::Rect;
2use ratatui::style::{Modifier, Style};
3use ratatui::text::{Line, Span};
4use ratatui::widgets::{Block, Borders, Paragraph};
5use ratatui::Frame;
6
7use crate::app::{App, AppScreen};
8
9pub fn render(app: &mut App, frame: &mut Frame, area: Rect) {
12 if app.screen != AppScreen::Main {
13 return;
14 }
15
16 let theme = app.theme();
17
18 let block = Block::default()
19 .borders(Borders::ALL)
20 .border_style(Style::default().fg(theme.border_inactive))
21 .style(Style::default().bg(theme.border_inactive));
22
23 let tab = app.tab();
24
25 let repo_name = tab
26 .repo_path
27 .as_ref()
28 .and_then(|p| p.file_name())
29 .map(|n| n.to_string_lossy().to_string())
30 .unwrap_or_else(|| "unknown".to_string());
31
32 let branch_name = tab
33 .repo_info
34 .as_ref()
35 .and_then(|info| info.head_branch.clone())
36 .unwrap_or_else(|| "detached".to_string());
37
38 let state = tab
39 .repo_info
40 .as_ref()
41 .map(|info| format!("{}", info.state))
42 .unwrap_or_else(|| "?".to_string());
43
44 let mut spans: Vec<Span> = Vec::new();
45
46 if app.tabs.len() > 1 {
48 for (i, t) in app.tabs.iter().enumerate() {
49 let name = t.display_name();
50 let style = if i == app.active_tab_index {
51 Style::default()
52 .fg(theme.accent)
53 .add_modifier(Modifier::BOLD)
54 } else {
55 Style::default().fg(theme.text_muted)
56 };
57 spans.push(Span::styled(format!(" {} ", name), style));
58 if i < app.tabs.len() - 1 {
59 spans.push(Span::styled("|", Style::default().fg(theme.text_muted)));
60 }
61 }
62 spans.push(Span::styled(
64 " [/]",
65 Style::default()
66 .fg(theme.warning)
67 .add_modifier(Modifier::BOLD),
68 ));
69 spans.push(Span::styled(
70 " switch tab ",
71 Style::default().fg(theme.text_primary),
72 ));
73 spans.push(Span::styled(
74 "│ ",
75 Style::default().fg(theme.text_secondary),
76 ));
77 }
78
79 if app.tabs.len() <= 1 {
82 spans.push(Span::styled(
83 format!(" {} ", repo_name),
84 Style::default()
85 .fg(theme.text_primary)
86 .add_modifier(Modifier::BOLD),
87 ));
88 spans.push(Span::styled("│", Style::default().fg(theme.text_secondary)));
89 }
90
91 spans.extend([
92 Span::styled(
93 format!(" {} ", branch_name),
94 Style::default()
95 .fg(theme.success)
96 .add_modifier(Modifier::BOLD),
97 ),
98 Span::styled("│", Style::default().fg(theme.text_secondary)),
99 Span::styled(format!(" {} ", state), Style::default().fg(theme.accent)),
100 Span::styled("│", Style::default().fg(theme.text_secondary)),
101 Span::styled(
102 " [←→]",
103 Style::default()
104 .fg(theme.warning)
105 .add_modifier(Modifier::BOLD),
106 ),
107 Span::styled(" pane ", Style::default().fg(theme.text_primary)),
108 Span::styled(
109 "[r]",
110 Style::default()
111 .fg(theme.warning)
112 .add_modifier(Modifier::BOLD),
113 ),
114 Span::styled(" refresh ", Style::default().fg(theme.text_primary)),
115 Span::styled(
116 "[f]",
117 Style::default()
118 .fg(theme.warning)
119 .add_modifier(Modifier::BOLD),
120 ),
121 Span::styled(" fetch ", Style::default().fg(theme.text_primary)),
122 Span::styled(
123 "[t]",
124 Style::default()
125 .fg(theme.warning)
126 .add_modifier(Modifier::BOLD),
127 ),
128 Span::styled(" theme ", Style::default().fg(theme.text_primary)),
129 Span::styled(
130 "[E]",
131 Style::default()
132 .fg(theme.warning)
133 .add_modifier(Modifier::BOLD),
134 ),
135 Span::styled(" editor ", Style::default().fg(theme.text_primary)),
136 Span::styled(
137 "[O]",
138 Style::default()
139 .fg(theme.warning)
140 .add_modifier(Modifier::BOLD),
141 ),
142 Span::styled(" options ", Style::default().fg(theme.text_primary)),
143 Span::styled(
144 "[o]",
145 Style::default()
146 .fg(theme.warning)
147 .add_modifier(Modifier::BOLD),
148 ),
149 Span::styled(" open ", Style::default().fg(theme.text_primary)),
150 Span::styled(
151 "[W]",
152 Style::default()
153 .fg(theme.warning)
154 .add_modifier(Modifier::BOLD),
155 ),
156 Span::styled(" close ", Style::default().fg(theme.text_primary)),
157 Span::styled(
158 "[q]",
159 Style::default()
160 .fg(theme.warning)
161 .add_modifier(Modifier::BOLD),
162 ),
163 Span::styled(" quit", Style::default().fg(theme.text_primary)),
164 ]);
165
166 let line = Line::from(spans);
167 let paragraph = Paragraph::new(line).block(block);
168
169 frame.render_widget(paragraph, area);
170}