diff --git a/AobaClient/src/components/basic/input.rs b/AobaClient/src/components/basic/input.rs index d816559..18e0372 100644 --- a/AobaClient/src/components/basic/input.rs +++ b/AobaClient/src/components/basic/input.rs @@ -7,7 +7,7 @@ pub struct InputProps { pub label: Option, pub placeholder: Option, pub name: String, - pub oninput: Option>, + pub oninput: Option>>, pub required: Option, } @@ -22,9 +22,12 @@ pub fn Input(props: InputProps) -> Element { r#type: props.r#type.unwrap_or("text".into()), value: props.value, oninput: move |e| { - if let Some(mut s) = props.value { - s.set(e.value()); - } + if let Some(mut s) = props.value { + s.set(e.value()); + } + if let Some(handler) = props.oninput{ + handler.call(e); + } }, name: props.name, placeholder: ph, diff --git a/AobaClient/src/components/context_menu.rs b/AobaClient/src/components/context_menu.rs new file mode 100644 index 0000000..d93b6bf --- /dev/null +++ b/AobaClient/src/components/context_menu.rs @@ -0,0 +1,20 @@ +use core::str; + +use dioxus::prelude::*; + +#[derive(PartialEq, Clone, Props)] +pub struct ContextMenuProps { + pub top: f64, + pub left: f64, + pub items: Option>, +} + +#[component] +pub fn ContextMenu(props: ContextMenuProps) -> Element { + rsx! { + div { + style: "background:#000; position: absolute; left: {props.left}px; top: {props.top}px;", + "Contect Menu" + } + } +} diff --git a/AobaClient/src/components/media_grid.rs b/AobaClient/src/components/media_grid.rs index 656634e..8b51d18 100644 --- a/AobaClient/src/components/media_grid.rs +++ b/AobaClient/src/components/media_grid.rs @@ -2,7 +2,7 @@ use dioxus::prelude::*; use tonic::IntoRequest; use crate::{ - components::MediaItem, + components::{ContextMenu, MediaItem}, rpc::{aoba::PageFilter, get_rpc_client}, }; @@ -46,15 +46,32 @@ pub fn MediaGrid(props: MediaGridProps) -> Element { } })); + let mut context_menu: Signal = use_signal(|| rsx! {}); + let oncontext = move |event: Event| { + event.prevent_default(); + let data = event.data(); + let pos = data.coordinates().client(); + let left = pos.x; + let top = pos.y; + context_menu.set(rsx! { ContextMenu{ + left: left, + top: top + }}); + }; + match media_result.cloned() { Some(value) => match value { Ok(result) => rsx! { div { class: "mediaGrid", + onclick: move |_e| { + context_menu.set(rsx!{}); + }, {result.items.iter().map(|itm| rsx!{ - MediaItem { item: Some(itm.clone()) } + MediaItem { item: Some(itm.clone()), oncontextmenu: oncontext } })}, } + {context_menu.cloned()} }, Err(msg) => rsx! { div { diff --git a/AobaClient/src/components/media_item.rs b/AobaClient/src/components/media_item.rs index 6ee193f..801734e 100644 --- a/AobaClient/src/components/media_item.rs +++ b/AobaClient/src/components/media_item.rs @@ -5,6 +5,7 @@ use crate::{HOST, rpc::aoba::MediaModel}; #[derive(PartialEq, Clone, Props)] pub struct MediaItemProps { pub item: Option, + pub oncontextmenu: Option>>, } #[component] @@ -15,11 +16,17 @@ pub fn MediaItem(props: MediaItemProps) -> Element { let id = item.id.unwrap().value; let thumb = item.thumb_url; let url = item.media_url; + return rsx! { a { class: "mediaItem", href: "{HOST}/{url}", target: "_blank", + oncontextmenu: move |e| { + if let Some(handler) = props.oncontextmenu{ + handler.call(e); + } + }, "data-id" : id, img { src: "{HOST}{thumb}" } span { class: "info", @@ -29,7 +36,7 @@ pub fn MediaItem(props: MediaItemProps) -> Element { span { "{item.view_count}" } } } - } + }, }; } else { return rsx! { diff --git a/AobaClient/src/components/mod.rs b/AobaClient/src/components/mod.rs index 3793b05..ad908bf 100644 --- a/AobaClient/src/components/mod.rs +++ b/AobaClient/src/components/mod.rs @@ -1,10 +1,12 @@ pub mod basic; +mod context_menu; mod media_grid; mod media_item; mod metrics_token; mod navbar; mod notif; mod search; +pub use context_menu::*; pub use media_grid::*; pub use media_item::*; pub use metrics_token::*;