Improve widget formatting and add logged-in users support

Services widget:
- Fix disk quota formatting with proper rounding instead of truncation
- Remove decimals from RAM quotas and use GB instead of G
- Change quota display to use GB consistently

Backups widget:
- Change GiB to GB for consistency
- Remove spaces between numbers and units
- Update disk usage format to match other widgets: used (totalGB)
- Remove percentage display for cleaner format

System widget:
- Add support for logged-in users in description lines
- Format C-states with "C-State:" prefix on first line, indent subsequent lines
- Add logged_in_users field to SystemSummary data structure

Documentation:
- Add example hash error output to NixOS update instructions
This commit is contained in:
2025-10-14 18:59:31 +02:00
parent 3e5e91f078
commit 1ee398e648
6 changed files with 59 additions and 22 deletions

View File

@@ -58,6 +58,8 @@ pub struct SystemSummary {
pub cpu_temp_status: Option<String>,
#[serde(default)]
pub cpu_cstate: Option<Vec<String>>,
#[serde(default)]
pub logged_in_users: Option<Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]

View File

@@ -59,11 +59,11 @@ fn render_metrics(frame: &mut Frame, _host: &HostDisplayData, metrics: &BackupMe
data.add_row(
Some(WidgetStatus::new(latest_status)),
vec![format!("{} archives, {:.1} GiB total", metrics.backup.snapshot_count, metrics.backup.size_gb)],
vec![format!("{} archives, {:.1}GB total", metrics.backup.snapshot_count, metrics.backup.size_gb)],
vec![
"Latest".to_string(),
latest_time,
format!("{:.1} GiB", metrics.backup.latest_archive_size_gb.unwrap_or(metrics.backup.size_gb)),
format!("{:.1}GB", metrics.backup.latest_archive_size_gb.unwrap_or(metrics.backup.size_gb)),
],
);
@@ -81,7 +81,15 @@ fn render_metrics(frame: &mut Frame, _host: &HostDisplayData, metrics: &BackupMe
vec![
"Disk".to_string(),
disk.health.clone(),
format!("{:.1}/{:.0} GB ({:.0}%)", disk.used_gb, disk.total_gb, disk.usage_percent),
{
let used_mb = disk.used_gb * 1000.0;
let used_str = if used_mb < 1000.0 {
format!("{:.0}MB", used_mb)
} else {
format!("{:.1}GB", disk.used_gb)
};
format!("{} ({}GB)", used_str, disk.total_gb.round() as u32)
},
],
);
} else {

View File

@@ -154,13 +154,8 @@ fn format_memory_value(used: f32, quota: f32) -> String {
if quota > 0.05 {
let quota_gb = quota / 1000.0;
// Format quota nicely - show decimals only if needed
let quota_str = if quota_gb.fract() == 0.0 {
format!("{}G", quota_gb as u32)
} else {
format!("{:.1}G", quota_gb)
};
format!("{} ({})", used_value, quota_str)
// Format quota without decimals and use GB
format!("{} ({}GB)", used_value, quota_gb as u32)
} else {
used_value
}
@@ -178,13 +173,8 @@ fn format_disk_value(used: f32, quota: f32) -> String {
let used_value = format_bytes(used * 1000.0); // Convert GB to MB for format_bytes
if quota > 0.05 {
// Format quota nicely - show decimals only if needed
let quota_str = if quota.fract() == 0.0 {
format!("{}G", quota as u32)
} else {
format!("{:.1}G", quota)
};
format!("{} ({})", used_value, quota_str)
// Format quota without decimals and use GB (round to nearest GB)
format!("{} ({}GB)", used_value, quota.round() as u32)
} else {
used_value
}

View File

@@ -65,12 +65,35 @@ fn render_metrics(
overall_status.clone()
);
// Use agent-provided C-states as description (agent decides what goes in descriptions)
let cstate_description = summary.cpu_cstate.clone().unwrap_or_default();
// Use agent-provided C-states and logged-in users as description
let mut description_lines = Vec::new();
// Add C-states with prefix on first line, indent subsequent lines
if let Some(cstates) = &summary.cpu_cstate {
for (i, cstate_line) in cstates.iter().enumerate() {
if i == 0 {
description_lines.push(format!("C-State: {}", cstate_line));
} else {
description_lines.push(format!(" {}", cstate_line));
}
}
}
// Add logged-in users to description
if let Some(users) = &summary.logged_in_users {
if !users.is_empty() {
let user_line = if users.len() == 1 {
format!("Logged in: {}", users[0])
} else {
format!("Logged in: {} users ({})", users.len(), users.join(", "))
};
description_lines.push(user_line);
}
}
system_dataset.add_row(
overall_status.clone(),
cstate_description,
description_lines,
vec![
format!("{:.1} / {:.1} GB", summary.memory_used_mb / 1000.0, summary.memory_total_mb / 1000.0),
format!("{:.2}{:.2}{:.2}", summary.cpu_load_1, summary.cpu_load_5, summary.cpu_load_15),