synpad 0.1.0

A full-featured Matrix chat client built with Dioxus
use std::path::PathBuf;

pub struct FileFilter {
    pub name: &'static str,
    pub extensions: &'static [&'static str],
}

pub struct PickedFile {
    pub file_name: String,
    pub bytes: Vec<u8>,
}

#[cfg(any(feature = "desktop", feature = "web"))]
pub async fn pick_file(
    title: &str,
    filters: &[FileFilter],
) -> Result<Option<PickedFile>, String> {
    let mut dialog = rfd::AsyncFileDialog::new().set_title(title);
    for filter in filters {
        dialog = dialog.add_filter(filter.name, filter.extensions);
    }

    let Some(handle) = dialog.pick_file().await else {
        return Ok(None);
    };

    Ok(Some(PickedFile {
        file_name: handle.file_name(),
        bytes: handle.read().await,
    }))
}

#[cfg(not(any(feature = "desktop", feature = "web")))]
pub async fn pick_file(
    _title: &str,
    _filters: &[FileFilter],
) -> Result<Option<PickedFile>, String> {
    Err("File dialogs are not available on this platform yet.".to_string())
}

#[cfg(any(feature = "desktop", feature = "web"))]
pub async fn pick_save_path(title: &str, file_name: &str) -> Result<Option<PathBuf>, String> {
    let handle = rfd::AsyncFileDialog::new()
        .set_title(title)
        .set_file_name(file_name)
        .save_file()
        .await;

    Ok(handle.map(|file| file.path().to_path_buf()))
}

#[cfg(not(any(feature = "desktop", feature = "web")))]
pub async fn pick_save_path(_title: &str, _file_name: &str) -> Result<Option<PathBuf>, String> {
    Err("Saving files is not available on this platform yet.".to_string())
}

#[cfg(any(feature = "desktop", feature = "web"))]
pub async fn save_file(title: &str, file_name: &str, bytes: &[u8]) -> Result<Option<PathBuf>, String> {
    let handle = rfd::AsyncFileDialog::new()
        .set_title(title)
        .set_file_name(file_name)
        .save_file()
        .await;

    let Some(handle) = handle else {
        return Ok(None);
    };

    handle
        .write(bytes)
        .await
        .map_err(|e| format!("Failed to save file: {e}"))?;

    Ok(Some(handle.path().to_path_buf()))
}

#[cfg(not(any(feature = "desktop", feature = "web")))]
pub async fn save_file(
    _title: &str,
    _file_name: &str,
    _bytes: &[u8],
) -> Result<Option<PathBuf>, String> {
    Err("Saving files is not available on this platform yet.".to_string())
}