feat: refine system specs screen layout
Build And Push Container / build-and-push (push) Successful in 56s

This commit is contained in:
2026-06-30 23:35:45 +02:00
parent c5f0249dbf
commit 382e82601a
6 changed files with 307 additions and 19 deletions
+185 -2
View File
@@ -14,6 +14,13 @@ use crate::types::SystemView;
pub(crate) const DISPLAY_WIDTH: u32 = 960;
pub(crate) const DISPLAY_HEIGHT: u32 = 376;
pub(crate) fn normalize_specs_mode(mode: &str) -> &'static str {
match mode {
"meters" => "meters",
_ => "cards",
}
}
pub(crate) fn collect_system_view() -> SystemView {
fn mount_usage(disks: &Disks, mount_point: &str) -> (String, String, String) {
disks
@@ -140,7 +147,14 @@ fn format_bytes(bytes: u64) -> String {
}
}
pub(crate) fn render_system_panel() -> RgbImage {
pub(crate) fn render_system_panel(mode: &str) -> RgbImage {
match normalize_specs_mode(mode) {
"meters" => render_system_panel_meters(),
_ => render_system_panel_cards(),
}
}
fn render_system_panel_cards() -> RgbImage {
let system = collect_system_view();
let mut canvas = RgbImage::from_pixel(DISPLAY_WIDTH, DISPLAY_HEIGHT, Rgb([10, 14, 18]));
let host_name = System::host_name().unwrap_or_else(|| "Unraid".into());
@@ -229,7 +243,10 @@ pub(crate) fn render_system_panel() -> RgbImage {
236,
"System",
system.uptime.clone(),
format!("{} CPU / {} proc", system.cpu_count, system.process_count),
format!(
"{} cores | {} procs",
system.cpu_count, system.process_count
),
Rgb([216, 253, 114]),
),
];
@@ -241,6 +258,109 @@ pub(crate) fn render_system_panel() -> RgbImage {
canvas
}
fn render_system_panel_meters() -> RgbImage {
let system = collect_system_view();
let mut canvas = RgbImage::from_pixel(DISPLAY_WIDTH, DISPLAY_HEIGHT, Rgb([9, 13, 17]));
let host_name = System::host_name().unwrap_or_else(|| "Unraid".into());
let timestamp = Local::now().format("%d.%m.%Y %H:%M:%S").to_string();
draw_filled_rect_mut(
&mut canvas,
Rect::at(0, 0).of_size(DISPLAY_WIDTH, 72),
Rgb([15, 23, 30]),
);
draw_text_line(
&mut canvas,
Rgb([216, 253, 114]),
26,
18,
32.0,
"AOOSTAR System Monitor",
);
draw_text_line(
&mut canvas,
Rgb([146, 163, 181]),
28,
48,
18.0,
&format!("{host_name} | {timestamp}"),
);
draw_meter_row(
&mut canvas,
26,
102,
"CPU",
&format!("{}%", system.cpu_usage_percent),
parse_metric_percent(&system.cpu_usage_percent),
Rgb([110, 231, 183]),
&format!(
"Load {} / {} / {} {} cores {} procs",
system.load_avg_one,
system.load_avg_five,
system.load_avg_fifteen,
system.cpu_count,
system.process_count
),
);
draw_meter_row(
&mut canvas,
26,
170,
"RAM",
&format!("{}%", system.mem_usage_percent),
parse_metric_percent(&system.mem_usage_percent),
Rgb([120, 189, 247]),
&format!("{} / {}", system.mem_used, system.mem_total),
);
draw_meter_row(
&mut canvas,
26,
238,
"GPU",
system.temperature_gpu.as_deref().unwrap_or("-"),
normalize_temperature_bar(system.temperature_gpu.as_deref()),
Rgb([241, 132, 121]),
&format!(
"Temp meter CPU {} Cache {}% User {}%",
system.temperature_cpu.as_deref().unwrap_or("-"),
system.cache_usage_percent,
system.user_usage_percent
),
);
draw_filled_rect_mut(
&mut canvas,
Rect::at(26, 308).of_size(908, 42),
Rgb([12, 18, 24]),
);
draw_hollow_rect_mut(
&mut canvas,
Rect::at(26, 308).of_size(908, 42),
Rgb([31, 44, 58]),
);
draw_text_line(
&mut canvas,
Rgb([146, 163, 181]),
42,
321,
18.0,
&format!(
"Swap {}% {} / {} Cache {} / {} User {} / {} Uptime {}",
system.swap_usage_percent,
system.swap_used,
system.swap_total,
system.cache_used,
system.cache_total,
system.user_used,
system.user_total,
system.uptime
),
);
canvas
}
pub(crate) fn overlay_system_specs(canvas: &mut RgbImage) {
let system = collect_system_view();
let host_name = System::host_name().unwrap_or_else(|| "Unraid".into());
@@ -309,6 +429,69 @@ pub(crate) fn overlay_system_specs(canvas: &mut RgbImage) {
);
}
fn draw_meter_row(
canvas: &mut RgbImage,
x: i32,
y: i32,
label: &str,
value: &str,
percent: f32,
accent: Rgb<u8>,
meta: &str,
) {
draw_text_line(canvas, accent, x, y, 19.0, label);
draw_text_line(canvas, Rgb([237, 242, 247]), x + 112, y, 19.0, value);
draw_meter_bar(canvas, x, y + 28, 840, 20, percent, accent);
draw_text_line(canvas, Rgb([146, 163, 181]), x, y + 56, 17.0, meta);
}
fn draw_meter_bar(
canvas: &mut RgbImage,
x: i32,
y: i32,
width: u32,
height: u32,
percent: f32,
accent: Rgb<u8>,
) {
draw_filled_rect_mut(
canvas,
Rect::at(x, y).of_size(width, height),
Rgb([19, 27, 35]),
);
draw_hollow_rect_mut(
canvas,
Rect::at(x, y).of_size(width, height),
Rgb([36, 50, 67]),
);
let fill_width =
((width.saturating_sub(2)) as f32 * (percent.clamp(0.0, 100.0) / 100.0)).round() as u32;
if fill_width > 0 {
draw_filled_rect_mut(
canvas,
Rect::at(x + 1, y + 1).of_size(fill_width, height.saturating_sub(2)),
accent,
);
}
}
fn parse_metric_percent(value: &str) -> f32 {
value.parse::<f32>().unwrap_or(0.0)
}
fn normalize_temperature_bar(value: Option<&str>) -> f32 {
let Some(raw) = value else {
return 0.0;
};
let numeric = raw
.replace(" °C", "")
.replace('C', "")
.trim()
.parse::<f32>()
.unwrap_or(0.0);
(numeric / 100.0 * 100.0).clamp(0.0, 100.0)
}
fn draw_metric_card(
canvas: &mut RgbImage,
x: i32,