//! Reconcile the OS login entry with the saved setting. use std::{io, path::Path}; pub fn reconcile(enabled: bool) -> io::Result<()> { apply(enabled, &std::env::current_exe()?) } #[cfg(target_os = "linux")] fn apply(enabled: bool, executable: &Path) -> io::Result<()> { let path = dirs::config_dir() .ok_or_else(|| io::Error::other("No config directory"))? .join("autostart/clipbin.desktop"); if enabled { std::fs::create_dir_all(path.parent().unwrap())?; let executable = executable .to_str() .ok_or_else(|| io::Error::other("Executable path is not UTF-8"))?; // Desktop Entry Exec quoting includes reserved characters and doubles %. let quoted = executable .replace('\\', "\\\\") .replace('"', "\\\"") .replace('`', "\\`") .replace('$', "\\$") .replace('%', "%%"); let escaped = quoted .replace('\\', "\\\\") .replace('\n', "\\n") .replace('\r', "\\r") .replace('\t', "\\t"); std::fs::write( path, format!( "[Desktop Entry]\nType=Application\nName=Clipbin\nExec=\"{escaped}\" --background\nTerminal=false\n" ), ) } else { match std::fs::remove_file(path) { Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(()), result => result, } } } #[cfg(windows)] fn apply(enabled: bool, executable: &Path) -> io::Result<()> { use winreg::{RegKey, enums::HKEY_CURRENT_USER}; let (key, _) = RegKey::predef(HKEY_CURRENT_USER) .create_subkey(r"Software\Microsoft\Windows\CurrentVersion\Run")?; if enabled { key.set_value( "Clipbin", &format!("\"{}\" --background", executable.display()), ) } else { match key.delete_value("Clipbin") { Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(()), result => result, } } }