From c650d63299489e7dfbfa64da6e2eb6c3b7e1d022 Mon Sep 17 00:00:00 2001 From: magges Date: Tue, 30 Jun 2026 23:54:04 +0200 Subject: [PATCH] refactor: simplify specs display layout --- README.md | 5 +- crates/aster-webui/src/system.rs | 191 ++++++++++--------------------- crates/aster-webui/src/ui.rs | 14 ++- unraid-aoostar-rs-template.xml | 46 -------- 4 files changed, 74 insertions(+), 182 deletions(-) delete mode 100644 unraid-aoostar-rs-template.xml diff --git a/README.md b/README.md index 4472407..ce4be4c 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,8 @@ Current scope: - manage rotation order and switch interval - enable or disable custom panels without the vendor web UI - drive the AOOSTAR LCD directly through the native `aoostar-rs` serial implementation +- show native system specs in either a card view or an htop-style meter view +- toggle a built-in `ricardo.gif` animation directly from the Web UI Start it from the workspace root: @@ -40,11 +42,12 @@ cargo run -p aster-webui -- --config-dir /config --bind 0.0.0.0:8080 Important: - the current web UI writes compatible `Monitor3.json` and `/config/img/*` assets -- animated GIF uploads currently use the first frame only - the native display loop runs automatically and uses the default AOOSTAR USB UART unless `--device`, `--usb`, `--simulate`, or `--disable-display` is specified - the native path currently targets custom image panels; built-in vendor sensor themes are not yet reimplemented in the web UI +- the Web UI currently exposes animated playback through the built-in `Ricardo` toggle rather than + arbitrary uploaded GIF rotation ## Native Container Variant diff --git a/crates/aster-webui/src/system.rs b/crates/aster-webui/src/system.rs index dc0b0f1..c8e89db 100644 --- a/crates/aster-webui/src/system.rs +++ b/crates/aster-webui/src/system.rs @@ -157,96 +157,74 @@ pub(crate) fn render_system_panel(mode: &str) -> RgbImage { 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()); - 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, 84), - Rgb([18, 27, 36]), + Rect::at(0, 0).of_size(DISPLAY_WIDTH, 64), + Rgb([14, 20, 28]), ); draw_filled_rect_mut( &mut canvas, - Rect::at(0, 84).of_size(DISPLAY_WIDTH, DISPLAY_HEIGHT - 84), + Rect::at(0, 64).of_size(DISPLAY_WIDTH, DISPLAY_HEIGHT - 64), Rgb([8, 11, 15]), ); draw_text_line( &mut canvas, Rgb([216, 253, 114]), - 28, - 20, - 36.0, - "AOOSTAR Native Specs", - ); - draw_text_line( - &mut canvas, - Rgb([146, 163, 181]), - 30, - 58, - 20.0, - &format!("{host_name} | {timestamp}"), + 24, + 16, + 30.0, + "SYSTEM SPECS", ); let cards = [ ( - 24, - 106, - "CPU", + 20, + 84, + "CPU USAGE", format!("{} %", system.cpu_usage_percent), - format!( - "Load {} / {} / {}", - system.load_avg_one, system.load_avg_five, system.load_avg_fifteen - ), + format!("Load {}", system.load_avg_one), Rgb([124, 231, 191]), ), ( - 332, - 106, - "Memory", + 334, + 84, + "RAM USAGE", format!("{} %", system.mem_usage_percent), format!("{} / {}", system.mem_used, system.mem_total), Rgb([125, 196, 255]), ), ( - 640, - 106, - "Storage", - format!( - "C {}% U {}%", - system.cache_usage_percent, system.user_usage_percent - ), - format!( - "/mnt/cache {} / {} | /mnt/user {} / {}", - system.cache_used, system.cache_total, system.user_used, system.user_total - ), + 648, + 84, + "GPU TEMP", + system.temperature_gpu.as_deref().unwrap_or("-").to_string(), + format!("CPU {}", system.temperature_cpu.as_deref().unwrap_or("-")), Rgb([255, 199, 115]), ), ( - 24, - 236, - "Swap", - format!("{} %", system.swap_usage_percent), - format!("{} / {}", system.swap_used, system.swap_total), + 20, + 226, + "CACHE", + format!("{} %", system.cache_usage_percent), + format!("{} / {}", system.cache_used, system.cache_total), Rgb([194, 167, 255]), ), ( - 332, - 236, - "Temperatures", - format!("CPU {}", system.temperature_cpu.as_deref().unwrap_or("-")), - format!("GPU {}", system.temperature_gpu.as_deref().unwrap_or("-")), + 334, + 226, + "USER", + format!("{} %", system.user_usage_percent), + format!("{} / {}", system.user_used, system.user_total), Rgb([255, 127, 115]), ), ( - 640, - 236, - "System", - system.uptime.clone(), - format!( - "{} cores | {} procs", - system.cpu_count, system.process_count - ), + 648, + 226, + "SWAP", + format!("{} %", system.swap_usage_percent), + format!("{} / {}", system.swap_used, system.swap_total), Rgb([216, 253, 114]), ), ]; @@ -261,53 +239,36 @@ fn render_system_panel_cards() -> RgbImage { 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]), + Rect::at(0, 0).of_size(DISPLAY_WIDTH, 56), + Rgb([14, 20, 28]), ); 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}"), + 24, + 14, + 28.0, + "HTOP STYLE", ); draw_meter_row( &mut canvas, - 26, - 102, - "CPU", + 24, + 84, + "CPU USAGE", &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 - ), + &format!("Load {} {} cores", system.load_avg_one, system.cpu_count), ); draw_meter_row( &mut canvas, - 26, - 170, - "RAM", + 24, + 178, + "RAM USAGE", &format!("{}%", system.mem_usage_percent), parse_metric_percent(&system.mem_usage_percent), Rgb([120, 189, 247]), @@ -315,46 +276,16 @@ fn render_system_panel_meters() -> RgbImage { ); draw_meter_row( &mut canvas, - 26, - 238, - "GPU", + 24, + 272, + "GPU TEMP", 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 {}%", + "CPU {} {} procs", 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 + system.process_count ), ); @@ -439,10 +370,10 @@ fn draw_meter_row( accent: Rgb, 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); + draw_text_line(canvas, accent, x, y, 21.0, label); + draw_text_line(canvas, Rgb([237, 242, 247]), x + 248, y, 21.0, value); + draw_meter_bar(canvas, x, y + 32, 900, 24, percent, accent); + draw_text_line(canvas, Rgb([146, 163, 181]), x, y + 64, 18.0, meta); } fn draw_meter_bar( @@ -457,12 +388,12 @@ fn draw_meter_bar( draw_filled_rect_mut( canvas, Rect::at(x, y).of_size(width, height), - Rgb([19, 27, 35]), + Rgb([15, 21, 28]), ); draw_hollow_rect_mut( canvas, Rect::at(x, y).of_size(width, height), - Rgb([36, 50, 67]), + Rgb([52, 68, 86]), ); let fill_width = ((width.saturating_sub(2)) as f32 * (percent.clamp(0.0, 100.0) / 100.0)).round() as u32; @@ -505,9 +436,9 @@ fn draw_metric_card( draw_hollow_rect_mut(canvas, Rect::at(x, y).of_size(284, 112), Rgb([36, 50, 67])); draw_filled_rect_mut(canvas, Rect::at(x + 1, y + 1).of_size(6, 110), accent); - draw_text_line(canvas, accent, x + 20, y + 16, 19.0, title); - draw_text_line(canvas, Rgb([237, 242, 247]), x + 20, y + 44, 28.0, value); - draw_text_line(canvas, Rgb([146, 163, 181]), x + 20, y + 82, 18.0, meta); + draw_text_line(canvas, accent, x + 20, y + 16, 18.0, title); + draw_text_line(canvas, Rgb([237, 242, 247]), x + 20, y + 44, 30.0, value); + draw_text_line(canvas, Rgb([146, 163, 181]), x + 20, y + 84, 17.0, meta); } fn draw_text_line(canvas: &mut RgbImage, color: Rgb, x: i32, y: i32, size: f32, text: &str) { diff --git a/crates/aster-webui/src/ui.rs b/crates/aster-webui/src/ui.rs index 154cea7..a29c070 100644 --- a/crates/aster-webui/src/ui.rs +++ b/crates/aster-webui/src/ui.rs @@ -63,6 +63,12 @@ const INDEX_HTML: &str = r##" gap: 16px; margin-bottom: 14px; } + .topbar-actions { + display: inline-flex; + gap: 8px; + align-items: center; + flex-wrap: wrap; + } .brand { display: flex; align-items: center; @@ -145,7 +151,7 @@ const INDEX_HTML: &str = r##" .subtle { color: var(--faint); font-size: .82rem; } .controls { display: grid; - grid-template-columns: 132px minmax(220px, 1fr) 180px auto; + grid-template-columns: 132px minmax(220px, 1fr) 180px; gap: 10px; align-items: end; } @@ -482,8 +488,9 @@ const INDEX_HTML: &str = r##"

