Feat: UI/UX fixes + removing clones from places
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use ratatui::layout::{Alignment, Constraint, Layout, Rect};
|
||||
use ratatui::style::{Color, Modifier, Style};
|
||||
use ratatui::text::{Line, Span};
|
||||
use ratatui::widgets::{Block, BorderType, Borders, Paragraph};
|
||||
use ratatui::widgets::{Block, Borders, Paragraph};
|
||||
use ratatui::Frame;
|
||||
|
||||
use crate::app::App;
|
||||
@@ -359,8 +359,7 @@ fn render_patterns(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, a
|
||||
|
||||
let cursor = app.patterns_nav.pattern_cursor;
|
||||
let available = inner.height as usize;
|
||||
// Cursor row takes 2 lines (main + detail); account for 1 extra
|
||||
let max_visible = available.saturating_sub(1).max(1);
|
||||
let max_visible = available.max(1);
|
||||
|
||||
let scroll_offset = if MAX_PATTERNS <= max_visible {
|
||||
0
|
||||
@@ -375,8 +374,6 @@ fn render_patterns(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, a
|
||||
let mut y = inner.y;
|
||||
for visible_idx in 0..visible_count {
|
||||
let idx = scroll_offset + visible_idx;
|
||||
let is_expanded = idx == cursor;
|
||||
let row_h = if is_expanded { 2u16 } else { 1u16 };
|
||||
if y >= inner.y + inner.height {
|
||||
break;
|
||||
}
|
||||
@@ -385,7 +382,7 @@ fn render_patterns(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, a
|
||||
x: inner.x,
|
||||
y,
|
||||
width: inner.width,
|
||||
height: row_h.min(inner.y + inner.height - y),
|
||||
height: 1u16.min(inner.y + inner.height - y),
|
||||
};
|
||||
|
||||
let is_cursor = is_focused && idx == app.patterns_nav.pattern_cursor;
|
||||
@@ -471,21 +468,9 @@ fn render_patterns(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, a
|
||||
let base_style = Style::new().bg(bg).fg(fg);
|
||||
let bold_style = base_style.add_modifier(Modifier::BOLD);
|
||||
|
||||
let content_area = if is_expanded {
|
||||
let border_color = if is_focused { theme.selection.cursor } else { theme.ui.unfocused };
|
||||
let block = Block::default()
|
||||
.borders(Borders::LEFT | Borders::RIGHT)
|
||||
.border_type(BorderType::QuadrantOutside)
|
||||
.border_style(Style::new().fg(border_color).bg(bg))
|
||||
.style(Style::new().bg(bg));
|
||||
let content = block.inner(row_area);
|
||||
frame.render_widget(block, row_area);
|
||||
content
|
||||
} else {
|
||||
let bg_block = Block::default().style(Style::new().bg(bg));
|
||||
frame.render_widget(bg_block, row_area);
|
||||
row_area
|
||||
};
|
||||
let bg_block = Block::default().style(Style::new().bg(bg));
|
||||
frame.render_widget(bg_block, row_area);
|
||||
let content_area = row_area;
|
||||
|
||||
let text_area = Rect {
|
||||
x: content_area.x,
|
||||
@@ -521,16 +506,38 @@ fn render_patterns(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, a
|
||||
String::new()
|
||||
};
|
||||
let props_indicator = if has_staged_props { "~" } else { "" };
|
||||
let right_info = if content_count > 0 {
|
||||
format!("{props_indicator}{content_count}/{length}{speed_str}")
|
||||
let quant_sync = if is_selected {
|
||||
format!(
|
||||
"{}:{} ",
|
||||
pattern.quantization.short_label(),
|
||||
pattern.sync_mode.short_label()
|
||||
)
|
||||
} else {
|
||||
format!("{props_indicator} {length}{speed_str}")
|
||||
String::new()
|
||||
};
|
||||
let right_info = if content_count > 0 {
|
||||
format!("{quant_sync}{props_indicator}{content_count}/{length}{speed_str}")
|
||||
} else {
|
||||
format!("{quant_sync}{props_indicator} {length}{speed_str}")
|
||||
};
|
||||
let left_width: usize = spans.iter().map(|s| s.content.chars().count()).sum();
|
||||
let right_width = right_info.chars().count();
|
||||
let padding = (text_area.width as usize).saturating_sub(left_width + right_width + 1);
|
||||
let gap = (text_area.width as usize).saturating_sub(left_width + right_width + 1);
|
||||
|
||||
spans.push(Span::styled(" ".repeat(padding), dim_style));
|
||||
if let Some(desc) = pattern.description.as_deref().filter(|d| !d.is_empty() && gap > 4) {
|
||||
let budget = gap - 2;
|
||||
let char_count = desc.chars().count();
|
||||
if char_count <= budget {
|
||||
spans.push(Span::styled(format!(" {desc}"), dim_style));
|
||||
spans.push(Span::styled(" ".repeat(gap - char_count - 1), dim_style));
|
||||
} else {
|
||||
let truncated: String = desc.chars().take(budget - 1).collect();
|
||||
spans.push(Span::styled(format!(" {truncated}\u{2026}"), dim_style));
|
||||
spans.push(Span::styled(" ", dim_style));
|
||||
}
|
||||
} else {
|
||||
spans.push(Span::styled(" ".repeat(gap), dim_style));
|
||||
}
|
||||
spans.push(Span::styled(right_info, dim_style));
|
||||
|
||||
let spans = if is_playing && !is_cursor && !is_in_range {
|
||||
@@ -543,52 +550,6 @@ fn render_patterns(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, a
|
||||
|
||||
frame.render_widget(Paragraph::new(Line::from(spans)), text_area);
|
||||
|
||||
if is_expanded && content_area.height >= 2 {
|
||||
let detail_area = Rect {
|
||||
x: content_area.x,
|
||||
y: content_area.y + 1,
|
||||
width: content_area.width,
|
||||
height: 1,
|
||||
};
|
||||
|
||||
let right_label = format!(
|
||||
"{} · {}",
|
||||
pattern.quantization.label(),
|
||||
pattern.sync_mode.label()
|
||||
);
|
||||
let w = detail_area.width as usize;
|
||||
let label = if let Some(desc) = &pattern.description {
|
||||
let right_len = right_label.chars().count();
|
||||
let max_desc = w.saturating_sub(right_len + 1);
|
||||
let truncated: String = desc.chars().take(max_desc).collect();
|
||||
let pad = w.saturating_sub(truncated.chars().count() + right_len);
|
||||
format!("{truncated}{}{right_label}", " ".repeat(pad))
|
||||
} else {
|
||||
format!("{right_label:>w$}")
|
||||
};
|
||||
let padded_label = label;
|
||||
|
||||
let filled_width = if is_playing {
|
||||
let ratio = snapshot.get_smooth_progress(bank, idx, length, speed.multiplier()).unwrap_or(0.0);
|
||||
(ratio * detail_area.width as f64).min(detail_area.width as f64) as usize
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let dim_fg = theme.ui.text_muted;
|
||||
let progress_bg = theme.list.playing_bg;
|
||||
let byte_offset = padded_label
|
||||
.char_indices()
|
||||
.nth(filled_width)
|
||||
.map_or(padded_label.len(), |(i, _)| i);
|
||||
let (left, right) = padded_label.split_at(byte_offset);
|
||||
let detail_spans = vec![
|
||||
Span::styled(left.to_string(), Style::new().bg(progress_bg).fg(dim_fg)),
|
||||
Span::styled(right.to_string(), Style::new().bg(theme.ui.bg).fg(dim_fg)),
|
||||
];
|
||||
frame.render_widget(Paragraph::new(Line::from(detail_spans)), detail_area);
|
||||
}
|
||||
|
||||
y += row_area.height;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user