276 lines
9.3 KiB
Rust
276 lines
9.3 KiB
Rust
use std::io::Cursor;
|
|
|
|
use super::BasePage;
|
|
use crate::gallery::Grid;
|
|
use crate::hooks::use_user_context;
|
|
use gloo_net::http::Request;
|
|
|
|
use js_sys::{Array, ArrayBuffer, Promise};
|
|
use serde::{Deserialize, Serialize};
|
|
use wasm_bindgen::{prelude::wasm_bindgen, JsCast, JsValue};
|
|
use web_sys::{
|
|
DataTransferItemList, Element, File, FileReader, FileSystemDirectoryEntry, FileSystemEntry,
|
|
HtmlElement,
|
|
};
|
|
use weblog::console_log;
|
|
use yew::prelude::*;
|
|
use yew_hooks::prelude::*;
|
|
|
|
use common::OutputPicture;
|
|
|
|
pub struct MetaData {
|
|
width: u32,
|
|
height: u32,
|
|
}
|
|
#[derive(Debug, Deserialize, Serialize)]
|
|
pub struct PhotosWrapper {
|
|
photos: Vec<String>,
|
|
}
|
|
#[derive(Debug, Deserialize, Serialize)]
|
|
pub struct PhotosUrlsWrapper {
|
|
photos: Vec<(String, String)>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize, Serialize)]
|
|
pub struct DetailPhoto {
|
|
key: String,
|
|
width: u32,
|
|
height: u32,
|
|
}
|
|
#[derive(Debug, Deserialize, Serialize)]
|
|
pub struct DetailPhotoWrapper {
|
|
photos: Vec<DetailPhoto>,
|
|
}
|
|
|
|
#[function_component(Home)]
|
|
pub fn home() -> Html {
|
|
let user_ctx = use_user_context();
|
|
|
|
let node = use_node_ref();
|
|
let size = use_size(node.clone());
|
|
|
|
let pictures = use_state(std::vec::Vec::new);
|
|
|
|
{
|
|
let pictures = pictures.clone();
|
|
use_effect_with_deps(
|
|
move |_| {
|
|
wasm_bindgen_futures::spawn_local(async move {
|
|
let url = "/api/photos/get";
|
|
let fetched_pictures: Vec<OutputPicture> = Request::get(url)
|
|
.send()
|
|
.await
|
|
.unwrap()
|
|
.json()
|
|
.await
|
|
.unwrap();
|
|
pictures.set(fetched_pictures);
|
|
});
|
|
|| ()
|
|
},
|
|
(),
|
|
);
|
|
}
|
|
|
|
let drag_node = node.clone();
|
|
let ondrop = Callback::from(move |e: DragEvent| {
|
|
e.prevent_default();
|
|
if let Some(element) = drag_node.cast::<HtmlElement>() {
|
|
element.class_list().remove_1("dragover_highlight").unwrap();
|
|
}
|
|
|
|
let items = e.data_transfer().unwrap().items();
|
|
wasm_bindgen_futures::spawn_local(async move {
|
|
let promise = get_files_data_transfer_items(items);
|
|
let result = wasm_bindgen_futures::JsFuture::from(promise).await.unwrap();
|
|
|
|
console_log!(&result);
|
|
|
|
let traverse = |d: JsValue| {
|
|
let mut new_files: Vec<JsValue> = Vec::new();
|
|
let mut files: Vec<File> = Vec::new();
|
|
|
|
if let Ok(fse) = d.clone().dyn_into::<File>() {
|
|
console_log!(&fse);
|
|
files.push(fse.clone());
|
|
} else if let Ok(a) = d.clone().dyn_into::<js_sys::Array>() {
|
|
for i in 0..a.length() {
|
|
let f = a.get(i);
|
|
new_files.push(f);
|
|
}
|
|
} else if let Ok(o) = d.clone().dyn_into::<js_sys::Object>() {
|
|
if let Ok(subfolder) = js_sys::Reflect::get(&o, &JsValue::from_str("subfolder"))
|
|
{
|
|
new_files.push(subfolder);
|
|
}
|
|
}
|
|
(new_files, files)
|
|
};
|
|
|
|
let mut files: Vec<File> = Vec::new();
|
|
let mut new_files = vec![result];
|
|
|
|
loop {
|
|
console_log!(files.len());
|
|
let Some(current) = new_files.pop() else {
|
|
console_log!("break");
|
|
break;
|
|
};
|
|
|
|
let (news, fs) = traverse(current);
|
|
news.iter().for_each(|x| new_files.push(x.clone()));
|
|
fs.iter().for_each(|x| files.push(x.clone()));
|
|
}
|
|
|
|
let uiae: Vec<String> = files
|
|
.iter()
|
|
.map(|x| {
|
|
if let Ok(filepath) = js_sys::Reflect::get(x, &JsValue::from_str("filepath")) {
|
|
filepath.as_string().unwrap_or("".to_string())
|
|
} else {
|
|
"".to_string()
|
|
}
|
|
})
|
|
.collect();
|
|
console_log!("end", uiae.join("\n"));
|
|
|
|
let photos: PhotosUrlsWrapper = Request::post("/api/photos/upload")
|
|
.json(&PhotosWrapper {
|
|
photos: uiae.clone(),
|
|
})
|
|
.unwrap()
|
|
.send()
|
|
.await
|
|
.unwrap()
|
|
.json()
|
|
.await
|
|
.unwrap();
|
|
console_log!("{}", serde_json::to_string(&photos).unwrap());
|
|
|
|
let mut metadata: Vec<MetaData> = Vec::new();
|
|
let mut promises: Vec<Promise> = Vec::new();
|
|
for (file, (key, url)) in files.iter().zip(photos.photos) {
|
|
console_log!("uploading: ", &file.name(), &url);
|
|
let promise = read_file(file.clone());
|
|
if let Ok(content) = wasm_bindgen_futures::JsFuture::from(promise).await {
|
|
let buffer: ArrayBuffer = content.dyn_into().unwrap();
|
|
let typed_buffer: js_sys::Uint8Array = js_sys::Uint8Array::new(&buffer);
|
|
let mut buf = vec![0; typed_buffer.length() as usize];
|
|
typed_buffer.copy_to(&mut buf);
|
|
// console_log!(
|
|
// serde_json::to_string(&buf.len()).unwrap(),
|
|
// serde_json::to_string(&buf).unwrap()
|
|
// );
|
|
let mut md = MetaData {
|
|
width: 0,
|
|
height: 0,
|
|
};
|
|
let meta = image_meta::load_from_buf(&buf).unwrap();
|
|
console_log!(format!(
|
|
"dims: {}x{}",
|
|
meta.dimensions.width, meta.dimensions.height
|
|
));
|
|
console_log!(format!("animation: {:?}", meta.is_animation()));
|
|
console_log!(format!("format: {:?}", meta.format));
|
|
md.height = meta.dimensions.height;
|
|
md.width = meta.dimensions.width;
|
|
|
|
let exifreader = exif::Reader::new();
|
|
let mut cursor = Cursor::new(&buf);
|
|
if let Ok(exif) = exifreader.read_from_container(&mut cursor) {
|
|
for f in exif.fields() {
|
|
console_log!(format!(
|
|
"{} {} {}",
|
|
f.tag,
|
|
f.ifd_num,
|
|
f.display_value().with_unit(&exif)
|
|
));
|
|
}
|
|
}
|
|
metadata.push(md);
|
|
|
|
promises.push(upload(buffer, file.type_(), url.clone()));
|
|
}
|
|
}
|
|
|
|
for promise in promises {
|
|
match wasm_bindgen_futures::JsFuture::from(promise).await {
|
|
Ok(result) => console_log!(result),
|
|
Err(e) => console_log!("errooooor", e),
|
|
};
|
|
}
|
|
|
|
let photos: DetailPhotoWrapper = Request::post("/api/photos/upload/done")
|
|
.json(&DetailPhotoWrapper {
|
|
photos: uiae
|
|
.iter()
|
|
.zip(metadata)
|
|
.map(|(p, md)| DetailPhoto {
|
|
key: p.clone(),
|
|
width: md.width,
|
|
height: md.height,
|
|
})
|
|
.collect(),
|
|
})
|
|
.unwrap()
|
|
.send()
|
|
.await
|
|
.unwrap()
|
|
.json()
|
|
.await
|
|
.unwrap();
|
|
console_log!("all uploaded");
|
|
});
|
|
});
|
|
|
|
let drag_node = node.clone();
|
|
let ondragenter = Callback::from(move |e: DragEvent| {
|
|
e.prevent_default();
|
|
// e.data_transfer().unwrap().set_drop_effect("move");
|
|
if let Some(element) = drag_node.cast::<HtmlElement>() {
|
|
element.class_list().remove_1("dragover_highlight").unwrap();
|
|
}
|
|
});
|
|
|
|
let drag_node = node.clone();
|
|
let ondragleave = Callback::from(move |e: DragEvent| {
|
|
e.prevent_default();
|
|
if let Some(element) = drag_node.cast::<HtmlElement>() {
|
|
element.class_list().remove_1("dragover_highlight").unwrap();
|
|
}
|
|
});
|
|
|
|
let drag_node = node.clone();
|
|
let ondragover = Callback::from(move |e: DragEvent| {
|
|
e.prevent_default();
|
|
if let Some(element) = drag_node.cast::<HtmlElement>() {
|
|
element.class_list().add_1("dragover_highlight").unwrap();
|
|
}
|
|
});
|
|
|
|
let body = if user_ctx.is_authenticated() {
|
|
html! {
|
|
<Grid
|
|
pictures={(*pictures).clone()}
|
|
width={size.0}
|
|
/>
|
|
}
|
|
} else {
|
|
html! {}
|
|
};
|
|
html! {
|
|
<BasePage>
|
|
<div ref={node} {ondrop} {ondragenter} {ondragleave} {ondragover}>
|
|
{body}
|
|
</div>
|
|
</BasePage>
|
|
}
|
|
}
|
|
|
|
#[wasm_bindgen(module = "/src/components/home.js")]
|
|
extern "C" {
|
|
fn get_files_data_transfer_items(data_transfer_items: DataTransferItemList) -> js_sys::Promise;
|
|
fn read_file(file: File) -> js_sys::Promise;
|
|
fn upload(content: ArrayBuffer, content_type: String, url: String) -> js_sys::Promise;
|
|
}
|