AOOSTAR display control

-
+
+
@@ -517,9 +524,6 @@ const INDEX_HTML: &str = r##" -
- -
diff --git a/unraid-aoostar-rs-template.xml b/unraid-aoostar-rs-template.xml deleted file mode 100644 index 178d118..0000000 --- a/unraid-aoostar-rs-template.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - aoostar-rs - git.mp-mueller.de/magges/aoostar-rs:latest - https://git.mp-mueller.de - bridge - - bash - false - https://git.mp-mueller.de/magges/aoostar-rs - https://git.mp-mueller.de/magges/aoostar-rs - AOOSTAR Rust WebUI fuer das Frontdisplay, gebaut aus der Gitea-Registry. - Tools:Utilities Other: - http://[IP]:[PORT:8080]/ - - /plugins/dynamix.docker.manager/images/custom/aoostar-rs.svg - --restart unless-stopped --device=/dev/ttyACM0:/dev/ttyACM0 - - - - - - Native aster-webui aus aoostar-rs mit persistentem /config und USB-Geraetedurchreichung fuer das AOOSTAR-Display. - - - bridge - - - 8081 - 8080 - tcp - - - - - 8081 - /mnt/user/appdata/aoostar-rs/config - /mnt/cache - /mnt/user - 8080 - /dev/ttyACM0 - - 0 - 0 - 0 -