aura-gui 0.2.2

UI nativa acelerada por GPU para escritorio, Android e iOS, en un solo crate: estilo tipo Tailwind, componentes, sombras, animaciones y agentes de IA. Reposo a cero. Licencia AGPL-3.0 o comercial.
//! macOS: `open`, `NSFileManager`, `taskpolicy` y el llavero (`keychain`).

use std::path::Path;
use std::process::{Command, Stdio};

pub use super::keychain::{secret_get, secret_remove, secret_set};

const OPEN: &str = "/usr/bin/open";
const TASKPOLICY: &str = "/usr/sbin/taskpolicy";

fn launch(command: &mut Command) -> Result<(), String> {
    let child = command
        .stdin(Stdio::null())
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .spawn()
        .map_err(|error| format!("no se pudo ejecutar open: {error}"))?;
    crate::core::platform::launch::reap(child)
}

pub fn open_url(url: &str, background: bool) -> Result<(), String> {
    let mut command = Command::new(OPEN);
    if background {
        command.arg("-g");
    }
    launch(command.arg(url))
}

pub fn reveal(path: &Path) -> Result<(), String> {
    launch(Command::new(OPEN).arg("-R").arg(path))
}

/// La misma llamada que usa el Finder: permite «Devolver» desde la papelera.
pub fn trash(path: &Path) -> Result<(), String> {
    use objc2_foundation::{NSFileManager, NSURL};
    let url = NSURL::from_file_path(path).ok_or("la ruta no es válida")?;
    NSFileManager::defaultManager()
        .trashItemAtURL_resultingItemURL_error(&url, None)
        .map_err(|error| error.localizedDescription().to_string())
}

pub fn low_priority_command(program: &str) -> Command {
    if !Path::new(TASKPOLICY).is_file() {
        return Command::new(program);
    }
    let mut command = Command::new(TASKPOLICY);
    command.args(["-b", program]);
    command
}