From dc45c82aba4824af826abaa58ccb23f54ac4dc33 Mon Sep 17 00:00:00 2001 From: pyr0ball Date: Mon, 18 May 2026 15:53:03 -0700 Subject: [PATCH] feat(m1): distro detection from /etc/os-release, update_notification_level command --- src-tauri/src/commands.rs | 26 ++++++++++++-- src-tauri/src/distro.rs | 73 +++++++++++++++++++++++++++++++++++++++ src-tauri/src/lib.rs | 2 ++ 3 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 src-tauri/src/distro.rs diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 0041697..94a7863 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -1,4 +1,4 @@ -use crate::config::{RobinConfig, MigrationConfig, SourceOs}; +use crate::config::{NotificationLevel, RobinConfig, MigrationConfig, SourceOs}; use tauri::State; use std::sync::Mutex; @@ -33,11 +33,33 @@ pub fn complete_onboarding( _ => SourceOs::Unknown, }; + let detected = if distro == "unknown" || distro.is_empty() { + crate::distro::detect() + } else { + distro + }; + let mut config = state.config.lock().map_err(|e| e.to_string())?; config.migration = Some(MigrationConfig { source_os: source, - distro, + distro: detected, fluency_level: 0, }); config.save().map_err(|e| e.to_string()) } + +#[tauri::command] +pub fn update_notification_level( + level: String, + state: State<'_, AppState>, +) -> Result<(), String> { + let parsed = match level.as_str() { + "off" => NotificationLevel::Off, + "badge_only" => NotificationLevel::BadgeOnly, + "badge_and_toast" => NotificationLevel::BadgeAndToast, + _ => return Err(format!("unknown notification level: {level}")), + }; + let mut config = state.config.lock().map_err(|e| e.to_string())?; + config.display.notification_level = parsed; + config.save().map_err(|e| e.to_string()) +} diff --git a/src-tauri/src/distro.rs b/src-tauri/src/distro.rs new file mode 100644 index 0000000..3a92c35 --- /dev/null +++ b/src-tauri/src/distro.rs @@ -0,0 +1,73 @@ +pub fn detect() -> String { + std::fs::read_to_string("/etc/os-release") + .map(|s| parse_id(&s)) + .unwrap_or_else(|_| "unknown".to_string()) +} + +pub fn distro_family(id: &str) -> &'static str { + match id { + "arch" | "cachyos" | "endeavouros" | "manjaro" | "garuda" => "arch", + "debian" | "ubuntu" | "linuxmint" | "pop" | "elementary" | "kali" => { + "debian" + } + "fedora" | "rhel" | "centos" | "rocky" | "alma" => "fedora", + "opensuse" | "opensuse-tumbleweed" | "opensuse-leap" => "opensuse", + _ => "unknown", + } +} + +fn parse_id(content: &str) -> String { + content + .lines() + .find_map(|line| { + let (key, val) = line.split_once('=')?; + if key.trim() == "ID" { + Some(val.trim().trim_matches('"').to_lowercase()) + } else { + None + } + }) + .unwrap_or_else(|| "unknown".to_string()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn parses_arch_id() { + let content = "ID=arch\nID_LIKE=\nPRETTY_NAME=Arch Linux\n"; + assert_eq!(parse_id(content), "arch"); + } + + #[test] + fn parses_cachyos_id() { + let content = "ID=cachyos\nID_LIKE=arch\nPRETTY_NAME=CachyOS\n"; + assert_eq!(parse_id(content), "cachyos"); + } + + #[test] + fn parses_linuxmint_id() { + let content = "ID=linuxmint\nID_LIKE=ubuntu\nPRETTY_NAME=Linux Mint 22\n"; + assert_eq!(parse_id(content), "linuxmint"); + } + + #[test] + fn distro_family_arch_based() { + assert_eq!(distro_family("cachyos"), "arch"); + assert_eq!(distro_family("arch"), "arch"); + assert_eq!(distro_family("manjaro"), "arch"); + } + + #[test] + fn distro_family_debian_based() { + assert_eq!(distro_family("linuxmint"), "debian"); + assert_eq!(distro_family("ubuntu"), "debian"); + assert_eq!(distro_family("debian"), "debian"); + } + + #[test] + fn distro_family_unknown() { + assert_eq!(distro_family("slackware"), "unknown"); + } +} diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index c292b19..618356e 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,5 +1,6 @@ mod commands; mod config; +mod distro; mod tray; mod watcher; @@ -29,6 +30,7 @@ pub fn run() { commands::get_config, commands::needs_onboarding, commands::complete_onboarding, + commands::update_notification_level, ]) .run(tauri::generate_context!()) .expect("error while running Robin");