From 5c1943bdd48c3308e21963994f6582988d64ebc0 Mon Sep 17 00:00:00 2001 From: luoxiao Date: Tue, 24 Oct 2023 17:39:09 +0800 Subject: [PATCH] feat: upload component --- Cargo.toml | 2 +- src/skeleton/mod.rs | 1 - src/upload/mod.rs | 20 ++++++++-- src/utils/callback.rs | 89 +++++++++++++++++++++++++++++++++++++++++++ src/utils/mod.rs | 2 + 5 files changed, 108 insertions(+), 6 deletions(-) create mode 100644 src/utils/callback.rs diff --git a/Cargo.toml b/Cargo.toml index e5ab00b..929138a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ license = "MIT" [dependencies] leptos = { version = "0.5.1", features = ["csr"] } -web-sys = { version = "0.3.62", features = ["DomRect"] } +web-sys = { version = "0.3.62", features = ["DomRect", "File", "FileList"] } wasm-bindgen = "0.2.85" icondata = { version = "0.1.0", features = [ "AiCloseOutlined", diff --git a/src/skeleton/mod.rs b/src/skeleton/mod.rs index 3843f3d..bf5b8ee 100644 --- a/src/skeleton/mod.rs +++ b/src/skeleton/mod.rs @@ -40,7 +40,6 @@ pub fn Skeleton( css_vars }); (0..repeat.get()) - .into_iter() .map(|_| { view! {
} }) diff --git a/src/upload/mod.rs b/src/upload/mod.rs index 0644f11..1aa8417 100644 --- a/src/upload/mod.rs +++ b/src/upload/mod.rs @@ -1,23 +1,35 @@ +use crate::{mount_style, utils::AsyncCallback}; use leptos::*; -use crate::mount_style; -// TODO +use web_sys::FileList; #[component] pub fn Upload( #[prop(optional, into)] accept: MaybeSignal, #[prop(optional, into)] multiple: MaybeSignal, + #[prop(optional, into)] on_before_upload: Option>, children: Children, ) -> impl IntoView { mount_style("upload", include_str!("./upload.css")); - let on_file_addition = move || { + let on_file_addition = move |files: FileList| { + spawn_local(async move { + if let Some(on_before_upload) = on_before_upload { + let is_allow = on_before_upload.call(files).await; + if is_allow { + //TODO submit + } + } + }); }; let input_ref = create_node_ref::(); let on_change = move |_| { if let Some(input_ref) = input_ref.get_untracked() { + if let Some(files) = input_ref.files() { + on_file_addition(files); + } } }; - let on_click= move |_| { + let on_click = move |_| { if let Some(input_ref) = input_ref.get_untracked() { input_ref.click(); } diff --git a/src/utils/callback.rs b/src/utils/callback.rs new file mode 100644 index 0000000..5002dd0 --- /dev/null +++ b/src/utils/callback.rs @@ -0,0 +1,89 @@ +use leptos::StoredValue; +use std::{fmt, future::Future, pin::Pin, rc::Rc}; + +pub struct AsyncCallback( + #[allow(clippy::complexity)] StoredValue Pin>>>>, +); + +impl fmt::Debug for AsyncCallback { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + fmt.write_str("AsyncCallback") + } +} + +impl Clone for AsyncCallback { + fn clone(&self) -> Self { + *self + } +} + +impl Copy for AsyncCallback {} + +impl AsyncCallback { + pub fn new(f: F) -> Self + where + F: Fn(In) -> Fu + 'static, + Fu: Future + 'static, + { + let f = Rc::new(move |input: In| { + let fut = f(input); + Box::pin(fut) as Pin>> + }); + Self(StoredValue::new(f)) + } + + pub async fn call(&self, input: In) -> Out { + let f = self.0.get_value(); + f(input).await + } +} + +impl From for AsyncCallback +where + F: Fn(In) -> Fu + 'static, + Fu: Future + 'static, +{ + fn from(f: F) -> AsyncCallback { + AsyncCallback::new(f) + } +} + +#[cfg(test)] +mod tests { + use crate::utils::AsyncCallback; + use leptos::create_runtime; + + struct NoClone {} + + #[test] + fn clone_async_callback() { + let rt = create_runtime(); + let callback = AsyncCallback::new(move |_no_clone: NoClone| async { NoClone {} }); + let _cloned = callback.clone(); + rt.dispose(); + } + + #[test] + fn async_callback_from() { + let rt = create_runtime(); + let _callback: AsyncCallback<(), String> = (|()| async { "test".to_string() }).into(); + rt.dispose(); + } + + #[test] + fn async_callback_from_html() { + let rt = create_runtime(); + use leptos::{ + html::{HtmlElement, H1}, + *, + }; + + let _callback: AsyncCallback> = (|x: String| async move { + view! { +

{x}

+ } + }) + .into(); + rt.dispose(); + } +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 367ce52..bcd9bcf 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,6 +1,8 @@ +mod callback; pub mod maybe_rw_signal; mod maybe_signal_store; pub mod mount_style; pub mod signal; +pub use callback::AsyncCallback; pub use maybe_signal_store::*;