Files
soulseek-rs-modded/soulseek-rs/src/ui/styles.rs
T
michel e72c8a5c07 style: crank clippy to pedantic+nursery and fix all lints
Enable the full clippy all + pedantic + nursery groups as workspace warnings,
with a small documented allow-list for the pedantic/nursery lints this project
intentionally does not follow (rustdoc-style requirements, deliberate numeric
casts in the protocol/UI layers, and a few noisy nursery lints). Also enable
the rust unused_lifetimes and unsafe_op_in_unsafe_fn lints.

Fixed every resulting warning (527 -> 0) mechanically per clippy's suggestions:
inline format args, const fns, item ordering, let-else, redundant clones,
map_or, cast_lossless, Eq derives, associated-fn conversions for methods that
never used self, and removing unnecessary Result wrappers whose call sites could
never propagate an error. No runtime behavior changed; cargo fmt applied.

cargo clippy --workspace --all-targets: 0 warnings. All tests pass.
2026-07-19 00:09:17 +02:00

175 lines
4.4 KiB
Rust

// Reusable styles and colors for consistent UI appearance
#![allow(dead_code)]
use ratatui::style::{Color, Modifier, Style};
use ratatui::symbols;
use ratatui::text::{Line, Span};
use ratatui::widgets::BorderType;
// Color scheme - using Light variants to match openapi-tui
pub const COLOR_PRIMARY: Color = Color::LightCyan;
pub const COLOR_SUCCESS: Color = Color::LightGreen;
pub const COLOR_WARNING: Color = Color::LightYellow;
pub const COLOR_ERROR: Color = Color::LightRed;
pub const COLOR_INACTIVE: Color = Color::Gray;
pub const COLOR_INFO: Color = Color::LightBlue;
pub const COLOR_ACCENT: Color = Color::LightMagenta;
// Border colors
pub const COLOR_FOCUSED_BORDER: Color = Color::LightGreen;
// Highlight symbol - using arrow like openapi-tui
pub const HIGHLIGHT_SYMBOL: &str = symbols::scrollbar::HORIZONTAL.end;
// Reusable styles
pub fn header_style() -> Style {
Style::default().add_modifier(Modifier::BOLD)
}
pub fn highlight_style() -> Style {
Style::default().add_modifier(Modifier::BOLD)
}
pub fn success_style() -> Style {
Style::default().fg(COLOR_SUCCESS)
}
pub fn warning_style() -> Style {
Style::default().fg(COLOR_WARNING)
}
pub fn error_style() -> Style {
Style::default().fg(COLOR_ERROR)
}
pub fn inactive_style() -> Style {
Style::default().fg(COLOR_INACTIVE)
}
pub fn primary_style() -> Style {
Style::default().fg(COLOR_PRIMARY)
}
pub fn info_style() -> Style {
Style::default().fg(COLOR_INFO)
}
pub fn accent_style() -> Style {
Style::default().fg(COLOR_ACCENT)
}
pub fn dimmed_style() -> Style {
Style::default().add_modifier(Modifier::DIM)
}
// Focus-based border styling (matching openapi-tui)
pub fn focused_border_style() -> Style {
Style::default().fg(COLOR_FOCUSED_BORDER)
}
pub fn unfocused_border_style() -> Style {
Style::default()
}
pub const fn focused_border_type() -> BorderType {
BorderType::Rounded
}
pub const fn unfocused_border_type() -> BorderType {
BorderType::Rounded
}
// Helper function to get border style based on focus state
pub fn border_style(focused: bool) -> Style {
if focused {
focused_border_style()
} else {
unfocused_border_style()
}
}
pub const fn border_type(focused: bool) -> BorderType {
if focused {
focused_border_type()
} else {
unfocused_border_type()
}
}
// Shortcut formatting helper (matching openapi-tui format)
pub fn format_shortcuts(shortcuts: &[(&str, &str)]) -> String {
shortcuts
.iter()
.map(|(key, action)| format!("[{key} {HIGHLIGHT_SYMBOL} {action}]"))
.collect::<Vec<_>>()
.join(" ")
}
// Styled shortcut formatting helper (returns Line with colored Spans)
pub fn format_shortcuts_styled(shortcuts: &[(&str, &str)]) -> Line<'static> {
let mut spans = Vec::new();
for (i, (key, action)) in shortcuts.iter().enumerate() {
if i > 0 {
spans.push(Span::raw(" "));
}
spans.push(Span::styled("[", dimmed_style()));
spans.push(Span::styled(
key.to_string(),
Style::default()
.fg(COLOR_PRIMARY)
.add_modifier(Modifier::BOLD),
));
spans.push(Span::styled(
format!(" {HIGHLIGHT_SYMBOL} "),
dimmed_style(),
));
spans.push(Span::raw(action.to_string()));
spans.push(Span::styled("]", dimmed_style()));
}
Line::from(spans)
}
// Status colors for downloads
pub fn status_color(status: &str) -> Color {
match status {
"queued" => COLOR_INACTIVE,
"in_progress" => COLOR_WARNING,
"paused" => COLOR_INFO,
"completed" => COLOR_PRIMARY,
"failed" | "timed_out" => COLOR_ERROR,
_ => Color::default(),
}
}
// Format progress bar with styled filled/unfilled portions
pub fn format_progress_bar(
progress: f64,
width: usize,
percentage: u8,
) -> Line<'static> {
let filled = (progress * width as f64) as usize;
let empty = width.saturating_sub(filled);
let filled_part = "█".repeat(filled);
let empty_part = "░".repeat(empty);
let spans = vec![
Span::raw("["),
Span::styled(filled_part, primary_style()),
Span::styled(empty_part, dimmed_style()),
Span::raw("]"),
Span::raw(" "),
Span::styled(
format!("{percentage}%"),
primary_style()
.add_modifier(Modifier::BOLD)
.fg(Color::default()),
),
];
Line::from(spans)
}