Monster commit: native version

This commit is contained in:
2026-01-30 15:03:49 +01:00
parent c2e6dfe88b
commit 44d1e9af24
35 changed files with 1491 additions and 366 deletions

View File

@@ -1,18 +1,15 @@
use cagire_ratatui::ListSelect;
use ratatui::layout::{Constraint, Layout, Rect};
use ratatui::style::{Color, Modifier, Style};
use ratatui::style::{Modifier, Style};
use ratatui::text::{Line, Span};
use ratatui::widgets::{Block, Borders, Paragraph, Row, Table};
use ratatui::Frame;
use crate::app::App;
use crate::state::{DeviceKind, EngineSection, SettingKind};
use crate::theme::{engine, meter};
use crate::widgets::{Orientation, Scope, Spectrum};
const HEADER_COLOR: Color = Color::Rgb(100, 160, 180);
const DIVIDER_COLOR: Color = Color::Rgb(60, 65, 70);
const SCROLL_INDICATOR_COLOR: Color = Color::Rgb(80, 85, 95);
pub fn render(frame: &mut Frame, app: &App, area: Rect) {
let [left_col, _, right_col] = Layout::horizontal([
Constraint::Percentage(55),
@@ -29,7 +26,7 @@ fn render_settings_section(frame: &mut Frame, app: &App, area: Rect) {
let block = Block::default()
.borders(Borders::ALL)
.title(" Engine ")
.border_style(Style::new().fg(Color::Magenta));
.border_style(Style::new().fg(engine::BORDER_MAGENTA));
let inner = block.inner(area);
frame.render_widget(block, area);
@@ -125,7 +122,7 @@ fn render_settings_section(frame: &mut Frame, app: &App, area: Rect) {
}
// Scroll indicators
let indicator_style = Style::new().fg(SCROLL_INDICATOR_COLOR);
let indicator_style = Style::new().fg(engine::SCROLL_INDICATOR);
let indicator_x = padded.x + padded.width.saturating_sub(1);
if scroll_offset > 0 {
@@ -158,14 +155,14 @@ fn render_scope(frame: &mut Frame, app: &App, area: Rect) {
let block = Block::default()
.borders(Borders::ALL)
.title(" Scope ")
.border_style(Style::new().fg(Color::Green));
.border_style(Style::new().fg(engine::BORDER_GREEN));
let inner = block.inner(area);
frame.render_widget(block, area);
let scope = Scope::new(&app.metrics.scope)
.orientation(Orientation::Horizontal)
.color(Color::Green);
.color(meter::LOW);
frame.render_widget(scope, inner);
}
@@ -173,7 +170,7 @@ fn render_spectrum(frame: &mut Frame, app: &App, area: Rect) {
let block = Block::default()
.borders(Borders::ALL)
.title(" Spectrum ")
.border_style(Style::new().fg(Color::Cyan));
.border_style(Style::new().fg(engine::BORDER_CYAN));
let inner = block.inner(area);
frame.render_widget(block, area);
@@ -210,16 +207,16 @@ fn render_section_header(frame: &mut Frame, title: &str, focused: bool, area: Re
Layout::vertical([Constraint::Length(1), Constraint::Length(1)]).areas(area);
let header_style = if focused {
Style::new().fg(Color::Yellow).add_modifier(Modifier::BOLD)
Style::new().fg(engine::HEADER_FOCUSED).add_modifier(Modifier::BOLD)
} else {
Style::new().fg(HEADER_COLOR).add_modifier(Modifier::BOLD)
Style::new().fg(engine::HEADER).add_modifier(Modifier::BOLD)
};
frame.render_widget(Paragraph::new(title).style(header_style), header_area);
let divider = "".repeat(area.width as usize);
frame.render_widget(
Paragraph::new(divider).style(Style::new().fg(DIVIDER_COLOR)),
Paragraph::new(divider).style(Style::new().fg(engine::DIVIDER)),
divider_area,
);
}
@@ -254,7 +251,7 @@ fn render_devices(frame: &mut Frame, app: &App, area: Rect) {
section_focused,
);
let sep_style = Style::new().fg(Color::Rgb(60, 65, 75));
let sep_style = Style::new().fg(engine::SEPARATOR);
let sep_lines: Vec<Line> = (0..separator.height)
.map(|_| Line::from(Span::styled("", sep_style)))
.collect();
@@ -289,11 +286,11 @@ fn render_device_column(
Layout::vertical([Constraint::Length(1), Constraint::Min(1)]).areas(area);
let label_style = if focused {
Style::new().fg(Color::Yellow).add_modifier(Modifier::BOLD)
Style::new().fg(engine::FOCUSED).add_modifier(Modifier::BOLD)
} else if section_focused {
Style::new().fg(Color::Rgb(150, 155, 165))
Style::new().fg(engine::LABEL_FOCUSED)
} else {
Style::new().fg(Color::Rgb(100, 105, 115))
Style::new().fg(engine::LABEL_DIM)
};
let arrow = if focused { "> " } else { " " };
@@ -318,10 +315,10 @@ fn render_settings(frame: &mut Frame, app: &App, area: Rect) {
render_section_header(frame, "SETTINGS", section_focused, header_area);
let highlight = Style::new().fg(Color::Yellow).add_modifier(Modifier::BOLD);
let normal = Style::new().fg(Color::White);
let label_style = Style::new().fg(Color::Rgb(120, 125, 135));
let value_style = Style::new().fg(Color::Rgb(180, 180, 190));
let highlight = Style::new().fg(engine::FOCUSED).add_modifier(Modifier::BOLD);
let normal = Style::new().fg(engine::NORMAL);
let label_style = Style::new().fg(engine::LABEL);
let value_style = Style::new().fg(engine::VALUE);
let channels_focused = section_focused && app.audio.setting_kind == SettingKind::Channels;
let buffer_focused = section_focused && app.audio.setting_kind == SettingKind::BufferSize;
@@ -438,8 +435,8 @@ fn render_samples(frame: &mut Frame, app: &App, area: Rect) {
let header_text = format!("SAMPLES {path_count} paths · {sample_count} indexed");
render_section_header(frame, &header_text, section_focused, header_area);
let dim = Style::new().fg(Color::Rgb(80, 85, 95));
let path_style = Style::new().fg(Color::Rgb(120, 125, 135));
let dim = Style::new().fg(engine::DIM);
let path_style = Style::new().fg(engine::PATH);
let mut lines: Vec<Line> = Vec::new();
if app.audio.config.sample_paths.is_empty() {
@@ -470,15 +467,15 @@ fn render_samples(frame: &mut Frame, app: &App, area: Rect) {
frame.render_widget(Paragraph::new(lines), content_area);
let hint_style = if section_focused {
Style::new().fg(Color::Rgb(180, 180, 100))
Style::new().fg(engine::HINT_ACTIVE)
} else {
Style::new().fg(Color::Rgb(60, 60, 70))
Style::new().fg(engine::HINT_INACTIVE)
};
let hint = Line::from(vec![
Span::styled("A", hint_style),
Span::styled(":add ", Style::new().fg(Color::Rgb(80, 85, 95))),
Span::styled(":add ", Style::new().fg(engine::DIM)),
Span::styled("D", hint_style),
Span::styled(":remove", Style::new().fg(Color::Rgb(80, 85, 95))),
Span::styled(":remove", Style::new().fg(engine::DIM)),
]);
frame.render_widget(Paragraph::new(hint), hint_area);
}