//! Official single-instance transport, scoped to an explicitly selected profile. use sha2::{Digest, Sha256}; use std::{ffi::OsString, io, path::PathBuf}; use tauri::{Emitter, Manager}; pub fn profile_identifier(base: &str, profile: Option) -> io::Result { let Some(profile) = profile else { return Ok(base.to_owned()); }; let path = crate::data_directory::resolve(PathBuf::new(), Some(profile))?; // Resolve the existing ancestor without creating a first-use profile. let canonical = crate::data_directory::canonical_exclusion(&path)?; let mut digest = Sha256::new(); #[cfg(windows)] { use std::os::windows::ffi::OsStrExt; for unit in canonical.as_os_str().encode_wide() { digest.update(unit.to_le_bytes()); } } #[cfg(not(windows))] { use std::os::unix::ffi::OsStrExt; digest.update(canonical.as_os_str().as_bytes()); } Ok(format!("{base}.profile{:x}", digest.finalize())) } pub fn focus_search(app: &tauri::AppHandle) { if let Some(window) = app.get_webview_window("main") { let result = window .show() .and_then(|_| window.unminimize()) .and_then(|_| window.set_focus()); if let Err(error) = result { eprintln!("Could not focus searchi: {error}"); } let _ = window.emit("focus-search", ()); } } #[cfg(test)] mod tests { use super::*; #[test] fn default_identity_is_unchanged_and_invalid_profile_rejected() { assert_eq!( profile_identifier("dev.searchi.desktop", None).unwrap(), "dev.searchi.desktop" ); assert!(profile_identifier("dev.searchi.desktop", Some("relative".into())).is_err()); } #[test] fn canonical_profiles_are_stable_distinct_and_do_not_expose_paths() { let root = tempfile::tempdir().unwrap(); let first = root.path().join("Gemäß_日本_😀"); let second = root.path().join("other"); let id = profile_identifier("dev.searchi.desktop", Some(first.clone().into_os_string())) .unwrap(); assert!(!first.exists()); std::fs::create_dir(&first).unwrap(); assert_eq!( id, profile_identifier( "dev.searchi.desktop", Some(first.join(".").into_os_string()) ) .unwrap() ); assert_ne!( id, profile_identifier("dev.searchi.desktop", Some(second.into_os_string())).unwrap() ); assert!(!id.contains("Gemäß")); assert_eq!(id.len(), "dev.searchi.desktop.profile".len() + 64); assert!(!root.path().join("other").exists()); } }