start file saving work
ci/woodpecker/push/woodpecker Pipeline was successful
Details
ci/woodpecker/push/woodpecker Pipeline was successful
Details
This commit is contained in:
parent
f2486208c7
commit
e4770a8894
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use std::{collections::HashMap, path::Path};
|
||||
use std::{collections::HashMap, fs, path::Path};
|
||||
|
||||
use crate::archive::Archive;
|
||||
|
||||
|
@ -24,6 +24,10 @@ impl Ray {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn add_meta(&mut self, key: String, value: String) -> bool {
|
||||
self.meta.insert(key, value).is_none()
|
||||
}
|
||||
|
||||
pub fn save(&self, path: &Path) -> Result<()> {
|
||||
let mut archive = Archive::new();
|
||||
for (i, f) in self.frames.iter().enumerate() {
|
||||
|
@ -38,6 +42,8 @@ impl Ray {
|
|||
let meta = serde_json::to_string(&self.meta)?;
|
||||
archive.add_file("meta.json", meta.as_bytes())?;
|
||||
|
||||
fs::write(path, archive.buffer())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,22 @@
|
|||
use std::collections::HashMap;
|
||||
use std::io::Cursor;
|
||||
|
||||
use base64_url as base64;
|
||||
use image::ImageFormat;
|
||||
use log::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,";
|
||||
|
||||
#[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![]);
|
||||
|
@ -16,8 +24,52 @@ pub(crate) async fn open_image() -> Option<String> {
|
|||
let encoded = base64::encode(buf.get_ref());
|
||||
trace!("Encoded: {:?}", encoded);
|
||||
|
||||
Some(format!("data:image/png;base64,{}", 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()?;
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub(crate) struct WebRay {
|
||||
frames: [String; 4],
|
||||
meta: HashMap<String, String>,
|
||||
}
|
||||
|
||||
#[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(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,8 @@ fn main() {
|
|||
get_mic_threshold,
|
||||
get_audio_level,
|
||||
fs::open_image,
|
||||
fs::save_ray,
|
||||
fs::open_ray,
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
import { invoke } from "@tauri-apps/api/tauri";
|
||||
import Bar from "../components/bar.svelte";
|
||||
import { tick } from "svelte";
|
||||
import { frames } from "../store";
|
||||
|
||||
let monitorTimer: NodeJS.Timer;
|
||||
|
||||
|
@ -46,6 +47,30 @@
|
|||
monitorTimer = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
const saveRay = async () => {
|
||||
let fr = new Array<string>(4);
|
||||
for (let i = 0; i < 4; i++) {
|
||||
$frames[i] ? (fr[i] = $frames[i]) : (fr[i] = "");
|
||||
}
|
||||
fr.map((e) => (e ? e : ""));
|
||||
const ray = {
|
||||
frames: [
|
||||
fr[0].toString(),
|
||||
fr[1].toString(),
|
||||
fr[2].toString(),
|
||||
fr[3].toString(),
|
||||
],
|
||||
meta: {
|
||||
threshold: $threshold.toString(),
|
||||
},
|
||||
};
|
||||
|
||||
// await invoke("log", { msg: `Saving ray: ${JSON.stringify(ray)}` });
|
||||
invoke("save_ray", { ray })
|
||||
.then()
|
||||
.catch((e) => invoke("log", { msg: e }).then());
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="container" class:transparent={$transparent}>
|
||||
|
@ -84,6 +109,7 @@
|
|||
>
|
||||
</div>
|
||||
{/if}
|
||||
<button on:click={saveRay}>Save</button>
|
||||
</div>
|
||||
|
||||
<svelte:body on:contextmenu|preventDefault />
|
||||
|
|
Loading…
Reference in New Issue