Fix border wrapping issue
This commit is contained in:
parent
9ef6143dbd
commit
89d1c02690
2 changed files with 30 additions and 27 deletions
10
src/app.rs
10
src/app.rs
|
|
@ -86,8 +86,8 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.log_view_grouping {
|
match self.log_view_grouping {
|
||||||
LogViewGrouping::ByProject => line.starts_with("\t\t"),
|
LogViewGrouping::ByProject => line.starts_with(" "),
|
||||||
LogViewGrouping::ByDate => line.starts_with('\t') && !line.starts_with("\t\t"),
|
LogViewGrouping::ByDate => line.starts_with(" ") && !line.starts_with(" "),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -637,7 +637,7 @@ impl App {
|
||||||
if let Some(prev) = prev_stop {
|
if let Some(prev) = prev_stop {
|
||||||
let gap = start_local.signed_duration_since(prev);
|
let gap = start_local.signed_duration_since(prev);
|
||||||
if gap.num_minutes() >= 5 {
|
if gap.num_minutes() >= 5 {
|
||||||
lines.push("\t ---".to_string());
|
lines.push(" ---".to_string());
|
||||||
// Note: don't add to frame_indices - separator is not an entry
|
// Note: don't add to frame_indices - separator is not an entry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -663,7 +663,7 @@ impl App {
|
||||||
};
|
};
|
||||||
|
|
||||||
let line_text = format!(
|
let line_text = format!(
|
||||||
"\t{} to {} {:>9} {}",
|
" {} to {} {:>9} {}",
|
||||||
start_time, stop_time, duration_str, display_text
|
start_time, stop_time, duration_str, display_text
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -763,7 +763,7 @@ impl App {
|
||||||
};
|
};
|
||||||
|
|
||||||
lines.push(format!(
|
lines.push(format!(
|
||||||
"\t\t{} to {} {:>9}{}",
|
" {} to {} {:>9}{}",
|
||||||
start_time, stop_time, duration_str, tags_str
|
start_time, stop_time, duration_str, tags_str
|
||||||
));
|
));
|
||||||
frame_indices.push(*idx);
|
frame_indices.push(*idx);
|
||||||
|
|
|
||||||
47
src/ui.rs
47
src/ui.rs
|
|
@ -2,7 +2,7 @@ use ratatui::{
|
||||||
layout::{Alignment, Constraint, Direction, Layout, Rect},
|
layout::{Alignment, Constraint, Direction, Layout, Rect},
|
||||||
style::{Color, Modifier, Style},
|
style::{Color, Modifier, Style},
|
||||||
text::{Line, Span},
|
text::{Line, Span},
|
||||||
widgets::{Block, Borders, Clear, List, ListItem, Paragraph, Row, Table, TableState},
|
widgets::{Block, Borders, Clear, Paragraph, Row, Table, TableState},
|
||||||
Frame,
|
Frame,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -698,8 +698,8 @@ fn render_log_view(frame: &mut Frame, app: &App) {
|
||||||
.borders(Borders::ALL)
|
.borders(Borders::ALL)
|
||||||
.style(Style::default().fg(ACTIVE_COLOR));
|
.style(Style::default().fg(ACTIVE_COLOR));
|
||||||
|
|
||||||
// Build list items with selection highlighting based on selection level
|
// Build text lines with selection highlighting based on selection level
|
||||||
let items: Vec<ListItem> = {
|
let text_lines: Vec<Line> = {
|
||||||
// Pre-calculate which line indices should be highlighted
|
// Pre-calculate which line indices should be highlighted
|
||||||
let mut selected_date = String::new();
|
let mut selected_date = String::new();
|
||||||
let mut selected_project = String::new();
|
let mut selected_project = String::new();
|
||||||
|
|
@ -715,17 +715,17 @@ fn render_log_view(frame: &mut Frame, app: &App) {
|
||||||
let is_by_project = matches!(app.log_view_grouping, LogViewGrouping::ByProject);
|
let is_by_project = matches!(app.log_view_grouping, LogViewGrouping::ByProject);
|
||||||
|
|
||||||
for (_idx, line) in app.log_view_content.iter().enumerate() {
|
for (_idx, line) in app.log_view_content.iter().enumerate() {
|
||||||
if !line.starts_with('\t') && !line.is_empty() && !line.starts_with(" ") {
|
if !line.starts_with(" ") && !line.is_empty() && !line.starts_with(" ") {
|
||||||
current_date = line.clone();
|
current_date = line.clone();
|
||||||
} else if line.starts_with(" ") && !line.starts_with("\t") {
|
} else if line.starts_with(" ") && !line.starts_with(" ") {
|
||||||
current_project = line.clone();
|
current_project = line.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only count actual entries (not all tab-indented lines)
|
// Only count actual entries (not all tab-indented lines)
|
||||||
let is_entry = if is_by_project {
|
let is_entry = if is_by_project {
|
||||||
line.starts_with("\t\t") // Double tab for ByProject
|
line.starts_with(" ") // 8 spaces for ByProject
|
||||||
} else {
|
} else {
|
||||||
line.starts_with('\t') && !line.starts_with("\t\t") // Single tab for ByDate
|
line.starts_with(" ") && !line.starts_with(" ") // 4 spaces for ByDate
|
||||||
};
|
};
|
||||||
|
|
||||||
if is_entry {
|
if is_entry {
|
||||||
|
|
@ -746,9 +746,9 @@ fn render_log_view(frame: &mut Frame, app: &App) {
|
||||||
for (idx, line) in app.log_view_content.iter().enumerate() {
|
for (idx, line) in app.log_view_content.iter().enumerate() {
|
||||||
// Use is_entry_line logic which excludes separator lines
|
// Use is_entry_line logic which excludes separator lines
|
||||||
let is_entry = if is_by_project {
|
let is_entry = if is_by_project {
|
||||||
line.starts_with("\t\t")
|
line.starts_with(" ")
|
||||||
} else {
|
} else {
|
||||||
line.starts_with('\t') && !line.starts_with("\t\t") && line.trim() != "---"
|
line.starts_with(" ") && !line.starts_with(" ") && line.trim() != "---"
|
||||||
};
|
};
|
||||||
|
|
||||||
if is_entry {
|
if is_entry {
|
||||||
|
|
@ -767,19 +767,19 @@ fn render_log_view(frame: &mut Frame, app: &App) {
|
||||||
current_date = String::new();
|
current_date = String::new();
|
||||||
|
|
||||||
for (idx, line) in app.log_view_content.iter().enumerate() {
|
for (idx, line) in app.log_view_content.iter().enumerate() {
|
||||||
if !line.starts_with('\t') && !line.is_empty() && !line.starts_with(" ") {
|
if !line.starts_with(" ") && !line.is_empty() && !line.starts_with(" ") {
|
||||||
current_date = line.clone();
|
current_date = line.clone();
|
||||||
if in_target_project {
|
if in_target_project {
|
||||||
break; // End of project group
|
break; // End of project group
|
||||||
}
|
}
|
||||||
} else if line.starts_with(" ") && !line.starts_with("\t") {
|
} else if line.starts_with(" ") && !line.starts_with(" ") {
|
||||||
if current_date == selected_date && line == &selected_project {
|
if current_date == selected_date && line == &selected_project {
|
||||||
selected_line_start = idx;
|
selected_line_start = idx;
|
||||||
in_target_project = true;
|
in_target_project = true;
|
||||||
} else if in_target_project {
|
} else if in_target_project {
|
||||||
break; // Different project
|
break; // Different project
|
||||||
}
|
}
|
||||||
} else if in_target_project && line.starts_with('\t') {
|
} else if in_target_project && line.starts_with(" ") {
|
||||||
selected_line_end = idx;
|
selected_line_end = idx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -789,7 +789,7 @@ fn render_log_view(frame: &mut Frame, app: &App) {
|
||||||
let mut in_target_day = false;
|
let mut in_target_day = false;
|
||||||
|
|
||||||
for (idx, line) in app.log_view_content.iter().enumerate() {
|
for (idx, line) in app.log_view_content.iter().enumerate() {
|
||||||
if !line.starts_with('\t') && !line.is_empty() && !line.starts_with(" ") {
|
if !line.starts_with(" ") && !line.is_empty() && !line.starts_with(" ") {
|
||||||
if line == &selected_date {
|
if line == &selected_date {
|
||||||
selected_line_start = idx;
|
selected_line_start = idx;
|
||||||
in_target_day = true;
|
in_target_day = true;
|
||||||
|
|
@ -820,17 +820,17 @@ fn render_log_view(frame: &mut Frame, app: &App) {
|
||||||
|
|
||||||
for (line_idx, line) in app.log_view_content.iter().enumerate() {
|
for (line_idx, line) in app.log_view_content.iter().enumerate() {
|
||||||
// New day header
|
// New day header
|
||||||
if !line.starts_with('\t') && !line.is_empty() && !line.starts_with(" ") {
|
if !line.starts_with(" ") && !line.is_empty() && !line.starts_with(" ") {
|
||||||
current_day_start_entry = app.log_view_content[..line_idx]
|
current_day_start_entry = app.log_view_content[..line_idx]
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|l| l.starts_with('\t') && !l.is_empty() && l.trim() != "---")
|
.filter(|l| l.starts_with(" ") && !l.is_empty() && l.trim() != "---")
|
||||||
.count();
|
.count();
|
||||||
in_day = true;
|
in_day = true;
|
||||||
} else if in_day && line.starts_with('\t') && !line.is_empty() && line.trim() != "---" {
|
} else if in_day && line.starts_with(" ") && !line.is_empty() && line.trim() != "---" {
|
||||||
// This is an entry line
|
// This is an entry line
|
||||||
let entry_idx = app.log_view_content[..=line_idx]
|
let entry_idx = app.log_view_content[..=line_idx]
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|l| l.starts_with('\t') && !l.is_empty() && l.trim() != "---")
|
.filter(|l| l.starts_with(" ") && !l.is_empty() && l.trim() != "---")
|
||||||
.count()
|
.count()
|
||||||
.saturating_sub(1);
|
.saturating_sub(1);
|
||||||
|
|
||||||
|
|
@ -868,12 +868,12 @@ fn render_log_view(frame: &mut Frame, app: &App) {
|
||||||
let is_separator = line.trim() == "---";
|
let is_separator = line.trim() == "---";
|
||||||
|
|
||||||
// Check if this line corresponds to an overlapping entry
|
// Check if this line corresponds to an overlapping entry
|
||||||
let has_overlap = if !is_separator && is_by_date && line.starts_with('\t') && !line.is_empty() {
|
let has_overlap = if !is_separator && is_by_date && line.starts_with(" ") && !line.is_empty() {
|
||||||
// Count which entry this is (0-based in display order)
|
// Count which entry this is (0-based in display order)
|
||||||
// Only count actual entry lines, not separator lines
|
// Only count actual entry lines, not separator lines
|
||||||
let entry_idx = app.log_view_content[..=idx]
|
let entry_idx = app.log_view_content[..=idx]
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|l| l.starts_with('\t') && !l.is_empty() && l.trim() != "---")
|
.filter(|l| l.starts_with(" ") && !l.is_empty() && l.trim() != "---")
|
||||||
.count()
|
.count()
|
||||||
.saturating_sub(1);
|
.saturating_sub(1);
|
||||||
|
|
||||||
|
|
@ -894,13 +894,16 @@ fn render_log_view(frame: &mut Frame, app: &App) {
|
||||||
Style::default().fg(Color::White)
|
Style::default().fg(Color::White)
|
||||||
};
|
};
|
||||||
|
|
||||||
ListItem::new(Line::from(vec![Span::styled(line.clone(), style)]))
|
Line::from(vec![Span::styled(line.clone(), style)])
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
};
|
};
|
||||||
|
|
||||||
let list = List::new(items).block(block);
|
let paragraph = Paragraph::new(text_lines)
|
||||||
frame.render_widget(list, chunks[0]);
|
.block(block)
|
||||||
|
.wrap(ratatui::widgets::Wrap { trim: false });
|
||||||
|
|
||||||
|
frame.render_widget(paragraph, chunks[0]);
|
||||||
|
|
||||||
// Render help hint at bottom if enabled
|
// Render help hint at bottom if enabled
|
||||||
if app.config.show_help_hint {
|
if app.config.show_help_hint {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue