maverick_os 0.2.5

Maverick OS
Documentation
use std::sync::mpsc::Sender;
use super::ImageOrientation;
use std::process::Command;
use std::path::Path;
use std::fs;
use std::thread;

#[derive(Clone)]
pub struct OsPhotoPicker;

impl OsPhotoPicker {
    pub fn open(sender: Sender<(Vec<u8>, ImageOrientation)>) {
        thread::spawn(move || {
            let result = Self::try_zenity()
                .or_else(|| Self::try_kdialog())
                .or_else(|| Self::try_xdg_open());

            match result {
                Some(file_path) => {
                    if let Ok(image_data) = fs::read(&file_path) {
                        let orientation = Self::get_image_orientation(&file_path);
                        let _ = sender.send((image_data, orientation));
                    } else {
                        let _ = sender.send((Vec::new(), ImageOrientation::Up));
                    }
                }
                None => {
                    let _ = sender.send((Vec::new(), ImageOrientation::Up));
                }
            }
        });
    }

    fn try_zenity() -> Option<String> {
        let result = Command::new("zenity")
            .args(&[
                "--file-selection",
                "--file-filter=Image files | *.jpg *.jpeg *.png",
                "--file-filter=All files | *",
                "--title=Select an Image",
            ])
            .output();

        match result {
            Ok(output) if output.status.success() => {
                let file_path = String::from_utf8_lossy(&output.stdout).trim().to_string();
                if !file_path.is_empty() && Path::new(&file_path).exists() {
                    Some(file_path)
                } else {
                    None
                }
            }
            _ => None,
        }
    }

    fn try_kdialog() -> Option<String> {
        let result = Command::new("kdialog")
            .args(&[
                "--getopenfilename",
                ".",
                "*.jpg *.jpeg *.png *.webp|Image files",
                "--title",
                "Select an Image",
            ])
            .output();

        match result {
            Ok(output) if output.status.success() => {
                let file_path = String::from_utf8_lossy(&output.stdout).trim().to_string();
                if !file_path.is_empty() && Path::new(&file_path).exists() {
                    Some(file_path)
                } else {
                    None
                }
            }
            _ => None,
        }
    }

    fn try_xdg_open() -> Option<String> {
        None
    }

    fn get_image_orientation(file_path: &str) -> ImageOrientation {
        let path = Path::new(file_path);
        if let Some(extension) = path.extension() {
            match extension.to_str().unwrap_or("").to_lowercase().as_str() {
                "jpg" | "jpeg" => {
                    ImageOrientation::Up
                }
                _ => ImageOrientation::Up,
            }
        } else {
            ImageOrientation::Up
        }
    }
}