Skip to content

Commit e8c7c47

Browse files
committed
Fixing tiny crashes and refactoring
1 parent 99ab9e3 commit e8c7c47

16 files changed

Lines changed: 89 additions & 148 deletions

src/app/app.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -270,22 +270,25 @@ impl App {
270270
}
271271

272272
pub fn draw(&mut self, frame: &mut Frame) {
273+
274+
let minimal_horizontal_space = if (self.is_branches || self.is_tags || self.is_stashes) && (self.is_inspector || self.is_status) { 100 } else { 50 };
275+
let is_zen = frame.area().width < minimal_horizontal_space;
273276

274277
// Compute the layout
275278
self.layout(frame);
276-
277-
let is_splash = self.viewport == Viewport::Splash;
279+
280+
let is_splash = self.viewport == Viewport::Splash || is_zen;
278281

279282
frame.render_widget( Block::default()
280283
.borders(if is_splash { Borders::NONE } else { Borders::ALL })
281284
.border_style(Style::default().fg(self.theme.COLOR_BORDER))
282285
.border_type(ratatui::widgets::BorderType::Rounded), self.layout.app);
283-
284-
// Main layout
285-
if !is_splash {
286-
self.draw_title(frame);
287-
}
288286

287+
if is_zen {
288+
self.draw_splash(frame);
289+
return;
290+
}
291+
289292
// Viewport
290293
match self.viewport {
291294
Viewport::Graph => {
@@ -304,6 +307,11 @@ impl App {
304307
self.draw_settings(frame);
305308
}
306309
}
310+
311+
// Main layout
312+
if !is_splash {
313+
self.draw_title(frame);
314+
}
307315

308316
// Panes
309317
match self.viewport {

src/app/app_default.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ impl Default for App {
124124
layout: Layout::default(),
125125

126126
// Focus
127-
is_shas: true,
127+
is_shas: false,
128128
is_minimal: false,
129129
is_branches: false,
130130
is_tags: false,

src/app/app_draw_modal_delete_tag.rs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,9 @@ use ratatui::{
2121
};
2222
use crate::helpers::symbols::SYM_TAG;
2323
#[rustfmt::skip]
24-
use crate::{
25-
app::app::{
24+
use crate::app::app::{
2625
App
27-
},
28-
git::{
29-
queries::{
30-
commits::{
31-
get_current_branch
32-
}
33-
}
34-
}
35-
};
26+
};
3627

3728
impl App {
3829

src/app/app_draw_settings.rs

Lines changed: 39 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,10 @@ impl App {
5353
pub fn draw_settings(&mut self, frame: &mut Frame) {
5454

5555
// Padding
56-
let padding = ratatui::widgets::Padding {
57-
left: 1,
58-
right: 1,
59-
top: 0,
60-
bottom: 0,
61-
};
56+
let padding = ratatui::widgets::Padding { left: 1, right: 1, top: 0, bottom: 0};
6257

6358
// Calculate maximum available width for text
64-
let available_width = self.layout.graph.width as usize - 1;
59+
let available_width = self.layout.graph.width.saturating_sub(1) as usize;
6560
let max_text_width = available_width.saturating_sub(2);
6661

6762
// Credentials
@@ -78,36 +73,41 @@ impl App {
7873
lines.push(Line::from(Span::styled("commit heatmap (last year)", Style::default().fg(self.theme.COLOR_TEXT))).centered());
7974
lines.push(Line::default());
8075

81-
let heatmap_width = self.heatmap[0].len();
76+
// Each heat cell is "X " - two columns
77+
let cell_width = 2;
78+
79+
// Borders
80+
let border_width = 8;
81+
82+
// Available width
83+
let usable_width = available_width.saturating_sub(border_width);
84+
85+
// How many weeks fit horizontally
86+
let max_weeks_fit = (usable_width / cell_width).max(1);
87+
88+
let total_weeks = self.heatmap[0].len();
89+
let visible_weeks = max_weeks_fit.min(total_weeks);
90+
91+
// Right align and keep most recent weeks
92+
let week_start = total_weeks.saturating_sub(visible_weeks);
93+
94+
// Width used by the heatmap body excluding borders
95+
let heatmap_width = visible_weeks * cell_width;
8296

8397
// Top border
84-
lines.push(Line::from(
85-
Span::styled(
86-
format!("╭{}╮", "─".repeat(heatmap_width + 2)),
87-
Style::default().fg(self.theme.COLOR_GREY_800),
88-
)
89-
).centered());
98+
lines.push(Line::from(Span::styled(format!("╭{}╮", "─".repeat(heatmap_width + 2)),Style::default().fg(self.theme.COLOR_GREY_800))).centered());
9099

91100
// Body
92101
for day in 0..7 {
93102
let mut spans = Vec::new();
94103
spans.push(Span::styled("│ ", Style::default().fg(self.theme.COLOR_GREY_800)));
95-
spans.extend(
96-
self.heatmap[day]
97-
.iter()
98-
.map(|&count| heat_cell(count, &self.theme))
99-
);
104+
spans.extend(self.heatmap[day][week_start..].iter().map(|&count| heat_cell(count, &self.theme)));
100105
spans.push(Span::styled(" │", Style::default().fg(self.theme.COLOR_GREY_800)));
101106
lines.push(Line::from(spans).centered());
102107
}
103108

104109
// Bottom border
105-
lines.push(Line::from(
106-
Span::styled(
107-
format!("╰{}╯", "─".repeat(heatmap_width + 2)),
108-
Style::default().fg(self.theme.COLOR_GREY_800),
109-
)
110-
).centered());
110+
lines.push(Line::from(Span::styled(format!("╰{}╯", "─".repeat(heatmap_width + 2)), Style::default().fg(self.theme.COLOR_GREY_800))).centered());
111111
lines.push(Line::default());
112112
lines.push(Line::default());
113113

@@ -171,31 +171,23 @@ impl App {
171171

172172
// Snap to nearest selectable line if needed
173173
if !self.settings_selections.contains(&self.settings_selected) {
174-
174+
175175
// Find nearest selectable line above or below
176176
let mut nearest = None;
177177

178178
// Moving down
179179
if self.last_input_direction == Some(Direction::Down) {
180-
nearest = self.settings_selections.iter()
181-
.copied()
182-
.find(|&i| i > self.settings_selected);
180+
nearest = self.settings_selections.iter().copied().find(|&i| i > self.settings_selected);
183181
}
184182

185183
// Moving up
186184
if nearest.is_none() && self.last_input_direction == Some(Direction::Up) {
187-
nearest = self.settings_selections.iter()
188-
.rev()
189-
.copied()
190-
.find(|&i| i < self.settings_selected);
185+
nearest = self.settings_selections.iter().rev().copied().find(|&i| i < self.settings_selected);
191186
}
192187

193188
// Fallback to nearest by distance if neither direction flag is set
194189
if nearest.is_none() {
195-
nearest = self.settings_selections
196-
.iter()
197-
.min_by_key(|&&i| i.abs_diff(self.settings_selected))
198-
.copied();
190+
nearest = self.settings_selections.iter().min_by_key(|&&i| i.abs_diff(self.settings_selected)).copied();
199191
}
200192

201193
if let Some(target) = nearest {
@@ -214,24 +206,28 @@ impl App {
214206
.map(|(i, line)| {
215207
let absolute_idx = start + i;
216208
let mut item = line.clone();
209+
210+
// Ensure there is at least one span
211+
if item.spans.is_empty() {
212+
item.spans.push(Span::raw(" "));
213+
}
214+
215+
// Highlight the selected line if focused
217216
if absolute_idx == self.settings_selected && self.focus == Focus::Viewport {
218-
let spans: Vec<Span> = item.clone().spans.iter().map(|span| {
217+
let spans: Vec<Span> = item.spans.iter().map(|span| {
219218
let mut style = span.style;
220219
style = style.bg(self.theme.COLOR_GREY_800);
221220
Span::styled(span.content.clone(), style)
222221
}).collect();
223222
item = Line::from(spans).centered();
224223
}
224+
225225
ListItem::from(item)
226226
})
227227
.collect();
228228

229229
// Setup the list
230-
let list = List::new(list_items)
231-
.block(
232-
Block::default()
233-
.padding(padding)
234-
);
230+
let list = List::new(list_items).block(Block::default().padding(padding));
235231

236232
// Render the list
237233
frame.render_widget(list, self.layout.graph);

src/app/app_draw_splash.rs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,10 @@ impl App {
2424
pub fn draw_splash(&mut self, frame: &mut Frame) {
2525

2626
// Padding
27-
let padding = ratatui::widgets::Padding {
28-
left: 1,
29-
right: 1,
30-
top: 0,
31-
bottom: 0,
32-
};
27+
let padding = ratatui::widgets::Padding { left: 1, right: 1, top: 0, bottom: 0 };
3328

3429
// Calculate maximum available width for text
35-
let available_width = self.layout.graph.width as usize - 1;
30+
let available_width = self.layout.graph.width.saturating_sub(1) as usize;
3631
let _max_text_width = available_width.saturating_sub(2);
3732

3833
// Get vertical dimensions
@@ -100,11 +95,7 @@ impl App {
10095
]).centered()));
10196

10297
// Setup the list
103-
let list = List::new(list_items)
104-
.block(
105-
Block::default()
106-
.padding(padding)
107-
);
98+
let list = List::new(list_items).block(Block::default().padding(padding));
10899

109100
// Render the list
110101
frame.render_widget(list, self.layout.app);

src/app/app_draw_stashes.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl App {
5151

5252
// Text
5353
let truncated = truncate_with_ellipsis(message.as_str(), max_text_width - 1);
54-
let color = if let Some(color) = self.stashes.colors.get(&stash_alias) { *color } else { self.theme.COLOR_TEXT };
54+
let color = if let Some(color) = self.stashes.colors.get(stash_alias) { *color } else { self.theme.COLOR_TEXT };
5555

5656
// Render a stash
5757
lines.push(Line::from(Span::styled(format!("{SYM_COMMIT_STASH} {truncated}"), Style::default().fg(color))));
@@ -93,7 +93,7 @@ impl App {
9393

9494
// Setup the list
9595
if self.is_branches || self.is_tags {
96-
let top_border = Paragraph::new("─".repeat(self.layout.stashes.width as usize - 1 as usize))
96+
let top_border = Paragraph::new("─".repeat(self.layout.stashes.width as usize - 1_usize))
9797
.style(Style::default().fg(self.theme.COLOR_BORDER));
9898
frame.render_widget(top_border, Rect {
9999
x: self.layout.stashes.x + 1,

src/app/app_draw_status.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ impl App {
4747
};
4848

4949
// Calculate maximum available width for text
50-
let available_width = self.layout.status_top.width as usize - 3;
50+
let available_width = self.layout.status_top.width.saturating_sub(3) as usize;
5151
let max_text_width = available_width.saturating_sub(2);
5252

5353
// Flags
@@ -175,7 +175,7 @@ impl App {
175175
{
176176
// Get vertical dimensions
177177
let total_lines = lines_status_top.len();
178-
let visible_height = self.layout.status_top.height as usize - 2;
178+
let visible_height = self.layout.status_top.height.saturating_sub(2) as usize;
179179

180180
// Clamp selection
181181
if total_lines == 0 {

src/app/app_draw_tags.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ impl App {
8989

9090
// Setup the list
9191
if self.is_branches || self.is_tags {
92-
let top_border = Paragraph::new("─".repeat(self.layout.tags.width as usize - 1 as usize))
92+
let top_border = Paragraph::new("─".repeat(self.layout.tags.width as usize - 1_usize))
9393
.style(Style::default().fg(self.theme.COLOR_BORDER));
9494
frame.render_widget(top_border, Rect {
9595
x: self.layout.tags.x + 1,

src/app/app_input.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,12 +1105,11 @@ impl App {
11051105
}
11061106

11071107
pub fn on_grep(&mut self) {
1108-
if self.viewport == Viewport::Graph {
1109-
if self.focus == Focus::Viewport {
1108+
if self.viewport == Viewport::Graph
1109+
&& self.focus == Focus::Viewport {
11101110
self.focus = Focus::ModalGrep;
11111111
self.modal_editor.mode = EditorMode::Insert;
11121112
}
1113-
}
11141113
}
11151114

11161115
pub fn on_fetch(&mut self) {
@@ -1359,13 +1358,12 @@ impl App {
13591358
}
13601359

13611360
pub fn on_cherrypick(&mut self) {
1362-
if self.viewport == Viewport::Graph && self.focus == Focus::Viewport {
1363-
if self.graph_selected != 0 {
1361+
if self.viewport == Viewport::Graph && self.focus == Focus::Viewport
1362+
&& self.graph_selected != 0 {
13641363
let oid = self.oids.get_oid_by_idx(if self.graph_selected == 0 { 1 } else { self.graph_selected });
13651364
cherry_pick_commit(&self.repo, *oid, Some("message"), true).unwrap();
13661365
self.reload();
13671366
}
1368-
}
13691367
}
13701368

13711369
pub fn on_go_back(&mut self) {

src/core/branches.rs

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use crate::{
3131
}
3232
};
3333

34+
#[derive(Default)]
3435
pub struct Branches {
3536
pub local: HashMap<u32, Vec<String>>,
3637
pub remote: HashMap<u32, Vec<String>>,
@@ -41,20 +42,6 @@ pub struct Branches {
4142
pub visible: HashMap<u32, Vec<String>>,
4243
}
4344

44-
impl Default for Branches {
45-
46-
fn default() -> Self {
47-
Self {
48-
local: Default::default(),
49-
remote: Default::default(),
50-
all: Default::default(),
51-
colors: Default::default(),
52-
sorted: Default::default(),
53-
indices: Default::default(),
54-
visible: Default::default(),
55-
}
56-
}
57-
}
5845

5946
impl Branches {
6047

0 commit comments

Comments
 (0)