Compare commits

..

8 Commits

Author SHA1 Message Date
Amatsugu ec0c6a3487 push history state
Build and Push Image / build-and-push (push) Successful in 5m12s
2026-04-10 01:15:51 -04:00
Amatsugu dd8faf8038 update 2026-04-08 22:45:29 -04:00
Amatsugu bd99b4beac update dx 2026-04-05 19:39:00 -04:00
Amatsugu 2517cd777f misc passkey prep 2026-04-05 19:20:02 -04:00
Amatsugu ea9ad2f8a7 rewrite components such that data always flows downwards 2026-04-05 17:03:19 -04:00
Amatsugu 44425723c6 media class on page change
Build and Push Image / build-and-push (push) Successful in 4m45s
2026-03-30 14:19:29 -04:00
Amatsugu 5caa08e145 moving list to it's own component 2026-03-29 22:31:56 -04:00
Amatsugu 44959589f8 async solve, now to fix list updating 2026-03-29 20:16:09 -04:00
15 changed files with 499 additions and 375 deletions
+112 -75
View File
@@ -79,7 +79,7 @@ dependencies = [
"futures-util",
"log",
"pin-project-lite",
"tungstenite",
"tungstenite 0.27.0",
]
[[package]]
@@ -509,9 +509,9 @@ dependencies = [
[[package]]
name = "dioxus"
version = "0.7.3"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92b583b48ac77158495e6678fe3a2b5954fc8866fc04cb9695dd146e88bc329d"
checksum = "a44c550c06b6785e16258ad620d5b559f5bbcbcc50e3c18c08aa6af2604a4c32"
dependencies = [
"dioxus-asset-resolver",
"dioxus-cli-config",
@@ -537,9 +537,9 @@ dependencies = [
[[package]]
name = "dioxus-asset-resolver"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0161af1d3cfc8ff31503ff1b7ee0068c97771fc38d0cc6566e23483142ddf4f"
checksum = "c240c4f092024b26e200ecd64723009173cf5bc2e5083c9feb778c077eb5741b"
dependencies = [
"dioxus-cli-config",
"http",
@@ -569,18 +569,18 @@ dependencies = [
[[package]]
name = "dioxus-cli-config"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccd67ab405e1915a47df9769cd5408545d1b559d5c01ce7a0f442caef520d1f3"
checksum = "86a13d42c5defcea333bdbae1dc5d64d078acd0fda1d8a1441c37e06be5146e3"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "dioxus-config-macro"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f040ec7c41aa5428283f56bb0670afba9631bfe3ffd885f4814807f12c8c9d91"
checksum = "1ba1d68a05a8a15293ba65d45c7a3263356f3eedf1a3e599440683f3eb014637"
dependencies = [
"proc-macro2",
"quote",
@@ -588,15 +588,15 @@ dependencies = [
[[package]]
name = "dioxus-config-macros"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10c41b47b55a433b61f7c12327c85ba650572bacbcc42c342ba2e87a57975264"
checksum = "f43f2d511d3c3c439a2fb7f863668b84caf8e0d2440cbfbcbb28521e26ba7f44"
[[package]]
name = "dioxus-core"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b389b0e3cc01c7da292ad9b884b088835fdd1671d45fbd2f737506152b22eef0"
checksum = "fb3dd61889e6a09daec93d44db86047fb8e6603beedcf9351b8528582254e075"
dependencies = [
"anyhow",
"const_format",
@@ -616,9 +616,9 @@ dependencies = [
[[package]]
name = "dioxus-core-macro"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a82d65f0024fc86f01911a16156d280eea583be5a82a3bed85e7e8e4194302d"
checksum = "8577c4d9a8cc23423c4d2137319044b03ab940e4b2790dd25f4f06601bd32d9a"
dependencies = [
"convert_case 0.8.0",
"dioxus-rsx",
@@ -629,15 +629,15 @@ dependencies = [
[[package]]
name = "dioxus-core-types"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfc4b8cdc440a55c17355542fc2089d97949bba674255d84cac77805e1db8c9f"
checksum = "b99d7d199aad72431b549759550002e7d72c8a257eba500dca9fbdb2122de103"
[[package]]
name = "dioxus-devtools"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcf89488bad8fb0f18b9086ee2db01f95f709801c10c68be42691a36378a0f2d"
checksum = "d27e7212436a581ce058d7554f1383916bd18a68ebd6015b0b4c2e9ecb0d5535"
dependencies = [
"dioxus-cli-config",
"dioxus-core",
@@ -648,14 +648,14 @@ dependencies = [
"subsecond",
"thiserror 2.0.18",
"tracing",
"tungstenite",
"tungstenite 0.28.0",
]
[[package]]
name = "dioxus-devtools-types"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e7381d9d7d0a0f66b9d5082d584853c3d53be21d34007073daca98ddf26fc4d"
checksum = "6aa24ed651b97e0b423270bf07a0f1b7dc0e0fa1f1dc26407cd2a118d6bf9de5"
dependencies = [
"dioxus-core",
"serde",
@@ -664,9 +664,9 @@ dependencies = [
[[package]]
name = "dioxus-document"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ba0aeeff26d9d06441f59fd8d7f4f76098ba30ca9728e047c94486161185ceb"
checksum = "24685cb51cc6227ea606c49dfe531836f362c49183d3007241afcd8827498401"
dependencies = [
"dioxus-core",
"dioxus-core-macro",
@@ -675,7 +675,7 @@ dependencies = [
"futures-channel",
"futures-util",
"generational-box",
"lazy-js-bundle 0.7.3",
"lazy-js-bundle 0.7.4",
"serde",
"serde_json",
"tracing",
@@ -683,9 +683,9 @@ dependencies = [
[[package]]
name = "dioxus-fullstack"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7db1f8b70338072ec408b48d09c96559cf071f87847465d8161294197504c498"
checksum = "5940c870751b6273a23b7c0e16d80039f45604d68d9b86c91e27b09edeabeb9e"
dependencies = [
"anyhow",
"async-stream",
@@ -729,7 +729,7 @@ dependencies = [
"thiserror 2.0.18",
"tokio-util",
"tracing",
"tungstenite",
"tungstenite 0.27.0",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
@@ -740,9 +740,9 @@ dependencies = [
[[package]]
name = "dioxus-fullstack-core"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda8b152e85121243741b9d5f2a3d8cb3c47a7b2299e902f98b6a7719915b0a2"
checksum = "28333274cfc8e5fe547ab04258c2511350c4930a07af9616d365dc4ba7b22d8f"
dependencies = [
"anyhow",
"axum-core",
@@ -768,9 +768,9 @@ dependencies = [
[[package]]
name = "dioxus-fullstack-macro"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "255104d4a4f278f1a8482fa30536c91d22260c561c954b753e72987df8d65b2e"
checksum = "53f7e5a9fa7f657aa519a07aced8b8936f3ae8a246d94855d497d8cce59b9533"
dependencies = [
"const_format",
"convert_case 0.8.0",
@@ -782,9 +782,9 @@ dependencies = [
[[package]]
name = "dioxus-history"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d00ba43bfe6e5ca226fef6128f240ca970bea73cac0462416188026360ccdcf"
checksum = "010b446322b3f9176476579fa61c7552f0430abbeec418cab543482da6ca4363"
dependencies = [
"dioxus-core",
"tracing",
@@ -792,9 +792,9 @@ dependencies = [
[[package]]
name = "dioxus-hooks"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dab2da4f038c33cb38caa37ffc3f5d6dfbc018f05da35b238210a533bb075823"
checksum = "09e7a6ba279050cc161e1215c6db0bd15915c9314ec2916d7b22c113a3039536"
dependencies = [
"dioxus-core",
"dioxus-signals",
@@ -808,9 +808,9 @@ dependencies = [
[[package]]
name = "dioxus-html"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eded5fa6d2e677b7442a93f4228bf3c0ad2597a8bd3292cae50c869d015f3a99"
checksum = "f0715e38cc6537aef5b79d0ddc1f4d7a56c2f4debe46b127eee24d8aa5dafd2d"
dependencies = [
"async-trait",
"bytes",
@@ -825,16 +825,16 @@ dependencies = [
"futures-util",
"generational-box",
"keyboard-types",
"lazy-js-bundle 0.7.3",
"lazy-js-bundle 0.7.4",
"rustversion",
"tracing",
]
[[package]]
name = "dioxus-html-internal-macro"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45462ab85fe059a36841508d40545109fd0e25855012d22583a61908eb5cd02a"
checksum = "ff6b7918b0908c8719a6165b4e3c362da4fd311fc7cb48720eddd8a45b2ddfc6"
dependencies = [
"convert_case 0.8.0",
"proc-macro2",
@@ -844,12 +844,12 @@ dependencies = [
[[package]]
name = "dioxus-interpreter-js"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a42a7f73ad32a5054bd8c1014f4ac78cca3b7f6889210ee2b57ea31b33b6d32f"
checksum = "a8ce1cf487007f90d0ec4ec87dff111d74ac04fca0918f9dcc4e80dc3b0531b2"
dependencies = [
"js-sys",
"lazy-js-bundle 0.7.3",
"lazy-js-bundle 0.7.4",
"rustc-hash 2.1.1",
"sledgehammer_bindgen",
"sledgehammer_utils",
@@ -860,9 +860,9 @@ dependencies = [
[[package]]
name = "dioxus-logger"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1eeab114cb009d9e6b85ea10639a18cfc54bb342f3b837770b004c4daeb89c2"
checksum = "d4742b16791a71eb4db2d0747f15c50b278b27369b3d93e5a4d6ec2570bcb9bc"
dependencies = [
"dioxus-cli-config",
"tracing",
@@ -887,9 +887,9 @@ dependencies = [
[[package]]
name = "dioxus-router"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d5b31f9e27231389bf5a117b7074d22d8c58358b484a2558e56fbab20e64ca4"
checksum = "ae50f5efa8d6f936c0c3bb85d7a55f6f19290f106290e331d1136d964e832fe6"
dependencies = [
"dioxus-cli-config",
"dioxus-core",
@@ -907,9 +907,9 @@ dependencies = [
[[package]]
name = "dioxus-router-macro"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "838b9b441a95da62b39cae4defd240b5ebb0ec9f2daea1126099e00a838dc86f"
checksum = "ae9beca02f6baca4b223256805536dc92e77a1541bb2331723100f66aae79332"
dependencies = [
"base16",
"digest",
@@ -922,9 +922,9 @@ dependencies = [
[[package]]
name = "dioxus-rsx"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53128858f0ccca9de54292a4d48409fda1df75fd5012c6243f664042f0225d68"
checksum = "344621f6dc435e76fbe272da09988d0118cf35cc2aa88ebb5ae7c1317a36e57c"
dependencies = [
"proc-macro2",
"proc-macro2-diagnostics",
@@ -947,9 +947,9 @@ dependencies = [
[[package]]
name = "dioxus-signals"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f48020bc23bc9766e7cce986c0fd6de9af0b8cbfd432652ec6b1094439c1ec6"
checksum = "409bf65d243443416650945f22cd6caf2a6bb13ae0347a50ec5852adb1961072"
dependencies = [
"dioxus-core",
"futures-channel",
@@ -963,9 +963,9 @@ dependencies = [
[[package]]
name = "dioxus-stores"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77aaa9ac56d781bb506cf3c0d23bea96b768064b89fe50d3b4d4659cc6bd8058"
checksum = "245ec4f84348e5be77451bd204181998b8bc0995b48ff3adb2db0e0ec430dab4"
dependencies = [
"dioxus-core",
"dioxus-signals",
@@ -975,9 +975,9 @@ dependencies = [
[[package]]
name = "dioxus-stores-macro"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b1a728622e7b63db45774f75e71504335dd4e6115b235bbcff272980499493a"
checksum = "dd9da8e9a1cc2d8bff387e0b99f09f2590b71f67d5d73ab343b2cc9d17990d92"
dependencies = [
"convert_case 0.8.0",
"proc-macro2",
@@ -987,9 +987,9 @@ dependencies = [
[[package]]
name = "dioxus-web"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b33fe739fed4e8143dac222a9153593f8e2451662ce8fc4c9d167a9d6ec0923"
checksum = "eac92ef863bc5333440021e8ec3e538a39598c9c960daeaab66ab10ba940b5e0"
dependencies = [
"dioxus-cli-config",
"dioxus-core",
@@ -1005,7 +1005,7 @@ dependencies = [
"generational-box",
"gloo-timers",
"js-sys",
"lazy-js-bundle 0.7.3",
"lazy-js-bundle 0.7.4",
"rustc-hash 2.1.1",
"send_wrapper",
"serde",
@@ -1234,9 +1234,9 @@ dependencies = [
[[package]]
name = "generational-box"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc4ed190b9de8e734d47a70be59b1e7588b9e8e0d0036e332f4c014e8aed1bc5"
checksum = "4ede46ff252793f9b6ef752c506ba8600c69d73cad2ef9bbf2e6dee85019a3bc"
dependencies = [
"parking_lot",
"tracing",
@@ -1694,9 +1694,9 @@ checksum = "e49596223b9d9d4947a14a25c142a6e7d8ab3f27eb3ade269d238bb8b5c267e2"
[[package]]
name = "lazy-js-bundle"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7b88b715ab1496c6e6b8f5e927be961c4235196121b6ae59bcb51077a21dd36"
checksum = "60d7adc10cb9440d17fa67e467febdfc98931338773d11bfee81809af54d0697"
[[package]]
name = "lazy_static"
@@ -1778,21 +1778,25 @@ dependencies = [
[[package]]
name = "manganis"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6cce7d688848bf9d034168513b9a2ffbfe5f61df2ff14ae15e6cfc866efdd344"
checksum = "492da8d77990281eabe6ded633e7b0cf805c5cf7a023a99abed8811edc872d6f"
dependencies = [
"const-serialize 0.7.2",
"const-serialize 0.8.0-alpha.0",
"jni",
"manganis-core",
"manganis-macro",
"ndk-context",
"objc2",
"thiserror 2.0.18",
]
[[package]]
name = "manganis-core"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84ce917b978268fe8a7db49e216343ec7c8f471f7e686feb70940d67293f19d4"
checksum = "a1b84cc2951f3b119702fab499b9b1aec3f454929c62feca55b895b82c628308"
dependencies = [
"const-serialize 0.7.2",
"const-serialize 0.8.0-alpha.0",
@@ -1804,9 +1808,9 @@ dependencies = [
[[package]]
name = "manganis-macro"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad513e990f7c0bca86aa68659a7a3dc4c705572ed4c22fd6af32ccf261334cc2"
checksum = "6d2e60d36758b201b6ebb8a31aff6b013e58924eeb6d3cbf19aea764f51d69e4"
dependencies = [
"dunce",
"macro-string",
@@ -1990,6 +1994,21 @@ dependencies = [
"libc",
]
[[package]]
name = "objc2"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f"
dependencies = [
"objc2-encode",
]
[[package]]
name = "objc2-encode"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
[[package]]
name = "once_cell"
version = "1.21.3"
@@ -2722,9 +2741,9 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
[[package]]
name = "subsecond"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8438668e545834d795d04c4335aafc332ce046106521a29f0a5c6501de34187c"
checksum = "5dbb9f2928b6654ccc28d4ddfef5213e97ed66afed4907774d049b376c62a838"
dependencies = [
"js-sys",
"libc",
@@ -2741,9 +2760,9 @@ dependencies = [
[[package]]
name = "subsecond-types"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e72f747606fc19fe81d6c59e491af93ed7dcbcb6aad9d1d18b05129914ec298"
checksum = "388bb28e6ddbee717745963b8932d9a6e24a5d3c93350655f733e938de04d81f"
dependencies = [
"serde",
]
@@ -2950,6 +2969,7 @@ dependencies = [
"futures-core",
"futures-io",
"futures-sink",
"futures-util",
"pin-project-lite",
"tokio",
]
@@ -3169,6 +3189,23 @@ dependencies = [
"utf-8",
]
[[package]]
name = "tungstenite"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442"
dependencies = [
"bytes",
"data-encoding",
"http",
"httparse",
"log",
"rand",
"sha1",
"thiserror 2.0.18",
"utf-8",
]
[[package]]
name = "typenum"
version = "1.19.0"
+2 -2
View File
@@ -6,7 +6,7 @@ edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
dioxus = { version = "0.7.3", features = ["router"] }
dioxus = { version = "0.7.5", features = ["router"] }
serde = "1.0.228"
serde_repr = "0.1.20"
tonic = { version = "*", default-features = false, features = [
@@ -15,7 +15,7 @@ tonic = { version = "*", default-features = false, features = [
] }
prost = "0.13"
tonic-web-wasm-client = "0.7"
web-sys = { version = "0.3.91", features = ["Storage", "Window"] }
web-sys = { version = "0.3.91", features = ["Storage", "Window", "Navigator", "CredentialsContainer", "CredentialCreationOptions"] }
dioxus-primitives = { git = "https://github.com/DioxusLabs/components", version = "0.0.1", default-features = false }
[build-dependencies]
@@ -7,4 +7,5 @@ div[role="menu"] {
width: auto;
outline: none;
width: max-content;
z-index: 10;
}
+2 -2
View File
@@ -113,11 +113,11 @@ $mediaItemSize: 300px;
&.placeholder {
}
&.nsfw img {
&.blur img {
filter: blur(20px);
transition: filter 0.25s ease-out;
}
&.nsfw:hover img {
&.blur:hover img {
filter: blur(0px);
}
}
+77 -56
View File
@@ -1,46 +1,46 @@
use dioxus::prelude::*;
use tonic::IntoRequest;
use crate::{
components::MediaItem,
rpc::{aoba::PageFilter, get_rpc_client},
components::{MediaItem, MediaItemPlaceHolder},
rpc::{
aoba::{MediaModel, PageFilter},
get_rpc_client,
},
};
#[derive(PartialEq, Clone, Props)]
pub struct MediaGridProps {
pub query: Option<String>,
pub query: Signal<String>,
pub max_page: Signal<i32>,
pub total_items: Signal<i32>,
#[props(default = Some(1))]
pub page: Option<i32>,
#[props(default = Some(100))]
pub page_size: Option<i32>,
pub page: Signal<i32>,
pub page_size: Signal<i32>,
pub on_page_loaded: Option<EventHandler<PaginationInfo>>,
}
impl IntoRequest<PageFilter> for MediaGridProps {
fn into_request(self) -> tonic::Request<PageFilter> {
let f: PageFilter = self.into();
f.into_request()
}
}
impl Into<PageFilter> for MediaGridProps {
fn into(self) -> PageFilter {
PageFilter {
page: self.page,
page_size: self.page_size,
query: self.query,
}
}
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! {}
});
let mut items = use_signal::<Option<Vec<MediaModel>>>(|| None);
let media_result = use_resource(use_reactive!(|(props)| async move {
items.set(None);
let mut client = get_rpc_client();
let result = client.list_media(props.into_request()).await;
let request = PageFilter {
page_size: Some(props.page_size.cloned()),
page: Some(props.page.cloned()),
query: Some(props.query.cloned()),
};
let result = client.list_media(request).await;
if let Ok(items) = result {
let res = items.into_inner();
return Ok(res);
} else {
let err = result.err().unwrap();
@@ -49,42 +49,63 @@ pub fn MediaGrid(mut props: MediaGridProps) -> Element {
}
}));
match media_result.cloned() {
use_effect(move || match media_result() {
Some(value) => match value {
Ok(result) => {
let pagination = result.pagination.unwrap();
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));
return rsx! {
div {
class: "mediaGrid",
// oncontextmenu: oncontext,
{result.items.iter().map(|itm| rsx!{
MediaItem {
item: itm.clone()
}
})},
}
};
}
Err(msg) => rsx! {
div {
class: "mediaGrid",
div {
"Failed to load results: {msg}"
if let Some(pagination) = result.pagination {
let total_pages = pagination.total_pages;
let total_items = pagination.total_items;
if let Some(handler) = props.on_page_loaded {
handler.call(PaginationInfo {
total_pages,
total_items,
});
}
}
},
},
None => rsx! {
div{
class: "mediaGrid",
{(0..50).map(|_| rsx!{
MediaItem { }
})}
items.set(Some(result.items));
error_display.set(rsx! {});
}
Err(msg) => error_display.set(rsx! {
div{
"Failed to load results: {msg}"
}
}),
},
_ => {}
});
rsx! {
div {
class: "mediaGrid",
{error_display}
{match items(){
Some(itms) => rsx!{MediaList { items: itms }},
None => rsx!{PlaceholderGrid { count: props.page_size.cloned() as usize }}
}}
}
}
}
#[component]
fn PlaceholderGrid(count: usize) -> Element {
rsx! {
div{
class: "mediaGrid",
{(0..count).map(|_| rsx!{
MediaItemPlaceHolder { }
})}
}
}
}
#[component]
fn MediaList(items: Vec<MediaModel>) -> Element {
rsx! {
{items.iter().enumerate().map(|(index, itm)| rsx!{
MediaItem {
item: itm.clone(),
index
}
})}
}
}
+170 -156
View File
@@ -1,188 +1,202 @@
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;
use crate::{
HOST,
route::Route,
rpc::{
aoba::{Id, MediaClass, MediaModel, SetMediaClassRequest},
aoba::{Id, MediaModel, SetMediaClassRequest},
get_rpc_client,
},
};
pub struct MediaClassChangeEvent {
pub index: usize,
pub class: String,
}
#[derive(PartialEq, Clone, Props)]
pub struct MediaItemProps
{
pub item: Option<MediaModel>,
// pub oncontextmenu: Option<EventHandler<Event<MouseData>>>,
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
{
let mut class_signal = use_signal(|| "");
if let Some(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 url = item.media_url;
let download = format!("{HOST}{url}");
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 {
1 => "blur",
2 => "secret",
_ => "",
});
let url = item.media_url;
let download = format!("{HOST}{url}");
match class
{
1 => class_signal.set("nsfw"),
2 => class_signal.set("secret"),
_ => class_signal.set(""),
};
// class_signal.set(match class
// {
// 1 => "blur",
// 2 => "secret",
// _ => "",
// });
return rsx! {
ContextMenu{
ContextMenuTrigger{
a {
class: "mediaItem {class_signal()}",
href: "{HOST}{url}",
target: "_blank",
"data-id" : id.clone(),
img { src: "{HOST}{thumb}" }
span { class: "info",
span { class: "name", "{filename}" }
span { class: "details",
span { "{mtype}" }
span { "{item.view_count}" }
}
return rsx! {
ContextMenu{
ContextMenuTrigger{
a {
class: "mediaItem {class_signal()}",
href: "{HOST}{url}",
target: "_blank",
"data-id" : id.clone(),
img { src: "{HOST}{thumb}" }
span { class: "info",
span { class: "name", "{filename}" }
span { class: "details",
span { "{mtype}" }
span { "{item.view_count}" }
}
},
}
},
ContextMenuContent{
ContextMenuItem {
index: 0 as usize,
value: id.clone(),
on_select: move |id: String|{
window().expect("Failed to get window")
.location().set_href(&format!("/media/{}", id))
.expect("Failed to open Url");
},
div{
class: "contextItem",
div{
class: "label",
"Details"
}
}
},
ContextMenuContent{
ContextMenuItem {
index: 0 as usize,
value: id.clone(),
on_select: move |id: String|{
window().expect("Failed to get window")
.location().set_href(&format!("/media/{}", id))
.expect("Failed to open Url");
},
ContextMenuItem {
index: 1 as usize,
value: "{download}",
on_select: move |url: String|{
window().expect("Failed to get window").open_with_url_and_target(&url, "_blank").expect("Failed to open url");
},
div{
class: "contextItem",
div{
class: "contextItem",
div{
class: "label",
"Download"
}
}
},
{
if class != 0 {
rsx!{ContextMenuItem {
index: 2 as usize,
value: "{id}",
on_select: async |id: String|{
_ = set_class(id, 0).await;
},
div{
class: "contextItem",
div{
class: "label",
"Mark Standard"
}
}
}}
}else{
rsx!{}
class: "label",
"Details"
}
}
{
if class != 1 {
rsx!{ContextMenuItem {
index: 2 as usize,
value: "{id}",
on_select: async |id: String|{
_ = set_class(id, 1).await;
},
div{
class: "contextItem",
div{
class: "label",
"Mark NSFW"
}
}
}}
}else{
rsx!{}
}
}
{
if class != 1 {
rsx!{ContextMenuItem {
index: 2 as usize,
value: "{id}",
on_select: async |id: String|{
_ = set_class(id, 2).await;
},
div{
class: "contextItem",
div{
class: "label",
"Mark Secret"
}
}
}}
}else{
rsx!{}
}
}
ContextMenuItem {
index: 2 as usize,
value: "",
div{
class: "contextItem",
div{
class: "label",
"Delete"
}
}
},
ContextMenuItem {
index: 1 as usize,
value: "{download}",
on_select: move |url: String|{
window().expect("Failed to get window").open_with_url_and_target(&url, "_blank").expect("Failed to open url");
},
div{
class: "contextItem",
div{
class: "label",
"Download"
}
}
},
{
if class_signal() != "" {
rsx!{ContextMenuItem {
index: 2 as usize,
value: "{id}",
on_select: move |id: String|{
spawn(async move {
if let Ok(_) = set_class(id, 0).await{
class_signal.set("");
}
});
},
div{
class: "contextItem",
div{
class: "label",
"Mark Standard"
}
}
}}
}else{rsx!{}}
}
}
};
}
else
{
return rsx! {
div { class: "mediaItem placeholder",
img { },
span { class: "info",
span { class: "name" }
span { class: "details",
span { }
span { }
}
{
if class_signal() != "blur" {
rsx!{ContextMenuItem {
index: 2 as usize,
value: "{id}",
on_select: move |id: String|{
spawn(async move {
if let Ok(_) = set_class(id, 1).await{
class_signal.set("blur");
}
});
},
div{
class: "contextItem",
div{
class: "label",
"Mark NSFW"
}
}
}}
}else{rsx!{}}
}
{
if class_signal() != "secret" {
rsx!{ContextMenuItem {
index: 2 as usize,
value: "{id}",
on_select: move |id: String|{
spawn(async move {
if let Ok(_) = set_class(id, 2).await{
class_signal.set("secret");
}
});
},
div{
class: "contextItem",
div{
class: "label",
"Mark Secret"
}
}
}}
}else{rsx!{}}
}
ContextMenuItem {
index: 2 as usize,
value: "",
div{
class: "contextItem",
div{
class: "label",
"Delete"
}
}
},
}
};
}
}
};
}
async fn set_class(id: String, class: i32) -> Result<Response<()>, Status>
{
#[component]
pub fn MediaItemPlaceHolder() -> Element {
return rsx! {
div { class: "mediaItem placeholder",
img { },
span { class: "info",
span { class: "name" }
span { class: "details",
span { }
span { }
}
}
}
};
}
async fn set_class(id: String, class: i32) -> Result<Response<()>, Status> {
let mut client = get_rpc_client();
return client
.set_media_class(SetMediaClassRequest {
+11 -6
View File
@@ -6,7 +6,8 @@ const NAV_CSS: Asset = asset!("/assets/style/nav.scss");
const NAV_ICON: Asset = asset!("/assets/favicon.ico");
#[component]
pub fn Navbar() -> Element {
pub fn Navbar() -> Element
{
rsx! {
document::Link { rel: "stylesheet", href: NAV_CSS }
nav {
@@ -19,17 +20,19 @@ pub fn Navbar() -> Element {
}
#[component]
pub fn MainNaviagation() -> Element {
pub fn MainNaviagation() -> Element
{
rsx! {
div { class: "mainNav",
Link { class: "navItem", to: Route::Home { }, "Home" }
Link { class: "navItem", to: Route::Home { page: None, q: None }, "Home" }
Link { class: "navItem", to: Route::Settings {}, "Settings" }
}
}
}
#[component]
pub fn Branding() -> Element {
pub fn Branding() -> Element
{
rsx! {
div { class: "branding",
img { src: NAV_ICON, alt: "Aoba" }
@@ -38,14 +41,16 @@ pub fn Branding() -> Element {
}
#[component]
pub fn Widgets() -> Element {
pub fn Widgets() -> Element
{
rsx! {
div { class: "widgets" }
}
}
#[component]
pub fn Utils() -> Element {
pub fn Utils() -> Element
{
let mut auth_context = use_context::<AuthContext>();
let version = APP_VERSION;
rsx! {
+15 -12
View File
@@ -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
+17 -8
View File
@@ -1,27 +1,36 @@
use dioxus::prelude::*;
use web_sys::{CredentialCreationOptions, window};
use crate::components::basic::Button;
#[component]
pub fn PasskeyRegistrationButton() -> Element
{
pub fn PasskeyRegistrationButton() -> Element {
rsx! {
Button{
text: "Register Passkey",
onclick: move |e| {
onclick: move |_| {
start_passkey_registration();
}
}
}
}
fn start_passkey_registration() {}
fn start_passkey_registration() {
create_credential();
}
fn create_credential() {}
fn create_credential() {
let credentials = window()
.expect("Failed to get window")
.navigator()
.credentials();
let opts = CredentialCreationOptions::new();
let _result = credentials.create_with_options(&opts);
}
#[component]
pub fn PasskeyLoginButton() -> Element
{
pub fn PasskeyLoginButton() -> Element {
rsx! {
Button{
text: "Login with Passkey"
+12 -2
View File
@@ -1,14 +1,24 @@
use dioxus::prelude::*;
#[component]
pub fn Search(query: Signal<String>, page: Signal<i32>) -> Element {
pub fn Search(query: String, oninput: Option<EventHandler<String>>, onchange: 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());
}
},
onchange: move |event|{
if let Some(handler) = onchange {
handler.call(event.value());
}
}
}
}
}
+13 -4
View File
@@ -8,7 +8,7 @@ pub mod rpc;
pub mod views;
use contexts::AuthContext;
use dioxus::prelude::*;
use dioxus::{prelude::*, router::RouterConfig};
use route::Route;
#[cfg(debug_assertions)]
@@ -34,7 +34,6 @@ fn main()
fn App() -> Element
{
use_context_provider(|| AuthContext::new());
// use_context_provider(|| ContextMenuRenderer::default());
rsx! {
document::Link { rel: "icon", href: FAVICON }
document::Link { rel: "preconnect", href: "https://fonts.googleapis.com" }
@@ -46,7 +45,17 @@ fn App() -> Element
rel: "stylesheet",
href: "https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100..900;1,100..900&display=swap",
}
Router::<Route> { }
Router::<Route> { config: || RouterConfig::default()
.on_update(|state|{
match state.current() {
Route::Home {page, q} => {
info!("Page {}", page.unwrap_or(1));
return None;
// return Some(NavigationTarget::Internal(Route::Home { page, q }))
},
_ => None
}
})
}
}
}
+4 -4
View File
@@ -1,6 +1,6 @@
use crate::{
layouts::MainLayout,
views::{Home, HomePaged, Media, Settings},
views::{Home, Media, Settings},
};
use dioxus::prelude::*;
@@ -9,10 +9,10 @@ use dioxus::prelude::*;
pub enum Route {
#[layout(MainLayout)]
#[route("/")]
Home { },
#[route("/?:page&:q")]
HomePaged { page: i32, q: String },
Home { page: Option<i32>, q: Option<String> },
// #[route("/")]
// Home { },
#[route("/media/:id")]
Media { id: String },
#[route("/settings")]
+51 -27
View File
@@ -1,36 +1,60 @@
use crate::components::{MediaGrid, Pagination, Search};
use dioxus::prelude::*;
use crate::{
components::{MediaGrid, Pagination, PaginationInfo, Search},
route::Route,
};
use dioxus::{prelude::*, router::RouterConfig};
// #[component]
// pub fn Home() -> Element
// {
// let query = use_signal(|| "".to_string());
// let page = use_signal(|| 1 as i32);
// let max_page = use_signal(|| 1 as i32);
// let item_count = use_signal(|| 0 as i32);
// rsx! {
// div {
// class: "stickyTop",
// Search { query, page },
// Pagination { page, max_page, item_count },
// }
// MediaGrid { query: query.cloned(), page: page.cloned(), max_page, total_items: item_count }
// }
// }
#[component]
pub fn Home() -> Element
pub fn Home(page: Option<i32>, q: Option<String>) -> Element
{
let query = use_signal(|| "".to_string());
let page = use_signal(|| 1 as i32);
let max_page = use_signal(|| 1 as i32);
let item_count = use_signal(|| 0 as i32);
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 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);
},
onchange: move |_|{
router().push(format!("/?page={}&q={}", page(), query()));
}
},
Pagination {
page, max_page, item_count,
on_page_change: move |p|{
page.set(p);
router().push(format!("/?page={}&q={}", page(), query()));
}
},
}
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.cloned(), page: page.cloned(), max_page, total_items: item_count }
}
}
#[component]
pub fn HomePaged(page: i32, q: String) -> Element
{
let query = use_signal(|| q);
let page = use_signal(|| page);
let max_page = use_signal(|| 1 as i32);
let item_count = use_signal(|| 0 as i32);
rsx! {
div {
class: "stickyTop",
Search { query, page },
Pagination { page, max_page, item_count },
}
MediaGrid { query: query.cloned(), page: page.cloned(), max_page, total_items: item_count }
}
}
+2 -1
View File
@@ -2,7 +2,7 @@ use dioxus::prelude::*;
use tonic::IntoRequest;
use crate::{
components::{basic::Input, Notif, NotifType},
components::{Notif, NotifType, PasskeyLoginButton, basic::Input},
contexts::AuthContext,
rpc::{aoba::Credentials, get_auth_rpc_client},
};
@@ -72,6 +72,7 @@ pub fn Login() -> Element {
required: true,
}
button { onclick: login, "Login!" }
PasskeyLoginButton {}
}
}
}
+10 -20
View File
@@ -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,20 +27,18 @@ 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 = match media.class
{
// let id = media.id.expect("Media has no id").value.clone();
let cur_class = use_signal(|| match media.class {
0 => "Standard",
1 => "NSFW",
2 => "Secret",
_ => "Unkown",
};
});
rsx! {
img { src: "{HOST}{url}", }
label { "Media Class: {cur_class}" }
label { "Media Class: {cur_class()}" }
}
}