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, } #[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, } #[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 = 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::() { 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 = Vec::new(); let mut files: Vec = Vec::new(); if let Ok(fse) = d.clone().dyn_into::() { console_log!(&fse); files.push(fse.clone()); } else if let Ok(a) = d.clone().dyn_into::() { for i in 0..a.length() { let f = a.get(i); new_files.push(f); } } else if let Ok(o) = d.clone().dyn_into::() { if let Ok(subfolder) = js_sys::Reflect::get(&o, &JsValue::from_str("subfolder")) { new_files.push(subfolder); } } (new_files, files) }; let mut files: Vec = 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 = 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 = Vec::new(); let mut promises: Vec = 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::() { 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::() { 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::() { element.class_list().add_1("dragover_highlight").unwrap(); } }); let body = if user_ctx.is_authenticated() { html! { } } else { html! {} }; html! {
{body}
} } #[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; }