cathode/src-tauri/src/fs.rs

105 lines
2.8 KiB
Rust

use std::collections::HashMap;
use std::io::Cursor;
use std::path::Path;
use base64_url as base64;
use image::ImageFormat;
use log::{debug, trace};
use ray_format::Ray;
use serde::{Deserialize, Serialize};
use tauri::api::dialog::blocking::FileDialogBuilder;
use tauri::api::path::home_dir;
const OBJ_URL: &'static str = "data:image/png;base64,";
#[derive(Serialize, Deserialize, Clone, Debug)]
pub(crate) struct WebRay {
frames: [String; 4],
meta: HashMap<String, String>,
}
#[tauri::command]
pub(crate) async fn open_image() -> Option<String> {
let path = FileDialogBuilder::new()
.add_filter("Images", &["png", "jpg"])
.set_directory(home_dir()?)
.set_title("Select an image")
.pick_file()?;
if let Ok(b) = image::open(path) {
let mut buf = Cursor::new(vec![]);
b.write_to(&mut buf, ImageFormat::Png).unwrap();
let encoded = base64::encode(buf.get_ref());
trace!("Encoded: {:?}", encoded);
Some(format!("{}{}", OBJ_URL, encoded))
} else {
None
}
}
#[tauri::command]
pub(crate) async fn open_ray() -> Option<WebRay> {
let path = FileDialogBuilder::new()
.add_filter("Rays", &["ray"])
.set_directory(home_dir()?)
.pick_file()?;
load_ray(path).await
}
pub(crate) async fn load_ray(path: impl AsRef<Path>) -> Option<WebRay> {
let ray = Ray::load(path).ok()?;
let mut frames = [String::new(), String::new(), String::new(), String::new()];
let mut meta = HashMap::new();
for i in 0..4 {
debug!("Trying frame {}", i);
if let Some(f) = ray.get_frame(i as usize) {
debug!("Got frame {}", i);
if f.is_empty() {
debug!("Frame {} was empty", i);
continue;
}
let encoded = base64::encode(&f);
frames[i as usize] = format!("{}{}", OBJ_URL, encoded);
}
}
for k in ray.get_meta_keys() {
if let Some(v) = ray.get_meta_value(&k) {
meta.insert(k.clone(), v.clone());
}
}
Some(WebRay { frames, meta })
}
#[tauri::command]
pub(crate) async fn save_ray(ray: WebRay) -> Result<(), String> {
if let Some(path) = FileDialogBuilder::new()
.add_filter("Rays", &["ray"])
.set_directory(home_dir().unwrap())
.set_title("Save Ray")
.set_file_name("new.ray")
.save_file()
{
let mut res = Ray::default();
for (i, f) in ray.frames.iter().enumerate() {
let stripped = f.strip_prefix(OBJ_URL).unwrap_or(f);
let decoded = base64::decode(stripped).unwrap();
res.set_frame(i as usize, decoded);
}
for (k, v) in ray.meta {
res.add_meta(k, v);
}
res.save(&path)
.map_err(|e| format!("Failed to save ray file: {}", e))
} else {
Ok(())
}
}