rewrite components such that data always flows downwards
This commit is contained in:
@@ -9,18 +9,22 @@ use crate::{
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Clone, Props)]
|
||||
pub struct MediaGridProps
|
||||
{
|
||||
pub struct MediaGridProps {
|
||||
pub query: Signal<String>,
|
||||
pub max_page: Signal<i32>,
|
||||
pub total_items: Signal<i32>,
|
||||
pub page: Signal<i32>,
|
||||
pub page_size: Signal<i32>,
|
||||
pub on_page_loaded: Option<EventHandler<PaginationInfo>>,
|
||||
}
|
||||
|
||||
pub struct PaginationInfo {
|
||||
pub total_pages: i32,
|
||||
pub total_items: i32,
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn MediaGrid(mut props: MediaGridProps) -> Element
|
||||
{
|
||||
pub fn MediaGrid(props: MediaGridProps) -> Element {
|
||||
let mut error_display = use_signal(|| {
|
||||
rsx! {}
|
||||
});
|
||||
@@ -34,32 +38,29 @@ pub fn MediaGrid(mut props: MediaGridProps) -> Element
|
||||
query: Some(props.query.cloned()),
|
||||
};
|
||||
let result = client.list_media(request).await;
|
||||
if let Ok(items) = result
|
||||
{
|
||||
if let Ok(items) = result {
|
||||
let res = items.into_inner();
|
||||
|
||||
return Ok(res);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
let err = result.err().unwrap();
|
||||
let message = err.message();
|
||||
return Err(format!("Failed to load results: {message}"));
|
||||
}
|
||||
}));
|
||||
|
||||
use_effect(move || match media_result()
|
||||
{
|
||||
Some(value) => match value
|
||||
{
|
||||
Ok(result) =>
|
||||
{
|
||||
if let Some(pagination) = result.pagination
|
||||
{
|
||||
use_effect(move || match media_result() {
|
||||
Some(value) => match value {
|
||||
Ok(result) => {
|
||||
if let Some(pagination) = result.pagination {
|
||||
let total_pages = pagination.total_pages;
|
||||
let total_items = pagination.total_items;
|
||||
props.max_page.set(total_pages.max(1));
|
||||
props.total_items.set(total_items.max(1));
|
||||
if let Some(handler) = props.on_page_loaded {
|
||||
handler.call(PaginationInfo {
|
||||
total_pages,
|
||||
total_items,
|
||||
});
|
||||
}
|
||||
}
|
||||
items.set(Some(result.items));
|
||||
error_display.set(rsx! {});
|
||||
@@ -70,8 +71,7 @@ pub fn MediaGrid(mut props: MediaGridProps) -> Element
|
||||
}
|
||||
}),
|
||||
},
|
||||
_ =>
|
||||
{}
|
||||
_ => {}
|
||||
});
|
||||
|
||||
rsx! {
|
||||
@@ -87,8 +87,7 @@ pub fn MediaGrid(mut props: MediaGridProps) -> Element
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn PlaceholderGrid(count: usize) -> Element
|
||||
{
|
||||
fn PlaceholderGrid(count: usize) -> Element {
|
||||
rsx! {
|
||||
div{
|
||||
class: "mediaGrid",
|
||||
@@ -100,12 +99,12 @@ fn PlaceholderGrid(count: usize) -> Element
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn MediaList(items: Vec<MediaModel>) -> Element
|
||||
{
|
||||
fn MediaList(items: Vec<MediaModel>) -> Element {
|
||||
rsx! {
|
||||
{items.iter().map(|itm| rsx!{
|
||||
{items.iter().enumerate().map(|(index, itm)| rsx!{
|
||||
MediaItem {
|
||||
item: itm.clone()
|
||||
item: itm.clone(),
|
||||
index
|
||||
}
|
||||
})}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_primitives::context_menu::{ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger};
|
||||
use dioxus_primitives::context_menu::{
|
||||
ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger,
|
||||
};
|
||||
use tonic::{Response, Status};
|
||||
use web_sys::window;
|
||||
|
||||
@@ -11,23 +13,28 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
pub struct MediaClassChangeEvent {
|
||||
pub index: usize,
|
||||
pub class: String,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone, Props)]
|
||||
pub struct MediaItemProps
|
||||
{
|
||||
pub struct MediaItemProps {
|
||||
pub item: MediaModel,
|
||||
pub index: usize,
|
||||
pub on_class_changed: Option<EventHandler<MediaClassChangeEvent>>,
|
||||
pub on_deleted: Option<EventHandler<usize>>,
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn MediaItem(props: MediaItemProps) -> Element
|
||||
{
|
||||
pub fn MediaItem(props: MediaItemProps) -> Element {
|
||||
let item = props.item;
|
||||
let mtype = item.media_type().as_str_name();
|
||||
let filename = item.file_name;
|
||||
let id = item.id.unwrap().value;
|
||||
let thumb = item.thumb_url;
|
||||
let class = item.class;
|
||||
let mut class_signal = use_signal(|| match class
|
||||
{
|
||||
let mut class_signal = use_signal(|| match class {
|
||||
1 => "blur",
|
||||
2 => "secret",
|
||||
_ => "",
|
||||
@@ -174,8 +181,7 @@ pub fn MediaItem(props: MediaItemProps) -> Element
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn MediaItemPlaceHolder() -> Element
|
||||
{
|
||||
pub fn MediaItemPlaceHolder() -> Element {
|
||||
return rsx! {
|
||||
div { class: "mediaItem placeholder",
|
||||
img { },
|
||||
@@ -190,8 +196,7 @@ pub fn MediaItemPlaceHolder() -> Element
|
||||
};
|
||||
}
|
||||
|
||||
async fn set_class(id: String, class: i32) -> Result<Response<()>, Status>
|
||||
{
|
||||
async fn set_class(id: String, class: i32) -> Result<Response<()>, Status> {
|
||||
let mut client = get_rpc_client();
|
||||
return client
|
||||
.set_media_class(SetMediaClassRequest {
|
||||
|
||||
@@ -2,8 +2,12 @@ use dioxus::prelude::*;
|
||||
use web_sys::window;
|
||||
|
||||
#[component]
|
||||
pub fn Pagination(page: Signal<i32>, max_page: Signal<i32>, item_count: Signal<i32>) -> Element
|
||||
{
|
||||
pub fn Pagination(
|
||||
page: Signal<i32>,
|
||||
max_page: Signal<i32>,
|
||||
item_count: Signal<i32>,
|
||||
on_page_change: EventHandler<i32>,
|
||||
) -> Element {
|
||||
let cur_page_val = page.cloned();
|
||||
let max_page_val = max_page.cloned();
|
||||
let item_count_val = item_count.cloned();
|
||||
@@ -12,16 +16,16 @@ pub fn Pagination(page: Signal<i32>, max_page: Signal<i32>, item_count: Signal<i
|
||||
class: "pagination",
|
||||
a {
|
||||
onclick: move|_| {
|
||||
page.set(1);
|
||||
on_page_change();
|
||||
on_page_change.call(1);
|
||||
scroll_document();
|
||||
},
|
||||
"First"
|
||||
}
|
||||
a {
|
||||
onclick: move|_| {
|
||||
let p = (cur_page_val - 1).max(1);
|
||||
page.set(p);
|
||||
on_page_change();
|
||||
on_page_change.call(p);
|
||||
scroll_document();
|
||||
},
|
||||
"Prev"
|
||||
}
|
||||
@@ -29,15 +33,15 @@ pub fn Pagination(page: Signal<i32>, max_page: Signal<i32>, item_count: Signal<i
|
||||
a {
|
||||
onclick: move|_| {
|
||||
let p = (cur_page_val + 1).min(max_page_val);
|
||||
page.set(p);
|
||||
on_page_change();
|
||||
on_page_change.call(p);
|
||||
scroll_document();
|
||||
},
|
||||
"Next"
|
||||
}
|
||||
a {
|
||||
onclick: move|_| {
|
||||
page.set(max_page_val);
|
||||
on_page_change();
|
||||
on_page_change.call(max_page_val);
|
||||
scroll_document();
|
||||
},
|
||||
"Last"
|
||||
}
|
||||
@@ -45,8 +49,7 @@ pub fn Pagination(page: Signal<i32>, max_page: Signal<i32>, item_count: Signal<i
|
||||
}
|
||||
}
|
||||
|
||||
fn on_page_change()
|
||||
{
|
||||
fn scroll_document() {
|
||||
let window = window().expect("Failed to get window");
|
||||
let document = window.document().expect("Failed to get document");
|
||||
document
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn Search(query: Signal<String>, page: Signal<i32>) -> Element {
|
||||
pub fn Search(query: String, oninput: Option<EventHandler<String>>) -> Element {
|
||||
rsx! {
|
||||
div { class: "searchBar",
|
||||
input {
|
||||
r#type: "search",
|
||||
placeholder: "Search Files",
|
||||
value: query,
|
||||
oninput: move |event| {query.set(event.value()); page.set(1);},
|
||||
oninput: move |event| {
|
||||
if let Some(handler) = oninput {
|
||||
handler.call(event.value());
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::components::{MediaGrid, Pagination, Search};
|
||||
use crate::components::{MediaGrid, Pagination, PaginationInfo, Search};
|
||||
use dioxus::prelude::*;
|
||||
|
||||
// #[component]
|
||||
@@ -19,19 +19,34 @@ use dioxus::prelude::*;
|
||||
// }
|
||||
|
||||
#[component]
|
||||
pub fn Home(page: Option<i32>, q: Option<String>) -> Element
|
||||
{
|
||||
let query = use_signal(|| q.unwrap_or("".to_string()));
|
||||
let page = use_signal(|| page.unwrap_or(1));
|
||||
pub fn Home(page: Option<i32>, q: Option<String>) -> Element {
|
||||
let mut query = use_signal(|| q.unwrap_or("".to_string()));
|
||||
let mut page = use_signal(|| page.unwrap_or(1));
|
||||
let page_size = use_signal::<i32>(|| 100);
|
||||
let max_page = use_signal(|| 1 as i32);
|
||||
let item_count = use_signal(|| 0 as i32);
|
||||
let mut max_page = use_signal(|| 1 as i32);
|
||||
let mut item_count = use_signal(|| 0 as i32);
|
||||
rsx! {
|
||||
div {
|
||||
class: "stickyTop",
|
||||
Search { query, page },
|
||||
Pagination { page, max_page, item_count },
|
||||
Search {
|
||||
query: query(),
|
||||
oninput: move |q| {
|
||||
query.set(q);
|
||||
page.set(1);
|
||||
}
|
||||
},
|
||||
Pagination {
|
||||
page, max_page, item_count,
|
||||
on_page_change: move |p|{
|
||||
page.set(p);
|
||||
}
|
||||
},
|
||||
}
|
||||
MediaGrid { query: query, page: page, max_page, total_items: item_count, page_size,
|
||||
on_page_loaded: move |p: PaginationInfo| {
|
||||
max_page.set(p.total_pages);
|
||||
item_count.set(p.total_items);
|
||||
}
|
||||
}
|
||||
MediaGrid { query: query, page: page, max_page, total_items: item_count, page_size }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
use crate::HOST;
|
||||
use crate::components::radio_group::{RadioGroup, RadioItem};
|
||||
use crate::rpc::aoba::SetMediaClassRequest;
|
||||
use crate::rpc::{
|
||||
aoba::{Id, MediaModel},
|
||||
get_rpc_client,
|
||||
@@ -8,26 +6,20 @@ use crate::rpc::{
|
||||
use dioxus::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn Media(id: String) -> Element
|
||||
{
|
||||
pub fn Media(id: String) -> Element {
|
||||
let media_result = use_resource(use_reactive!(|(id)| async move {
|
||||
let mut client = get_rpc_client();
|
||||
let result = client.get_media(Id { value: id.clone() }).await;
|
||||
if let Ok(item) = result
|
||||
{
|
||||
if let Ok(item) = result {
|
||||
let res = item.into_inner();
|
||||
return res.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}));
|
||||
|
||||
return match media_result.cloned().unwrap_or(None)
|
||||
{
|
||||
Some(media) =>
|
||||
{
|
||||
return match media_result.cloned().unwrap_or(None) {
|
||||
Some(media) => {
|
||||
return rsx! {MediaPage{media: media}};
|
||||
}
|
||||
None => rsx! {"Not Found"},
|
||||
@@ -35,12 +27,10 @@ pub fn Media(id: String) -> Element
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn MediaPage(media: MediaModel) -> Element
|
||||
{
|
||||
fn MediaPage(media: MediaModel) -> Element {
|
||||
let url = media.thumb_url;
|
||||
let id = media.id.expect("Media has no id").value.clone();
|
||||
let cur_class = use_signal(|| match media.class
|
||||
{
|
||||
let cur_class = use_signal(|| match media.class {
|
||||
0 => "Standard",
|
||||
1 => "NSFW",
|
||||
2 => "Secret",
|
||||
|
||||
Reference in New Issue
Block a user